cvs commit: hugs98/lib/exts ConcBase.hs

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
participants (1)
-
Alastair Reid