[Alastair Reid <alastair@reid-consulting-uk.ltd.uk>] Re: cvs commit: haskell-report/ffi finalizers.txt

Simon Marlow simonmar at microsoft.com
Tue Oct 15 05:37:42 EDT 2002

> Things you mights add are:
> eg(1) in composite finalizers:
>   This would be handled just fine by C finalizers if
>   addForeignPtrFinalizer guaranteed to execute finalizers in reverse
>   order of their addition.  This seems like a reasonable thing to
>   specify since addForeignPtrFinalizer is much less useful if this
>   guarantee doesn't hold and because it is easy to implement.

Ok, I've added that.

> eg(2):
>   isn't too convincing since you could easily write the same thing in
>   C.  I expect you could find something more convincing with a little
>   effort.

Please feel free to suggest something - I can't off the top of my head
think of anything that you couldn't also do in C, but then that's not
the point of the exercise.  The point is that it's rather more
convenient in Haskell.

> Communicating with a foreign runtime/garbage collector:
>   I remain unconvinced that this example has been worked out in detail
>   and believe that if it were worked out in detail we'd either find
>   that all George needs is to be able to call into the _runtime
>   system_ during a Java GC (doesn't require Haskell finalizers) or
>   that he requires a much more intimate relationship with Haskell's GC
>   (requires a lot more than the FFI provides).

I'll let others comment on this.

> Other cleanups:
> 1)
>   Unsavouriness of exporting &free seems like a judgement an impartial
>   witness would avoid.

Well, at some point we have to make judgements about what is a good
design.  I assumed this was an uncontested point - is it?
> Manipulating mutable state and communicating with other threads:
>   I don't see how adding concurrency strengthens the argument for
>   Haskell finalizers.  

Well, when you add concurrency Haskell finalizers become much more
useful because you can manipulate Haskell-side mutable state using them.
Without concurrency (or perhaps a blockFinalizers primitive), you can't.

We're taking slightly different viewpoints here: you're saying that we
must have mutable state and Haskell finalizers are useless without it,
whereas I'm saying that Haskall finalizers are still useful even if you
can't manipulate Haskell state inside one.  Essentially this comes down
to a matter of opinion, and we won't reach a conclusion without more

>   Adding mutable Haskell state doesn't seem to strengthen it either.
>   Indeed, I assume the existence of mutable Haskell state in arguing
>   against Haskell finalizers.

And that's exactly the standpoint I disagree with.  The document goes to
some lengths to consider the utility of Haskell finalizers in the
absence of mutable state.

> Arguments against:
>   Adding Haskell finalizers drags in many concurrency issues for
>   programmers:
>   - potential to introduce race conditions
>   - potential for deadlock

These points are made later in the document, and the "arguments against"
section forward-references them.

>   As with most concurrency issues, the resulting bugs are easy to
>   introduce, hard to reproduce and hard to track down.

If you use IORefs, then you have the same concurrency bugs in GHC as you
would in Hugs, so I don't believe that argument.  Most programmers will
understand the concept of a race condition.  So then it remains to
explain to them that if they want to use IORefs from finalizers, they
must use GHC and MVars instead.

>   Adding Haskell finalizers has a high implementation burden for those
>   who have not already implemented preemptive concurrency - greatly
>   increasing the complexity of implementing Haskell + FFI (+ mutable
>   state, of course - but that is a trivial thing to implement).

I think we've already demonstrated that the implementation burden isn't
anything like as bad as we thought it was.

>   The complexities introduced seem out of line with the problem being
>   solved.
> Implementations/Hugs:
>   You say: "There is some doubt over whether the patch is 
> safe as it stands:"
>   I say: "There is no doubt that the patch is unsafe as it stands:"

Ok, I'll change the wording.  How about checking the safety conditions?

> Implications of allowing Haskell finalizers in non-concurrent 
> systems/Mutable state:
>   You omit my argument that, since the primary goal of finalizers is
>   to modify mutable state, Haskell finalizers which do not modify
>   mutable Haskell state will be of little use.

Ok, so your opinion is that Haskell finalizers are useless unless you
can modify mutable Haskell state.  The document gives some rationale as
to why Haskell finalizers might still be useful, but again this comes
down to a matter of opinion.

I've added the following point to the "arguments against" section:

    3. If finalizers cannot modify mutable Haskell state (see later),
       then they are significantly less uesful in a system that
       supports mutable Haskell state, and we might prefer to avoid
       the complexity on the grounds that the payoff isn't worth it.

>   All they will be able
>   to do is lookup objects in immutable Haskell state and invoke C
>   finalizers to do their work - a significant limitation.  (In
>   fairness, I will say that useful information might be stored in the
>   finalizer closure so actions like looking up an object in a binary
>   tree of all live objects (say) might be avoidable with a little
>   effort.)

These points are already made in the document.

> Interaction with co-operative concurrency:
>   You say (though your final paragraph suggest you don't 
> insist on it):
>     One might argue that since you have to do this anyway in Hugs -
>     another thread can only get control at an explicit yield point -
>     doing it for finalizers too isn't so bad.
>   I say:
>     There is a world of difference between being delayed for an
>     unknown, finite amount of time and being delayed for an unbounded,
>     potentially infinite amount of time.  (This is why vague concepts
>     like 'fairness' are useful in reasoning about scheduling - you
>     don't know when you will run but you know you will get a shot
>     sometime.)

I think these are completely unrelated points.  In fact, I agree with
your statement, but it doesn't describe the behaviour of finalizers:
currently there's no guarantee that finalizers are run in a finite
amount of time.

There is a qualitative difference here, but we have to be very careful
about how it is described.  One thing you can say is that a program
written in a certain way in a co-operatively scheduled system can force
finalizers to be delayed until the end of the program, whereas the same
should not be true of a pre-emptively scheduled system.

> Proposals:
> Add:
>   4) No change to the spec for the time being, while we evaluate the
>      need and cost of implementing Haskell finalizers in a range of
>      implementations.  Note that upgrading from C finalizers to
>      Haskell finalizers would only require that we say that finalizers
>      are invoked with the equivalent of a 'safe' ffi call instead of
>      an 'unsafe' ffi call and, no doubt, the addition of some
>      convenience functions.
> I don't think this is the same as (3)



More information about the FFI mailing list