[Haskell-cafe] weak references and sharing
Thomas Conway
drtomc at gmail.com
Tue Mar 6 19:50:42 EST 2007
Hi All,
I have the situation where I have something like the following:
type Foo = TVar Int
data Clasp t = Clasp t
makeClasp x f
= do
let c = Clasp x
mkWeakRef c (Just (f x))
return c
finis p
= do
atomically $ do
x <- readTVar p
writeTVar p (x - 1)
.... makeClasp p finis ....
The Foo object has a greater lifetime than the Clasp.
The bit I want you to focus on is the three lines:
let c = Clasp x
mkWeakRef c (Just (f x))
return c
We can only be sure that (f x) will be called after we let go of the
returned value if we can be sure that the language implementation
preserves the (explicit) sharing of 'c' between the call to mkWeakRef
and return. In particular, if the implementation rewrote the fragment
as:
mkWeakRef (Clasp x) (Just (f x))
return (Clasp x)
then the finalizer might be called sooner than we expect. The problem
is, that as I read it, making a distinction between the two fragments
would be a violation of referential transparency.
So here's the question: is there a way of writing this that is
guaranteed to work on all correct implementations of Haskell?
cheers,
T.
ps FWIW, the actual situation is that we have a TVar pointing to a
record representing a 'page' of an external data structure. For some
operations we need to make sure the the page is in-memory, but when
all the operations using a particular page are finished, we'd like to
flush it back to disk if it has been modified. Now it'd be really nice
to use the garbage collector to tell us when noone is using the
in-memory version of the page, so we can write it out. However, if we
can't be certain that we've got a genuine hard-reference to the
object, then we can't be sure it will not be prematurely flushed.
--
Dr Thomas Conway You are beautiful; but learn to work,
drtomc at gmail.com for you cannot eat your beauty.
-- Congo proverb
More information about the Haskell-Cafe
mailing list