Weak.lhs 4.74 KB
Newer Older
 simonmar committed Jun 28, 2001 1 \begin{code}  Ian Lynagh committed Jun 16, 2008 2 {-# OPTIONS_GHC -XNoImplicitPrelude #-}  Ross Paterson committed Jan 20, 2008 3 {-# OPTIONS_HADDOCK hide #-}  simonmar committed Apr 26, 2002 4 5 6 7 8 9 10 11 12 13 14 15 16 ----------------------------------------------------------------------------- -- | -- Module : GHC.Weak -- Copyright : (c) The University of Glasgow, 1998-2002 -- License : see libraries/base/LICENSE -- -- Maintainer : cvs-ghc@haskell.org -- Stability : internal -- Portability : non-portable (GHC Extensions) -- -- Weak pointers. -- -----------------------------------------------------------------------------  simonmar committed Jun 28, 2001 17   ross committed Feb 03, 2005 18 -- #hide  simonmar committed Jun 28, 2001 19 20 21 module GHC.Weak where import GHC.Base  simonmar committed Jul 03, 2001 22 import Data.Maybe  Don Stewart committed Mar 08, 2008 23 import GHC.IOBase ( IO(..), unIO )  Ian Lynagh committed Jun 19, 2008 24 import Data.Typeable  simonmar committed Jun 28, 2001 25   simonmar committed May 27, 2002 26 27 28 29 30 31 32 33 34 {-| A weak pointer object with a key and a value. The value has type @v@. A weak pointer expresses a relationship between two objects, the /key/ and the /value/: if the key is considered to be alive by the garbage collector, then the value is also alive. A reference from the value to the key does /not/ keep the key alive. A weak pointer may also have a finalizer of type @IO ()@; if it does,  simonmar committed Dec 08, 2004 35 36 37 38 39 40 41 42 43 44 then the finalizer will be run at most once, at a time after the key has become unreachable by the program (\"dead\"). The storage manager attempts to run the finalizer(s) for an object soon after the object dies, but promptness is not guaranteed. 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.  simonmar committed May 27, 2002 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65  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 alive. A finalizer may therefore ressurrect the key, perhaps by storing it in the same data structure. The finalizer, and the relationship between the key and the value, exist regardless of whether the program keeps a reference to the 'Weak' object or not. There may be multiple weak pointers with the same key. In this case, the finalizers for each of these weak pointers will all be run in some arbitrary order, or perhaps concurrently, when the key dies. If the programmer specifies a finalizer that assumes it has the only reference to an object (for example, a file that it wishes to close), then the programmer must ensure that there is only one 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. -}  simonmar committed Jun 28, 2001 66 67 data Weak v = Weak (Weak# v)  simonpj committed Feb 02, 2005 68 69 70 #include "Typeable.h" INSTANCE_TYPEABLE1(Weak,weakTc,"Weak")  simonmar committed May 27, 2002 71 72 73 74 -- | Establishes a weak pointer to @k@, with value @v@ and a finalizer. -- -- This is the most general interface for building a weak pointer. --  Don Stewart committed Mar 08, 2008 75 76 77 78 mkWeak :: k -- ^ key -> v -- ^ value -> Maybe (IO ()) -- ^ finalizer -> IO (Weak v) -- ^ returns: a weak pointer object  simonmar committed Jun 28, 2001 79 80 81 82 83 84  mkWeak key val (Just finalizer) = IO $\s -> case mkWeak# key val finalizer s of { (# s1, w #) -> (# s1, Weak w #) } mkWeak key val Nothing = IO$ \s -> case mkWeak# key val (unsafeCoerce# 0#) s of { (# s1, w #) -> (# s1, Weak w #) }  simonmar committed May 27, 2002 85 {-|  ross committed Jan 17, 2003 86 87 88 Dereferences a weak pointer. If the key is still alive, then @'Just' v@ is returned (where @v@ is the /value/ in the weak pointer), otherwise 'Nothing' is returned.  simonmar committed May 27, 2002 89   ross committed Jan 17, 2003 90 91 The return value of 'deRefWeak' depends on when the garbage collector runs, hence it is in the 'IO' monad.  simonmar committed May 27, 2002 92 -}  ross committed Jan 17, 2003 93 94 95 deRefWeak :: Weak v -> IO (Maybe v) deRefWeak (Weak w) = IO $\s -> case deRefWeak# w s of  Don Stewart committed Mar 08, 2008 96 97 98  (# s1, flag, p #) -> case flag of 0# -> (# s1, Nothing #) _ -> (# s1, Just p #)  ross committed Jan 17, 2003 99 100 101 102 103 104  -- | Causes a the finalizer associated with a weak pointer to be run -- immediately. finalize :: Weak v -> IO () finalize (Weak w) = IO$ \s -> case finalizeWeak# w s of  Don Stewart committed Mar 08, 2008 105 106  (# s1, 0#, _ #) -> (# s1, () #) -- already dead, or no finaliser (# s1, _, f #) -> f s1  simonmar committed Jun 28, 2001 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123  {- Instance Eq (Weak v) where (Weak w1) == (Weak w2) = w1 sameWeak# w2 -} -- run a batch of finalizers from the garbage collector. We're given -- an array of finalizers and the length of the array, and we just -- call each one in turn. -- -- the IO primitives are inlined by hand here to get the optimal -- code (sigh) --SDM. runFinalizerBatch :: Int -> Array# (IO ()) -> IO () runFinalizerBatch (I# n) arr = let go m = IO \$ \s ->  Don Stewart committed Mar 08, 2008 124 125 126 127 128 129 130  case m of 0# -> (# s, () #) _ -> let m' = m -# 1# in case indexArray# arr m' of { (# io #) -> case unIO io s of { (# s, _ #) -> unIO (go m') s }}  simonmar committed Jun 28, 2001 131 132 133 134  in go n \end{code}