[commit: base] ghc-7.6: Add a big warning to the documentation for Weak (#7250) (77f2692)
Ian Lynagh
igloo at earth.li
Fri Oct 12 01:22:54 CEST 2012
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 <marlowsd at gmail.com>
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 at . 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
More information about the Cvs-libraries
mailing list