On Wed, Sep 25, 2002 at 09:33:04AM +0100, Ross Paterson wrote:
If the struct were allocated with mallocForeignPtr, you need another C call to use as the finalizer for that, say hs_f_free().
Sorry, that's wrong: If the struct were allocated with mallocForeignPtr, you're stuck. You've no choice but to use addForeignPtrFinalizer, except that you can't because the order of finalizers is unspecified.
I can guarantee in GHC that if you add a finalizer to a ForeignPtr made with mallocForeignPtr, then it will run before the memory is released. However, to provide a general ordering property on finalizers would be quite awkward in GHC - I just can't think of an easy way to do it. One way is to add a unique tag to each weak pointer object and sort them before running the finalizers, but also the finalizers have to run sequentially somehow (currently there's a hack to run some finalizers in the same thread, but it's nothing more than a performance hack; I don't think I could use it to provide reliable ordering). I tell you what, I'll implement finalizer ordering if you guys implement full Haskell finalizers :-) Cheers, Simon
On Wed, Sep 25, 2002 at 10:25:31AM +0100, Simon Marlow wrote:
If the struct was allocated with mallocForeignPtr, you're stuck. You've no choice but to use addForeignPtrFinalizer, except that you can't because the order of finalizers is unspecified.
I can guarantee in GHC that if you add a finalizer to a ForeignPtr made with mallocForeignPtr, then it will run before the memory is released.
Clunky, but if the spec said that it might be just enough. Hugs and Nhc could implement it by running the finalizers in the reverse order. (Neither of them implement addForeignPtrFinalizer yet, but they both store the finalizer in a ForeignPtr structure, and could store a list of finalizers instead.)
I tell you what, I'll implement finalizer ordering if you guys implement full Haskell finalizers :-)
How about providing newForeignPtr as specified? (Or are you still hoping?)
However, to provide a general ordering property on finalizers would be quite awkward in GHC - I just can't think of an easy way to do it. [Awkward ways deleted]
If I understand correctly, the problem is that each FP has a cloud of finalizer objects attached to it with no particular structure between finalizer objects and the reason for this unstructured cloud is because you're piggy-backing on some other mechanism. It seems like the easy way to fix this is not to impose structure on the cloud but to impose structure on the finalizer objects. That is, allow finalizer objects to contain a list of finalizers and then allocate just one. Sketch of possible implementation: // Some useful support code - nothing exciting type Finalizer a = FunPtr (Ptr a -> IO ()) foreign import "dynamic" invoke_finalizer :: Finalizer -> IO () finalize :: IORef [Finalizer a] -> IO () finalize fs_ref = do fs <- readIORef fs_ref mapM_ invoke_finalizer fs // New implementation built on top of the old implementation data NewFP a = NFP (ForeignPtr a) (IORef [Finalizer a]) newFP :: Ptr a -> Finalizer a -> IO (NewFP a) newFP p f = do x <- newForeignPtr p (finalize fs_ref) // old version with Haskell finalizers fs_ref <- newIORef [f] return (NFP x fs_ref) addFPFinalizer :: NewFP a -> Finalizer a -> IO () addFPFinalizer (NFP x fs_ref) f = do fs <- readIORef fs_ref writeIORef fs_ref (f:fs) -- Alastair
participants (3)
-
Alastair Reid -
Ross Paterson -
Simon Marlow