> II
> 1-4 as above
> 5'. putMVar' :: MVar a -> a -> IO () -- blocking
> 6. tryButDoNotSuspend :: IO a -> IO a -> IO a
> where (6) tries to execute its first parameter, and if this
> would lead to an immediate suspension of the current thread, it
> executes its second parameter instead. Then
>
> 5. putMVar mv v = tryButDoNotSuspend (putMVar' mv v)
> (throw PutFullMVar)
>
> as well as
>
> 4'. takeMVar' mv = tryButDoNotSuspend (takeMVar mv >>= return.Just)
> (return Nothing)
I don't think I understand "tryButDoNotSuspend". Suppose that 'mv' in your
above example is currently under evaluation by another thread, that would
also cause the current thread to block. Does that count as suspending, i.e.
would tryButDoNotSuspend return immediately?
> 6'. tryForaWhileButDoNotBlockForever :: IO a -> Int -> IO a -> IO a
We have an implementation of this function using asynchronous exceptions.
See
http://research.microsoft.com/~simonpj/papers/asynch-exns.ps.gz
There's one implementation issue related to efficiency that springs to mind:
in GHC, a primitive which blocks or does any allocation must be an
out-of-line function. This means that non-blocking put or takeMVar can be
inline primitives (although putMVar is currently out-of-line to avoid code
duplication).
Jan-Willen Maessen writes:
> My conclusions:
> The suspensive behaviors are necessary. At least one, and
> preferably both of takeMVar/putMVar must be suspensive.
> The non-suspensive behaviors are nice, but should be captured using
> separate operations. Cooking them up using multiple MVars will
> work, but is arguably only necessary because the implementation
> isn't flexible enough.
This sounds reasonable to me. Ok, here's a proposal:
--- blocking versions
takeMVar :: MVar a -> IO a
putMVar :: MVar a -> a -> IO ()
--- non-blocking versions
tryTakeMVar :: MVar a -> IO (Maybe a)
tryPutMVar :: MVar a -> a -> IO Bool
--- current putMVar:
putMVarMayFail :: MVar a -> a -> IO ()
putMVarMayFail m a
= b <- tryPutMVar m a
if b then throw PutFullMVar else return ()
Existing applications shouldn't be affected unless they make use of
putMVar's exception-throwing semantics, which as I mentioned before is
unlikely because until very recently it was a fatal error rather than an
exception to put to a full MVar.
Cheers,
Simon