    {-# 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