[Haskell-cafe] Implementing tryReadMVar

Einar Karttunen ekarttun at cs.helsinki.fi
Wed Sep 1 10:44:12 EDT 2004

On 01.09 09:27, Jan-Willem Maessen - Sun Labs East wrote:
> Einar Karttunen wrote:
> >Hello
> >
> >Is it possible to implement an operation like 
> >tryReadMVar :: MVar a -> IO (Maybe a)
> >in a good fashion? The semantics should be 
> >"Read the value of the MVar without taking
> >it if it is filled, otherwise return Nothing".
> >
> >There are several easy and flawed implementations:
> >...
> >tryReadMVar mv = do mc <- tryTakeMVar mv
> >                    case mc of
> >                     Nothing -> return mc
> >                     Just v  -> putMVar mv v >> return mc
> >
> >Now this can block on the putMVar if there was a thread switch 
> >and someone filled the MVar behind our back. 
> This sets off alarm bells in my head.  What are you actually trying to 
> do, and why is correct for mutiple threads to race to "putMVar"?

There are several cases in which multiple threads racing putMVar is
correct. Consider e.g. a server thread encapsulating state, which 
needs to rate limit its clients. The server is put behind a MVar
to which all the clients putMVar and thus block until the server 
is ready e.g. 

plumbIn :: MVar SCoreT -> HId -> Handle -> IO ()
plumbIn mv hid h = hGetContents h >>= loop
    where loop s = let (m,r) = readInput s in putMVar mv (Msg m hid) >> loop r

The server thread uses tryTakeMVar for its job. 

Now add a debug function:

debug :: MVar SCoreT -> IO ()
debug mv = tryReadMVar mv >>= maybe (putStrLn "Nothing") print

And suddenly we have a created a subtle bug in the code with 
flawed tryReadMVar implementation.

- Einar Karttunen 

More information about the Haskell-Cafe mailing list