mkWeakPtr :: a -> Maybe (IO ()) -> IO (Weak a)
deRefWeak :: Weak a -> IO (Maybe a)
addFinalizer :: a -> IO () -> IO ()
mkWeakPtr
takes a value of any type a
, and maybe a finalizer
of type IO ()
, and returns a weak pointer object referring to the
value, of type Weak a
. It is in the IO
monad because it has
the side effect of arranging that the finalizer (if there is one) will
be run when the object dies. In what follows, a ``weak pointer
object'', or ``weak pointer'' for short, means precisely ``a Haskell
value of type Weak t
'' for some type t
. A weak pointer
(object) is a first-class Haskell value; it can be passed to
functions, stored in data structures, and so on.
deRefWeak
dereferences a weak pointer, returning Just v
if
the value is still alive. If the key has already died, then
deRefWeak
returns Nothing
; that's why it's in the IO
monad - the return value of deRefWeak
depends on when the garbage
collector runs.
addFinalizer
is just another name for mkWeakPtr
except that
it throws the weak pointer itself away. (The runtime system will
remember that the weak pointer and hence the finalizer exists even if
the program has forgotten it.)
addFinalizer :: a -> IO () -> IO ()
addFinalizer v f = do { mkWeakPtr v f; return () }
The effect of addFinalizer
is simply that the finalizer runs when
the referenced object dies.
The following properties hold:
deRefWeak
returns the original object until
that object is considered dead; it returns Nothing
subsequently.deRefWeak
will return Nothing
.
f :: Show a => a -> IO a
f x = addFinalizer x (print (show x))
Here the finalizer print (show x)
contains a reference to x
itself, but that does not keep x
alive. When that is the only
reference to x
, the finalizer is run; and the message appears
on the screen.