cvs commit: hugs98/lib/exts ConcBase.hs
Alastair Reid
reid@glass.cse.ogi.edu
Fri, 20 Apr 2001 17:18:30 -0700
reid 2001/04/20 17:18:30 PDT
Modified files:
lib/exts ConcBase.hs
Log:
2nd (and last) commit in this series.
Added new MVar operations: tryTakeMVar and tryPutMVar.
These have not been tested very thoroughly.
We need one other change to make Hugs fully compatible with GHC: GHC
recently(?) changed the behaviour of putMVar on a full variable. This
used to raise an exception but now it's supposed to block. This is
going to take a little pondering. At the moment, an MVar is:
newtype MVar a = MkMVar (IORef (Either a [a -> IOResult]))
That is, it's either full or it's a (possibly empty) queue of blocked
threads. To accomodate the new semantics, it should change to
something like:
newtype MVar a = MkMVar (IORef (Either (a, [(a,IOResult)]) [a -> IOResult]))
where
Left (x, ts)
represents a full mvar with a (possibly empty) list ts of
blocked putters (and the values they want to put).
Right ts
represents an empty mvar with a (possibly empty) list ts
which want to receive a value.
Then we have to make putMVar block - with luck the mechanism used to
block in takeMVar will work.
And then we have to ponder the question of fairness:
My original MVar implementation made no attempt to unblock threads in
the same order as they had blocked. In fact, they could be unblocked
in exactly the opposite order from the order in which they had
blocked.
At the time, I argued that this was the correct behaviour since it was
so manifestly unfair that no-one was going to be fooled into believing
that Hugs' "scheduler" was fair. I felt this was a good idea because
it just wasn't possible to achieve fairness with a non-preemptive
implementation and I'd rather have my code always fail than
occasionally fail.
But the moment my back was turned (:-)), the OGI folks made MVars
fairer. I imagine they much have had a reason to do this ... Maybe I
should preserve this fairness in the interest of not breaking
anything.
[Incidentally, a recent bug report on the ghc list suggests that
ghc's MVars aren't fair either. This code:
forkIO (mapM_ putChar as) >> forkIO (mapM_ putChar bs)
where as = 'a':as; bs = 'b':bs
will output either all as or all bs. It seems that 'mapM putChar as'
spends almost all its time inside a mutex (protecting the stdout
object) and that when 'mapM putChar bs' tries to acquire the same
lock, it always fails. The GHC folk are considering changing putMVar
(I think) to consider preempting if there were any threads blocked on
the mvar.
]
Revision Changes Path
1.6 +42 -1 hugs98/lib/exts/ConcBase.hs