On 26 July 2005 14:15, Einar Karttunen wrote:

> "Simon Marlow" <[EMAIL PROTECTED]> 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
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to