Fix build on OS X
[packages/base.git] / GHC / Weak.lhs
1 \begin{code}
2 {-# LANGUAGE Unsafe #-}
3 {-# LANGUAGE CPP
4            , NoImplicitPrelude
5            , BangPatterns
6            , MagicHash
7            , UnboxedTuples
8            , DeriveDataTypeable
9            , StandaloneDeriving
10   #-}
11 {-# OPTIONS_HADDOCK hide #-}
12
13 -----------------------------------------------------------------------------
14 -- |
15 -- Module      :  GHC.Weak
16 -- Copyright   :  (c) The University of Glasgow, 1998-2002
17 -- License     :  see libraries/base/LICENSE
18 -- 
19 -- Maintainer  :  cvs-ghc@haskell.org
20 -- Stability   :  internal
21 -- Portability :  non-portable (GHC Extensions)
22 --
23 -- Weak pointers.
24 --
25 -----------------------------------------------------------------------------
26
27 -- #hide
28 module GHC.Weak (
29         Weak(..),
30         mkWeak,
31         deRefWeak,
32         finalize,
33         runFinalizerBatch
34     ) where
35
36 import GHC.Base
37 import Data.Maybe
38 import Data.Typeable
39
40 {-|
41 A weak pointer object with a key and a value.  The value has type @v@.
42
43 A weak pointer expresses a relationship between two objects, the
44 /key/ and the /value/:  if the key is considered to be alive by the
45 garbage collector, then the value is also alive.  A reference from
46 the value to the key does /not/ keep the key alive.
47
48 A weak pointer may also have a finalizer of type @IO ()@; if it does,
49 then the finalizer will be run at most once, at a time after the key
50 has become unreachable by the program (\"dead\").  The storage manager
51 attempts to run the finalizer(s) for an object soon after the object
52 dies, but promptness is not guaranteed.  
53
54 It is not guaranteed that a finalizer will eventually run, and no
55 attempt is made to run outstanding finalizers when the program exits.
56 Therefore finalizers should not be relied on to clean up resources -
57 other methods (eg. exception handlers) should be employed, possibly in
58 addition to finalizers.
59
60 References from the finalizer to the key are treated in the same way
61 as references from the value to the key: they do not keep the key
62 alive.  A finalizer may therefore ressurrect the key, perhaps by
63 storing it in the same data structure.
64
65 The finalizer, and the relationship between the key and the value,
66 exist regardless of whether the program keeps a reference to the
67 'Weak' object or not.
68
69 There may be multiple weak pointers with the same key.  In this
70 case, the finalizers for each of these weak pointers will all be
71 run in some arbitrary order, or perhaps concurrently, when the key
72 dies.  If the programmer specifies a finalizer that assumes it has
73 the only reference to an object (for example, a file that it wishes
74 to close), then the programmer must ensure that there is only one
75 such finalizer.
76
77 If there are no other threads to run, the runtime system will check
78 for runnable finalizers before declaring the system to be deadlocked.
79
80 WARNING: weak pointers to ordinary non-primitive Haskell types are
81 particularly fragile, because the compiler is free to optimise away or
82 duplicate the underlying data structure.  Therefore attempting to
83 place a finalizer on an ordinary Haskell type may well result in the
84 finalizer running earlier than you expected.  This is not a problem
85 for caches and memo tables where early finalization is benign.
86
87 Finalizers /can/ be used reliably for types that are created explicitly
88 and have identity, such as @IORef@ and @MVar@.  However, to place a
89 finalizer on one of these types, you should use the specific operation
90 provided for that type, e.g. @mkWeakIORef@ and @addMVarFinalizer@
91 respectively (the non-uniformity is accidental).  These operations
92 attach the finalizer to the primitive object inside the box
93 (e.g. @MutVar#@ in the case of @IORef@), because attaching the
94 finalizer to the box itself fails when the outer box is optimised away
95 by the compiler.
96
97 -}
98 data Weak v = Weak (Weak# v)
99
100 #include "Typeable.h"
101 INSTANCE_TYPEABLE1(Weak,weakTc,"Weak")
102
103 -- | Establishes a weak pointer to @k@, with value @v@ and a finalizer.
104 --
105 -- This is the most general interface for building a weak pointer.
106 --
107 mkWeak  :: k                            -- ^ key
108         -> v                            -- ^ value
109         -> Maybe (IO ())                -- ^ finalizer
110         -> IO (Weak v)                  -- ^ returns: a weak pointer object
111
112 mkWeak key val (Just finalizer) = IO $ \s ->
113    case mkWeak# key val finalizer s of { (# s1, w #) -> (# s1, Weak w #) }
114 mkWeak key val Nothing = IO $ \s ->
115    case mkWeakNoFinalizer# key val s of { (# s1, w #) -> (# s1, Weak w #) }
116
117 {-|
118 Dereferences a weak pointer.  If the key is still alive, then
119 @'Just' v@ is returned (where @v@ is the /value/ in the weak pointer), otherwise
120 'Nothing' is returned.
121
122 The return value of 'deRefWeak' depends on when the garbage collector
123 runs, hence it is in the 'IO' monad.
124 -}
125 deRefWeak :: Weak v -> IO (Maybe v)
126 deRefWeak (Weak w) = IO $ \s ->
127    case deRefWeak# w s of
128         (# s1, flag, p #) -> case flag of
129                                 0# -> (# s1, Nothing #)
130                                 _  -> (# s1, Just p #)
131
132 -- | Causes a the finalizer associated with a weak pointer to be run
133 -- immediately.
134 finalize :: Weak v -> IO ()
135 finalize (Weak w) = IO $ \s ->
136    case finalizeWeak# w s of
137         (# s1, 0#, _ #) -> (# s1, () #) -- already dead, or no finalizer
138         (# s1, _,  f #) -> f s1
139
140 {-
141 Instance Eq (Weak v) where
142   (Weak w1) == (Weak w2) = w1 `sameWeak#` w2
143 -}
144
145
146 -- run a batch of finalizers from the garbage collector.  We're given 
147 -- an array of finalizers and the length of the array, and we just
148 -- call each one in turn.
149 --
150 -- the IO primitives are inlined by hand here to get the optimal
151 -- code (sigh) --SDM.
152
153 runFinalizerBatch :: Int -> Array# (IO ()) -> IO ()
154 runFinalizerBatch (I# n) arr = 
155    let  go m  = IO $ \s ->
156                   case m of 
157                   0# -> (# s, () #)
158                   _  -> let !m' = m -# 1# in
159                         case indexArray# arr m' of { (# io #) -> 
160                         case unIO io s of          { (# s', _ #) -> 
161                         unIO (go m') s'
162                         }}
163    in
164         go n
165
166 \end{code}