X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FWeak.lhs;h=5935f1833f011e05dfe377fc9d3a26928941d5bd;hb=7c0b04fd273621130062418bb764809c79488dd2;hp=3ce0467170f164625fc80a4fba7025c9d4d3024e;hpb=c2b87cb97d551bd98864ecd923a0f17fbb1b98e3;p=haskell-directory.git diff --git a/GHC/Weak.lhs b/GHC/Weak.lhs index 3ce0467..5935f18 100644 --- a/GHC/Weak.lhs +++ b/GHC/Weak.lhs @@ -1,5 +1,5 @@ \begin{code} -{-# OPTIONS -fno-implicit-prelude #-} +{-# OPTIONS_GHC -fno-implicit-prelude #-} ----------------------------------------------------------------------------- -- | -- Module : GHC.Weak @@ -14,11 +14,13 @@ -- ----------------------------------------------------------------------------- +-- #hide module GHC.Weak where import GHC.Base import Data.Maybe import GHC.IOBase ( IO(..), unIO ) +import Data.Typeable ( Typeable1(..), mkTyCon, mkTyConApp ) {-| A weak pointer object with a key and a value. The value has type @v@. @@ -29,10 +31,16 @@ 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, -then the finalizer will be run once, and once only, 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. +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. 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 @@ -56,6 +64,9 @@ for runnable finalizers before declaring the system to be deadlocked. -} data Weak v = Weak (Weak# v) +#include "Typeable.h" +INSTANCE_TYPEABLE1(Weak,weakTc,"Weak") + -- | Establishes a weak pointer to @k@, with value @v@ and a finalizer. -- -- This is the most general interface for building a weak pointer. @@ -71,24 +82,27 @@ mkWeak key val Nothing = IO $ \s -> case mkWeak# key val (unsafeCoerce# 0#) s of { (# s1, w #) -> (# s1, Weak w #) } {-| - A specialised version of 'mkWeak', where the key and the value are the - same object: +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. - > mkWeakPtr key finalizer = mkWeak key key finalizer --} -mkWeakPtr :: k -> Maybe (IO ()) -> IO (Weak k) -mkWeakPtr key finalizer = mkWeak key key finalizer - -{-| - A specialised version of 'mkWeakPtr', where the 'Weak' object - returned is simply thrown away (however the finalizer will be - remembered by the garbage collector, and will still be run - when the key becomes unreachable). +The return value of 'deRefWeak' depends on when the garbage collector +runs, hence it is in the 'IO' monad. -} -addFinalizer :: key -> IO () -> IO () -addFinalizer key finalizer = do - mkWeakPtr key (Just finalizer) -- throw it away - return () +deRefWeak :: Weak v -> IO (Maybe v) +deRefWeak (Weak w) = IO $ \s -> + case deRefWeak# w s of + (# s1, flag, p #) -> case flag of + 0# -> (# s1, Nothing #) + _ -> (# s1, Just p #) + +-- | 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 + (# s1, 0#, _ #) -> (# s1, () #) -- already dead, or no finaliser + (# s1, _, f #) -> f s1 {- Instance Eq (Weak v) where