The way to use finalizers is in conjunction with an exception handler that provides an absolute guarantee that the resource will be reclaimed on exit.

Note that Java doesn't guarantee to run finalizers on exit either:

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html#runFinalizersOnExit(boolean)

Although in Java it's for different reasons.

We can give more guarantees to C finalizers because they're much simpler:

  - a C finalizer can't synchronise with other Haskell code,
    including Haskell finalizers.
  - we don't have to worry about whether a C finalizer refers to
    other finalizable objects
  - we don't mind if a C finalizer blocks: that's the programmer's problem.

Cheers,
        Simon

Lennart Augustsson wrote:
From a theoretical perspective I'd say that they are completely
useless, because there's no guarantee that the finalizer will ever
run.  You might as well throw them away as use them and there would be
the same guarantees.
From a practical perspective they are useful, because they probably
run.  So you can use them to reclaim most resources.

I realize that the situation is complicated in ghc, but it also means
that to get finalizers with guarantees you have to implement them
yourself rather than relying on the ghc runtime system, which can be
quite tedious.

  -- Lennart

On Mon, Dec 8, 2008 at 9:59 AM, Simon Marlow <[EMAIL PROTECTED]> wrote:
Lennart Augustsson wrote:
Finalizers without guarantees, like what ghc implements, are totally
useless. Since there is no guarantee that the finalizer will ever run
attaching one is a no-op. It has bitten me several times. I wish ghc
implemented finalizers according to the ffi spec.
We do plan to do that (I'm sure you're aware of bug #1364), however I'm sure
you're also aware that GHC's finalizers are more general than the FFI spec
requires in that finalizers can be Haskell computations, and it is this that
leads to the lack of guarantees.  Implementing the FFI-style finalizers
requires us to treat C finalizers as a special case, rather than
implementing them as foreign calls from Haskell finalizers, which is a bit
of a pain.

I disagree that finalizers are completely useless.  They're just not useful
for some of the things you might like them to be useful for, like guaranteed
resource reclamation.

  -- Lennart (iPhone)
Cheers,
       Simon (MS natural keyboard and 28" LCD screen)

On Dec 7, 2008, at 13:12, "Claus Reinke" <[EMAIL PROTECTED]> wrote:

Adding finalizers to arbitrary objects was useful for the memo table
application we had in mind when weak pointers were introduced, but for all
the other applications I've come across since then, we really want to add
finalizers to objects whose lifetimes are under programmer control.  Notice
how ForeignPtrs attach the finalizer carefully to the MutVar# inside the
ForeignPtr, not the ForeignPtr itself.
One application that was effectively killed by GHC's approach to
finalizers was GHood (I lost interest when it became apparent that
GHC was moving away from giving any kinds of guarantees about
finalizers). The idea was that, just as unsafePerformIO gives us a
way to instrument the evaluator, so finalizers could have given us a way
to instrument garbage collection. Then GHood could not only
have shown when which parts of which structure are first observed
(how and when structures get unfolded) but also (roughly) when which
parts of which structure become unreachable (how and when
structures disappear again). That would have made a very nice tool.

But it would have needed finalizers on arbitrary objects that are
actually guaranteed to be run, preferably promptly, but not early. Given
the application, I would have considered wrapping/annotating those objects
in some transparent way, not visible to the original program, but forcing
the memory manager to keep track of that object even if that means worse
code. Only that there are no guarantees whatsoever on these finalizers
anymore (there were some back then, but it emerged that they weren't backed
up by the implementation).
Which also hurts other, table-like, applications: I have an application
where I need to keep track of synchronous communication channels, basically:
advance each live channel at every step. Now, I would like to attach
finalizers to the channels, so that when there are no more threads having
references to a channel, the channel gets removed
from the tracking table. But without finalizer guarantees, there is no
guarantee that the table will not simply keep accumulating more and
more of those dynamically created channels..

I, for one, would like to have good support for "adding finalizers to
arbitrary objects with useful run guarantees". Actually, it is a bit hard
to understand what finalizers without any guarantees (System.Mem.Weak)
are supposed to achieve?

Claus

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Reply via email to