No atomic read on MVar?
haskell at list.mightyreason.com
Tue Nov 4 05:57:58 EST 2008
It is true that STM's TMVars (which are TVar (Maybe _)) allow atomic readTMVar.
They are not a great replacement for MVars for serious performance reasons.
MVars have "wake one" semantics: There can be many threads stopped and waiting
on a particular MVar to be filled/emptied. These are actually in a FIFO queue.
Filling or emptying it will cause the next thread in the FIFO queue to run,
and leave the others to sleep. 
TVars (and TMVars, and all STM threads) have "wake all" semantics: All threads
which are stopped after a "retry" that are monitoring a particular TVar will be
woken when the TVar is changed by the next STM commit. This will cause the
"thundering herd" problem that plagued big Apache web servers with the original
multi-process model .
To understand MVars and Simon's comments on the atomic read proposal I went and
read the code in  to see it first hand. The putMVar# and tryPutMVar#
operations, when a take operation is blocked, will perform the take operation
and then wake the blocked thread. The takeMVar# and tryTakeMVar# do the
reverse. So adding an atomicRead# operation would mean that on filling the MVar
that all the atomicRead# that are waiting might need to be woken (or perhaps
just those at the front of the FIFO). This is a fairly large change.
The desire to atomically read an MVar could be expressed by
(1) Use STM and lose the "wake one" performance
(2) Use an (MVar ()) guarding the (MVar a)
(3) Use an (MVar ()) guarding an (IORef a)
Where (3) has a performance advantage to (2) and (3) is safe when only the right
operations are exposed.
I started looking at this with the opinion that "readMVar" and "withMVar" should
have atomic semantics, i.e. edit PrimOps.cmm to add these operations. Now I am
leaning to taking (3) and packaging this as a new module that exposes the safe
More information about the Glasgow-haskell-users