RE: [Haskell-cafe] ForeignPtrs with liveness dependencies

On 25 July 2005 14:44, Einar Karttunen wrote:
What is the correct way to express liveness dependencies for ForeignPtrs? I am wrapping a C library and need a way to keep ForeignPtrs alive until the finalizer for an another ForeignPtr has been executed.
Basically I have two types, ForeignPtr A and ForeignPtr B and a function associate :: ForeignPtr A -> ForeignPtr B -> IO (). I want to keep all of the ForeignPtr Bs associated with a given ForeignPtr A alive until its finalizer has been run. The relationship is M:N - each ForeignPtr A may be associated with multiple ForeignPtr B and each ForeignPtr B may be associated with multiple ForeignPtr A.
GHC documentation tells that touchForeignPtr is not enough as it makes no guarantees about when the finalizers are run. If it helps the finalizers are C functions which neither block nor perform callbacks into Haskell.
You might be able to find more information on this in the mailing list archives. It's true that touchForeignPtr isn't enough to enforce an ordering on the running of finalizers, but it *can* be used to express a liveness relationship between one ForeignPtr and another (ForeignPtr A is alive if ForeignPtr B is alive). This should be enough if you're dealing with pointer relationships between memory objects, for example, where it doesn't matter which one gets freed first when they're both unreferenced. If you really do need ordering, maybe it would be possible to use reference counting in your case? Cheers, Simon

"Simon Marlow"
You might be able to find more information on this in the mailing list archives. It's true that touchForeignPtr isn't enough to enforce an ordering on the running of finalizers, but it *can* be used to express a liveness relationship between one ForeignPtr and another (ForeignPtr A is alive if ForeignPtr B is alive). This should be enough if you're dealing with pointer relationships between memory objects, for example, where it doesn't matter which one gets freed first when they're both unreferenced.
The order of the cleanup functions is significant in this case, so that does not unfortunately help.
If you really do need ordering, maybe it would be possible to use reference counting in your case?
I ended up using the following design, which seems to work fine: data Foo = Foo (ForeignPtr Foo) (IORef [IO ()]) Each ForeignPtr Foo has a single finalizer which first calls the C-side cleanup function for Foo and then executes all the IO-actions inside the IORef. Now the association becomes associate (Foo _ ref) bar = atomicModifyIORef ref (\lst -> (touchForeignPtr bar : lst, ())) - Einar Karttunen
participants (2)
-
Einar Karttunen
-
Simon Marlow