(message referred to follows) Alastair suggested implementing blockFinalizers rather than PVars. However I dislike this for two reason: (1) I'm rather attached to PVars. Not just because I suggested them (actually I think I stole them from Einar Karlsen) but because it looks to me as if they could be implemented very efficiently and would be quite useful. If we take the more general interface:
newPVar :: a -> IO (PVar a) updatePVar :: PVar a -> (a -> (a,b)) -> IO b then PVar's are absolutely guaranteed not to block, and updatePVar can be implemented as an atomic operation in any of GHC, NHC and Hugs, and I suspect it should even be pretty easy to implement it directly in C (since all you are doing is moving pointers to thunks around). In particular I would like to petition Simon Marlow to include updatePVar in this way in GHC, because (unlike the corresponding solution with MVars) it could very cheaply be guaranteed to work atomically (with MVars you need complicated patterns of expensive block-exception primitives to stop asynchronous exceptions mucking things up). Furthermore although you cannot provide updatePVarIO :: PVar a -> (a -> IO (a,b)) -> IO b you can implement something fairly similar to it if you are naughty by giving updatePVar a function which returns an unsafePerformIO'd action. The action will then of course be executed at some outspecified date when the user tries to read the contents of the PVar. For UniForM at least there is an application for this which would plug an existing embarassing hole in the events code, namely that you mustn't throw asynchronous exceptions at threads which use events. (2) blockFinalizers looks fine for Hugs and NHC which only have a single-thread model, but it looks tricky in general where we do not have a conception of "during". Effectively that means an implementation on a parallel architecture which accesses state has to come up with some arbitrary order of state accesses, just so that it can rely on it to specify blockFinalizers. Of course PVars assume an ordering of state accesses, but only between accesses to the single PVar. (There is a similar problem lurking with "unsafe" external calls, which is probably why they are called "unsafe".) (3) The implementation of PVars Alastair gives using blockFinalizers also will not work in general unless you also specify that Haskell finalizers are properly nested. This is OK for NHC, maybe not for Hugs, certainly not for GHC. This is not of course a problem for PVars since the reason is that Hugs and GHC have concurrency, and on a concurrent machine you would naturally implement PVars using MVars (if not as primitives in their own right). Alastair Reid wrote: > > > However even if Haskell finalizers + MVars are impossible in NHC, I > > don't think Haskell finalizers + mutable state have to be. For > > example another mutable variable we could have would be a PVar which > > is always full and has functions [snip] > > > updatePVar (PVar ioRef) updateFn = > > do > > [stop any new finalizers running] > > a <- readIORef ioRef > > writeIORef (updateFn a) > > [reenable finalizers] > > return a > > Just for the record, I think that if we were to pursue this approach, > then the right primitive to add is: > > -- | > -- Execute argument atomically with respect to finalizers. > -- Nested calls to blockFinalizers are allowed. > -- > -- That is, while executing the argument, no finalizers will start > -- to execute. > -- (Finalizers that are already executing may continue to execute.) > blockFinalizers :: IO a -> IO a _______________________________________________ FFI mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/ffi