Hi Simon, thanks a lot for the pointer! I was kind of wondering why mkWeak# has an IO type, and the paper made it much clearer that it's not about reachability from the Weak# object, but the side effect that's between key and value objects.
Just out of curiosity, why not implement a memo table where both keys and values are weak pointers? Sure, it doesn't have the nice property that keys keep values alive, but I wonder how much difference it would be in practice. Regards, Paul Liu On Tue, Oct 11, 2011 at 1:07 AM, Simon Peyton-Jones <[email protected]> wrote: > | I'm just trying to understand the design rationale behind GHC's weak > | references. Any help is greatly appreciated! Thanks! > > Did you read the paper > http://research.microsoft.com/en-us/um/people/simonpj/papers/weak.htm > > It gives the design rationale in detail. > > Simon > > | -----Original Message----- > | From: [email protected] [mailto:[email protected]] On > Behalf Of > | Paul Liu > | Sent: 10 October 2011 21:21 > | To: [email protected] > | Subject: help needed to understand weak reference and its design choice > | > | GHC.Weak says "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." > | > | Am I right to say that if we use the same object for both key and > | value, we get the behavior of a traditional weak pointer (where it > | doesn't keep the object alive, and becomes null when the object goes)? > | > | I tried to look for use cases where key and value are different, there > | are in total only two such cases in GHC's library sources (and a few > | others where only the finalizer is of interest): > | > | mkWeakIORef :: IORef a -> IO () -> IO (Weak (IORef a)) > | mkWeakIORef r@(IORef (STRef r#)) f = IO $ \s -> > | case mkWeak# r# r f s of (# s1, w #) -> (# s1, Weak w #) > | > | and > | > | mkWeakThreadId :: ThreadId -> IO (Weak ThreadId) > | mkWeakThreadId t@(ThreadId t#) = IO $ \s -> > | case mkWeak# t# t (unsafeCoerce# 0#) s of > | (# s1, w #) -> (# s1, Weak w #) > | > | In both cases it is trying make a weak reference of an unboxed value > | and yet to return its box when de-referencing. I wonder if the same > | goal can be achieved by using the following definition: > | > | data Weak v where > | Weak :: Weak# w -> (w -> v) -> Weak v > | > | mkWeakIORef :: IORef a -> IO () -> IO (Weak (IORef a)) > | mkWeakIORef r@(IORef (STRef r#)) f = IO $ \s -> > | case mkWeak# r# r# f s of (# s1, w #) -> (# s1, Weak w (IORef . STRef) > #) > | > | Apart from some kind mis-matches (no way to annotate v as unlifted > | kind), will this definition of mkWeakIORef work the same? If so, It > | seems to me that GHC's weak references are no more general than the > | traditional definition of weak pointers. > | > | I'm just trying to understand the design rationale behind GHC's weak > | references. Any help is greatly appreciated! Thanks! > | > | Regards, > | Paul Liu > | > | _______________________________________________ > | Cvs-ghc mailing list > | [email protected] > | http://www.haskell.org/mailman/listinfo/cvs-ghc > > > -- Regards, Paul Liu _______________________________________________ Cvs-ghc mailing list [email protected] http://www.haskell.org/mailman/listinfo/cvs-ghc
