(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

Reply via email to