simonmar at microsoft.com
Tue Oct 22 05:07:36 EDT 2002
> I also need the touchForeignPtr trick in much of my code. we need to
> come up with a replacement if we dont have haskell
> finalizers. here are my canidate suggestions:
> * add a subset of Weak pointers (or some subset of their
> to the FFI spec. just get rid of the finalizer capability
> (for obvious
> reasons) and the Weak pointers work just as well, and it
> might have uses
> - or -
> * add addForeignDependency :: ForeignPtr a -> ForeignPtr b -> IO ()
> (which on ghc is trivially implemented as
> 'addForeignDependency a b = mkWeak a b Nothing >> return ()')
I'm not sure this does what you want. It prevents b's finalizer from
being started before a's, but there's nothing that makes them actually
run in the desired order. The two finalizers can also be started at the
same time, if both a and b are found to be unreachable in a given GC.
It *may* be possible to change the semantics of Weak pointers in GHC so
that a finalizer is considered a strong root, with the finalizer being
passed the key as an argument when it runs. I haven't fully thought
through the consequences of this though. In any case, doing it this way
isn't ideal either, because it would take multiple full GCs to work out
all the dependencies.
Maybe you want to synchronise between finalizers using MVars, but of
course that only works on GHC, and it might not always be convenient.
m <- newEmptyMVar
addForeignPtrFinalizer a (putMVar m ())
b <- newForeignPtr p (takeMVar m >> ...)
enforces a strict ordering between 'a' and 'b'.
A simpler way in some cases is to use addForeignPtrFinalizer directly.
If you know that you're creating an object 'a' which should be finalized
after some other object 'b', then instead of placing a finalizer on
object 'a', place it on object 'b' using addForeignPtrFinalizer. We're
going to guarantee ordering between finalizers registered using
addForeignPtrFinalizer. This doesn't work if 'a' is possibly referenced
from elsewhere, of course.
More information about the FFI