    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Graphics.HGL.Internals.Flag
    -- Copyright   :  (c) Alastair Reid, 1999-2003
    -- License     :  BSD-style (see the file libraries/base/LICENSE)
    --
    -- Maintainer  :  libraries@haskell.org
    -- Stability   :  internal
    -- Portability :  non-portable (requires concurrency)
    --
    -- A simple graphics library.
    --
    -----------------------------------------------------------------------------

    -- #hide
    module Graphics.HGL.Internals.Flag
    	( Flag, newFlag, setFlag, resetFlag
    	) where

    import Control.Concurrent.MVar
    	( MVar, newEmptyMVar, newMVar, takeMVar, putMVar
    	)

    ----------------------------------------------------------------
    -- Interface
    ----------------------------------------------------------------

    -- We maintain a list of blocked processes.
    -- Blocked processes are "stored" in MVars; the outer MVar
    -- is used to implement a critical section.
    newtype Flag a = Flag (MVar [MVar a])

    newFlag   :: IO (Flag a)
    -- sets the flag, never blocks, never fails
    setFlag   :: Flag a -> a -> IO ()
    -- block until the flag is set (and reset it)
    resetFlag :: Flag a -> IO a

    ----------------------------------------------------------------
    -- Implementation
    ----------------------------------------------------------------

    newFlag = do
      queue <- newMVar []
      return (Flag queue)

    setFlag (Flag queue) a = do
      ps <- takeMVar queue
      mapM_ (\ p -> putMVar p a) ps
      putMVar queue []

    resetFlag (Flag queue) = do
      ps <- takeMVar queue
      p  <- newEmptyMVar
      putMVar queue (p:ps)
      takeMVar p             -- block

    ----------------------------------------------------------------
    -- End
    ----------------------------------------------------------------