content: -- | A trivial mutex.
  
  module Data.Mutex where
  
  import Prelude
  import Data.Var
  
  data Mutex = Mutex (Var Bool)
  
  -- | Make a new unlocked mutex.
  newMutex :: Fay Mutex
  newMutex = do v <- newVar False
                return (Mutex v)
  
  -- | If a mutex is free run the action, otherwise don't.
  ifMutexFree :: Mutex -> Fay () -> Fay ()
  ifMutexFree (Mutex var) action = do
    locked <- get var
    if locked then return () else action
  
  -- | Wait until the mutex is free to do something.
  whenMutexFree :: Mutex -> Fay () -> Fay ()
  whenMutexFree (Mutex var) cont = do
    locked <- get var
    if locked
       then do _ <- withUnsubscriber
                      (subscribe var)
                      (\unsubscribe lockedNow ->
                         if lockedNow
                            then return ()
                            else do unsubscribe ()
                                    cont)
               return ()
  
       else cont
  
  -- | Lock the given mutex until I'm done with it.
  lockMutex :: Mutex -> (Fay () -> Fay a) -> Fay a
  lockMutex (Mutex var) cont = do
    locked <- get var
    if locked
       then error "mutex is already locked"
       else do set var True
               cont (set var False)
  