content: {-# LANGUAGE Safe #-}
  
  -- |
  --
  -- Module      :  Control.Concurrent.MVar
  -- Copyright   :  (c) The University of Glasgow 2001
  -- License     :  BSD-style (see the file libraries/base/LICENSE)
  --
  -- Maintainer  :  libraries@haskell.org
  -- Stability   :  stable
  -- Portability :  non-portable (concurrency)
  --
  -- An @'MVar' t@ is a mutable location that is either empty or contains a
  -- value of type @t@.  It has two fundamental operations: 'putMVar'
  -- which fills an 'MVar' if it is empty and blocks otherwise, and
  -- 'takeMVar' which empties an 'MVar' if it is full and blocks
  -- otherwise.  They can be used in multiple different ways:
  --
  --   1. As synchronized mutable variables,
  --
  --   2. As channels, with 'takeMVar' and 'putMVar' as receive and send, and
  --
  --   3. As a binary semaphore @'MVar' ()@, with 'takeMVar' and 'putMVar' as
  --      wait and signal.
  --
  -- They were introduced in the paper
  -- ["Concurrent Haskell"](https://www.microsoft.com/en-us/research/wp-content/uploads/1996/01/concurrent-haskell.pdf)
  -- by Simon Peyton Jones, Andrew Gordon and Sigbjorn Finne, though
  -- some details of their implementation have since then changed (in
  -- particular, a put on a full 'MVar' used to error, but now merely
  -- blocks.)
  --
  -- === Applicability
  --
  -- 'MVar's offer more flexibility than 'Data.IORef.IORef's, but less flexibility
  -- than 'GHC.Conc.STM'.  They are appropriate for building synchronization
  -- primitives and performing simple inter-thread communication; however
  -- they are very simple and susceptible to race conditions, deadlocks or
  -- uncaught exceptions.  Do not use them if you need to perform larger
  -- atomic operations such as reading from multiple variables: use 'GHC.Conc.STM'
  -- instead.
  --
  -- In particular, the "bigger" functions in this module ('swapMVar',
  -- 'withMVar', 'modifyMVar_' and 'modifyMVar') are simply
  -- the composition of a 'takeMVar' followed by a 'putMVar' with
  -- exception safety.
  -- These have atomicity guarantees only if all other threads
  -- perform a 'takeMVar' before a 'putMVar' as well;  otherwise, they may
  -- block.
  --
  -- === Fairness
  --
  -- No thread can be blocked indefinitely on an 'MVar' unless another
  -- thread holds that 'MVar' indefinitely.  One usual implementation of
  -- this fairness guarantee is that threads blocked on an 'MVar' are
  -- served in a first-in-first-out fashion (this is what GHC does),
  -- but this is not guaranteed in the semantics.
  --
  -- === Gotchas
  --
  -- Like many other Haskell data structures, 'MVar's are lazy.  This
  -- means that if you place an expensive unevaluated thunk inside an
  -- 'MVar', it will be evaluated by the thread that consumes it, not the
  -- thread that produced it.  Be sure to 'evaluate' values to be placed
  -- in an 'MVar' to the appropriate normal form, or utilize a strict
  -- @MVar@ provided by the [strict-concurrency](https://hackage.haskell.org/package/strict-concurrency) package.
  --
  -- === Ordering
  --
  -- 'MVar' operations are always observed to take place in the order
  -- they are written in the program, regardless of the memory model of
  -- the underlying machine.  This is in contrast to 'Data.IORef.IORef' operations
  -- which may appear out-of-order to another thread in some cases.
  --
  -- === Example
  --
  -- Consider the following concurrent data structure, a skip channel.
  -- This is a channel for an intermittent source of high bandwidth
  -- information (for example, mouse movement events.)  Writing to the
  -- channel never blocks, and reading from the channel only returns the
  -- most recent value, or blocks if there are no new values.  Multiple
  -- readers are supported with a @dupSkipChan@ operation.
  --
  -- A skip channel is a pair of 'MVar's. The first 'MVar' contains the
  -- current value, and a list of semaphores that need to be notified
  -- when it changes. The second 'MVar' is a semaphore for this particular
  -- reader: it is full if there is a value in the channel that this
  -- reader has not read yet, and empty otherwise.
  --
  -- @
  -- data SkipChan a = SkipChan (MVar (a, [MVar ()])) (MVar ())
  --
  -- newSkipChan :: IO (SkipChan a)
  -- newSkipChan = do
  --     sem <- newEmptyMVar
  --     main <- newMVar (undefined, [sem])
  --     return (SkipChan main sem)
  --
  -- putSkipChan :: SkipChan a -> a -> IO ()
  -- putSkipChan (SkipChan main _) v = do
  --     (_, sems) <- takeMVar main
  --     putMVar main (v, [])
  --     mapM_ (\\sem -> putMVar sem ()) sems
  --
  -- getSkipChan :: SkipChan a -> IO a
  -- getSkipChan (SkipChan main sem) = do
  --     takeMVar sem
  --     (v, sems) <- takeMVar main
  --     putMVar main (v, sem : sems)
  --     return v
  --
  -- dupSkipChan :: SkipChan a -> IO (SkipChan a)
  -- dupSkipChan (SkipChan main _) = do
  --     sem <- newEmptyMVar
  --     (v, sems) <- takeMVar main
  --     putMVar main (v, sem : sems)
  --     return (SkipChan main sem)
  -- @
  --
  -- This example was adapted from the original Concurrent Haskell paper.
  -- For more examples of 'MVar's being used to build higher-level
  -- synchronization primitives, see 'Control.Concurrent.Chan' and
  -- 'Control.Concurrent.QSem'.
  --
  
  module Control.Concurrent.MVar
      (-- *  @MVar@s
       MVar,
       newEmptyMVar,
       newMVar,
       takeMVar,
       putMVar,
       readMVar,
       swapMVar,
       tryTakeMVar,
       tryPutMVar,
       isEmptyMVar,
       withMVar,
       withMVarMasked,
       modifyMVar_,
       modifyMVar,
       modifyMVarMasked_,
       modifyMVarMasked,
       tryReadMVar,
       mkWeakMVar,
       addMVarFinalizer
       ) where
  
  import GHC.Internal.Control.Concurrent.MVar
  