
On 26 July 2005 14:15, Einar Karttunen wrote:
"Simon Marlow"
writes: Now the association becomes associate (Foo _ ref) bar = atomicModifyIORef ref (\lst -> (touchForeignPtr bar : lst, ()))
Isn't that equivalent to using addForeignPtrFinalizer? I don't think this fixes anything: the finalizer for bar can still run before the finalizer for foo.
foo has a single finalizer which is defined like:
fooFinalizer cfoo ref = do cdeleteFoo cfoo vs <- readIORef ref mapM_ (\c -> c) vs
the last line is equivalent to "sequence_ vs", FWIW.
and foo is created like
createFoo ptr = do ref <- newIORef [] fp <- newForeigPtr ptr (fooFinalizer ptr ref) return (Foo fp ref)
As the finalizer of foo references the IORef which contains the list of actions containing the "touchForeignPtr bar" the finalizer of foo is run first. The finalizer to bar should be able to run only when the touchForeignPtr has been executed in the mapM_ which only happens after foo has been cleaned up - if I understand things correctly.
No, unfortunately not. You have foo's finalizer which refers to bar via a touchForeignPtr. If both foo and bar are unreachable (references from finalizers don't count), then both foo and bar's finalizers will be started together, and may run in any order. So touchForeignPtr does only one thing: it expresses the precise relationship "bar is alive if foo is alive". If both are not alive, then both finalizers can run, in any order. I realise this is very subtle. By all means suggest improvements to the docs. Cheers, Simon