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