Weak pointers and STM

John Meacham john at repetae.net
Sun Dec 7 06:15:11 EST 2008

On Thu, Dec 04, 2008 at 09:09:06AM +0000, Simon Marlow wrote:
>> So now I have a scheme whereby I attach a finalizer to a proxy thunk.
>>> data TimeStamp = TimeStamp TS
>>> data TS = TS {
>>>     tsWord :: TVar Word64,
>>>     tsPrev :: TVar TS,
>>>     tsNext :: TVar TS
>>>     }
>> so, the finalizer attached to 'TimeStamp' values simply deletes the
>> value it points to from the linked list.
> What you want here is to attach the finalizer to one of the TVars, 
> probably tsWord.  Attaching the finalizer to Timestamp is very risky: the 
> compiler is free to optimise the Timestamp wrapper away, regardless of 
> how much you hide in the module API.  For example, consider an operation 
> on Timestamp: once the operation has looked inside the Timestamp wrapper, 
> it no longer holds a pointer to it, so the finalizer might run, even 
> though the operation is still working on the TS.  A function that is 
> strict in Timestamp will have a worker that takes the unboxed TS, and 
> might even re-wrap it in a new Timestamp (with no finalizer, of course).

but wouldn't a finalizer attached to any of these TVar's never run since
they are all references from the circularly linked list? I am not quite
sure where you are advocating adding the finalizer.

>> While I am wishing for things,
>>> unsafePerformSTM :: STM a -> a
>> would be really handy too :)
> The trouble with that is that it can lead to nested transactions, and the 
> RTS isn't set up to handle that.  It's probably a fair bit of work.

Yeah I was thinking that when you came across an usafePerformSTM inside
another transaction, you would abort the current transaction, evaluate
the unsafePerformSTM (memoizing the result) then retry the original
transaction. though.. that doesn't cover every case.. 

> > insertAfter :: TimeStamp -> IO TimeStamp
> > insertAfter t@(TimeStamp ts) = do
> >     (tts,ts) <- atomically $ insertAfter' ts
> >     touchTS t
> >     addFinalizer ts (deleteTimeStamp tts)
> >     return ts
> ah, I see you're adding the finalizer to the TS, not the Timestamp.  Same 
> arguments apply, though.
> > touchTS :: TimeStamp -> IO ()
> > touchTS ts =  touchForeignPtr (unsafeCoerce# ts)
> *blink*  that can't possibly work!

It seems to, but that may just be pure accident. I couldn't seem to find
where the data constructor for constructing IO actions from wandered too
so just threw that in there as a hack while testing. yeah, it should be
a properly wrapped touch#.


John Meacham - ⑆repetae.net⑆john⑈

More information about the Glasgow-haskell-users mailing list