Alastair: >> So, is this a design that we could agree on? SimonM: > I like it. I'd vote for 'atomicModifyIORef' rather than a new PVar > type, though.
Ok, onto the second question: Can we use atomicModifyIORef to make our code finalizer-safe? I see potential problems wherever two IORefs need to be modified atomically. Obviously, it's easy enough to change code like this: foo :: (IORef a, IORef b) -> IO () foo (ref1,ref2) = do modifyIORef ref1 f modifyIORef ref2 g to foo :: IORef (a,b) -> IO () foo ref = do modifyIORef ref (f `cross` g) More difficult would be something composite objects where multiple IORefs need to be updated 'at once'. With MVars, you'd use a single MVar as the lock for the whole object and then use IORefs for mutable bits within the tree. You'd use a similar approach with a construct like blockFinalizers. I don't know how to achieve the same goal with atomicModifyIORef. -- Alastair ps While pondering the problems in the semantics of blockFinalizers, I came up with an alternative semantics which would make sense for GHC. @runAtomically m@ runs m atomically with respect to any finalizers or any threads also executing @runAtomically@. That is, any side effects from m must not overlap with the side effects of any other finalizer or thread (if other threads exist). On a system where finalizers behave like interrupts (i.e., finalizers can preempt normal threads and finalizers run to completion before any other finalizers or normal threads run), runAtomically has the effect of delaying execution of finalizers until m completes. In the presence of cooperative concurrency, we must also block execution of normal threads while m runs. On a system where finalizers behave like preemptive threads runAtomically must wait until all [other] currently running finalizers terminate and any other thread running rnuAtomically to terminate, then fresh finalizers must be prevented from starting while m is running, when m completes, any pending finalizers can be started. (I think this can be implemented using something like a reader-writer lock where all finalizers must take the 'reader' lock when they start and runAtomically takes the 'writer' lock when it runs. There's a small wrinkle on the standard reader-writer design that a 'reader' become a 'writer' if it calls runAtomically.) On multiprocessor systems, it might be possible to optimize things by taking the 'reader' lock only when the finalizers/threads start to have side effects. I feel more confident that runAtomically could be used to make libraries finalizer-safe than I do with atomicModifyIORef. _______________________________________________ FFI mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/ffi