Repository : ssh://darcs.haskell.org//srv/darcs/packages/base On branch : ghc-7.6
http://hackage.haskell.org/trac/ghc/changeset/77f2692573ade4a89f999ca585081a73edaf7b53 >--------------------------------------------------------------- commit 77f2692573ade4a89f999ca585081a73edaf7b53 Author: Simon Marlow <[email protected]> Date: Fri Sep 21 16:11:20 2012 +0100 Add a big warning to the documentation for Weak (#7250) >--------------------------------------------------------------- GHC/Weak.lhs | 22 ++++++++++++++++++++-- System/Mem/Weak.hs | 13 ++++--------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/GHC/Weak.lhs b/GHC/Weak.lhs index 93c4eac..e3109e1 100644 --- a/GHC/Weak.lhs +++ b/GHC/Weak.lhs @@ -55,7 +55,7 @@ It is not guaranteed that a finalizer will eventually run, and no attempt is made to run outstanding finalizers when the program exits. Therefore finalizers should not be relied on to clean up resources - other methods (eg. exception handlers) should be employed, possibly in -addition to finalisers. +addition to finalizers. References from the finalizer to the key are treated in the same way as references from the value to the key: they do not keep the key @@ -76,6 +76,24 @@ such finalizer. If there are no other threads to run, the runtime system will check for runnable finalizers before declaring the system to be deadlocked. + +WARNING: weak pointers to ordinary non-primitive Haskell types are +particularly fragile, because the compiler is free to optimise away or +duplicate the underlying data structure. Therefore attempting to +place a finalizer on an ordinary Haskell type may well result in the +finalizer running earlier than you expected. This is not a problem +for caches and memo tables where early finalization is benign. + +Finalizers /can/ be used reliably for types that are created explicitly +and have identity, such as @IORef@ and @MVar@. However, to place a +finalizer on one of these types, you should use the specific operation +provided for that type, e.g. @mkWeakIORef@ and @addMVarFinalizer@ +respectively (the non-uniformity is accidental). These operations +attach the finalizer to the primitive object inside the box +(e.g. @MutVar#@ in the case of @IORef@), because attaching the +finalizer to the box itself fails when the outer box is optimised away +by the compiler. + -} data Weak v = Weak (Weak# v) @@ -116,7 +134,7 @@ deRefWeak (Weak w) = IO $ \s -> finalize :: Weak v -> IO () finalize (Weak w) = IO $ \s -> case finalizeWeak# w s of - (# s1, 0#, _ #) -> (# s1, () #) -- already dead, or no finaliser + (# s1, 0#, _ #) -> (# s1, () #) -- already dead, or no finalizer (# s1, _, f #) -> f s1 {- diff --git a/System/Mem/Weak.hs b/System/Mem/Weak.hs index 4003a74..71b8446 100644 --- a/System/Mem/Weak.hs +++ b/System/Mem/Weak.hs @@ -94,15 +94,10 @@ mkWeakPtr key finalizer = mkWeak key key finalizer when the key becomes unreachable). Note: adding a finalizer to a 'Foreign.ForeignPtr.ForeignPtr' using - 'addFinalizer' won't work as well as using the specialised version - 'Foreign.ForeignPtr.addForeignPtrFinalizer' because the latter - version adds the finalizer to the primitive 'ForeignPtr#' object - inside, whereas the generic 'addFinalizer' will add the finalizer to - the box. Optimisations tend to remove the box, which may cause the - finalizer to run earlier than you intended. The same motivation - justifies the existence of - 'Control.Concurrent.MVar.addMVarFinalizer' and - 'Data.IORef.mkWeakIORef' (the non-uniformity is accidental). + 'addFinalizer' won't work; use the specialised version + 'Foreign.ForeignPtr.addForeignPtrFinalizer' instead. For discussion + see the 'Weak' type. +. -} addFinalizer :: key -> IO () -> IO () addFinalizer key finalizer = do _______________________________________________ Cvs-libraries mailing list [email protected] http://www.haskell.org/mailman/listinfo/cvs-libraries
