    {-# LANGUAGE Unsafe #-}
    {-# LANGUAGE NoImplicitPrelude, MagicHash #-}
    {-# LANGUAGE UnboxedTuples #-}
    {-# LANGUAGE BangPatterns #-}
    {-# OPTIONS_HADDOCK not-home #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GHC.Internal.IORef
    -- Copyright   :  (c) The University of Glasgow 2008
    -- License     :  see libraries/base/LICENSE
    --
    -- Maintainer  :  ghc-devs@haskell.org
    -- Stability   :  internal
    -- Portability :  non-portable (GHC Extensions)
    --
    -- The IORef type
    --
    -----------------------------------------------------------------------------

    module GHC.Internal.IORef (
            IORef(..),
            newIORef, readIORef, writeIORef, atomicModifyIORef2Lazy,
            atomicModifyIORef2, atomicModifyIORefLazy_, atomicModifyIORef'_,
            atomicModifyIORefP, atomicSwapIORef, atomicModifyIORef'
        ) where

    import GHC.Internal.Base
    import GHC.Internal.STRef
    import GHC.Internal.IO

    -- ---------------------------------------------------------------------------
    -- IORefs

    -- |A mutable variable in the 'IO' monad.
    --
    -- >>> import GHC.Internal.Data.IORef
    -- >>> r <- newIORef 0
    -- >>> readIORef r
    -- 0
    -- >>> writeIORef r 1
    -- >>> readIORef r
    -- 1
    -- >>> atomicWriteIORef r 2
    -- >>> readIORef r
    -- 2
    -- >>> modifyIORef' r (+ 1)
    -- >>> readIORef r
    -- 3
    -- >>> atomicModifyIORef' r (\a -> (a + 1, ()))
    -- >>> readIORef r
    -- 4
    --
    -- See also 'Data.STRef.STRef' and 'Control.Concurrent.MVar.MVar'.
    --
    newtype IORef a = IORef (STRef RealWorld a)
      deriving IORef a -> IORef a -> Bool
    (IORef a -> IORef a -> Bool)
    -> (IORef a -> IORef a -> Bool) -> Eq (IORef a)
    forall a. IORef a -> IORef a -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: forall a. IORef a -> IORef a -> Bool
    == :: IORef a -> IORef a -> Bool
    $c/= :: forall a. IORef a -> IORef a -> Bool
    /= :: IORef a -> IORef a -> Bool
    Eq
      -- ^ Pointer equality.
      --
      -- @since base-4.0.0.0

    -- |Build a new 'IORef'
    newIORef    :: a -> IO (IORef a)
    newIORef :: forall a. a -> IO (IORef a)
    newIORef a
    v = ST RealWorld (STRef RealWorld a) -> IO (STRef RealWorld a)
    forall a. ST RealWorld a -> IO a
    stToIO (a -> ST RealWorld (STRef RealWorld a)
    forall a s. a -> ST s (STRef s a)
    newSTRef a
    v) IO (STRef RealWorld a)
    -> (STRef RealWorld a -> IO (IORef a)) -> IO (IORef a)
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \ STRef RealWorld a
    var -> IORef a -> IO (IORef a)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (STRef RealWorld a -> IORef a
    forall a. STRef RealWorld a -> IORef a
    IORef STRef RealWorld a
    var)

    -- |Read the value of an 'IORef'.
    --
    -- Beware that the CPU executing a thread can reorder reads or writes
    -- to independent locations. See "Data.IORef#memmodel" for more details.
    readIORef   :: IORef a -> IO a
    readIORef :: forall a. IORef a -> IO a
    readIORef  (IORef STRef RealWorld a
    var) = ST RealWorld a -> IO a
    forall a. ST RealWorld a -> IO a
    stToIO (STRef RealWorld a -> ST RealWorld a
    forall s a. STRef s a -> ST s a
    readSTRef STRef RealWorld a
    var)

    -- |Write a new value into an 'IORef'.
    --
    -- This function does not create a memory barrier and can be reordered
    -- with other independent reads and writes within a thread, which may cause issues
    -- for multithreaded execution. In these cases, consider using 'GHC.Internal.Data.IORef.atomicWriteIORef'
    -- instead. See "Data.IORef#memmodel" for more details.
    writeIORef  :: IORef a -> a -> IO ()
    writeIORef :: forall a. IORef a -> a -> IO ()
    writeIORef (IORef STRef RealWorld a
    var) a
    v = ST RealWorld () -> IO ()
    forall a. ST RealWorld a -> IO a
    stToIO (STRef RealWorld a -> a -> ST RealWorld ()
    forall s a. STRef s a -> a -> ST s ()
    writeSTRef STRef RealWorld a
    var a
    v)

    -- | Atomically apply a function to the contents of an 'IORef',
    -- installing its first component in the 'IORef' and returning
    -- the old contents and the result of applying the function.
    -- The result of the function application (the pair) is not forced.
    -- As a result, this can lead to memory leaks. It is generally better
    -- to use 'atomicModifyIORef2'.
    atomicModifyIORef2Lazy :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
    atomicModifyIORef2Lazy :: forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))
    atomicModifyIORef2Lazy (IORef (STRef MutVar# RealWorld a
    r#)) a -> (a, b)
    f =
      (State# RealWorld -> (# State# RealWorld, (a, (a, b)) #))
    -> IO (a, (a, b))
    forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    IO (\State# RealWorld
    s -> case MutVar# RealWorld a
    -> (a -> (a, b))
    -> State# RealWorld
    -> (# State# RealWorld, a, (a, b) #)
    forall d a c.
    MutVar# d a -> (a -> c) -> State# d -> (# State# d, a, c #)
    atomicModifyMutVar2# MutVar# RealWorld a
    r# a -> (a, b)
    f State# RealWorld
    s of
                  (# State# RealWorld
    s', a
    old, (a, b)
    res #) -> (# State# RealWorld
    s', (a
    old, (a, b)
    res) #))

    -- | Atomically apply a function to the contents of an 'IORef',
    -- installing its first component in the 'IORef' and returning
    -- the old contents and the result of applying the function.
    -- The result of the function application (the pair) is forced,
    -- but neither of its components is.
    atomicModifyIORef2 :: IORef a -> (a -> (a,b)) -> IO (a, (a, b))
    atomicModifyIORef2 :: forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))
    atomicModifyIORef2 IORef a
    ref a -> (a, b)
    f = do
      r@(_old, (_new, _res)) <- IORef a -> (a -> (a, b)) -> IO (a, (a, b))
    forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))
    atomicModifyIORef2Lazy IORef a
    ref a -> (a, b)
    f
      return r

    -- | A version of 'GHC.Internal.Data.IORef.atomicModifyIORef' that forces
    -- the (pair) result of the function.
    atomicModifyIORefP :: IORef a -> (a -> (a,b)) -> IO b
    atomicModifyIORefP :: forall a b. IORef a -> (a -> (a, b)) -> IO b
    atomicModifyIORefP IORef a
    ref a -> (a, b)
    f = do
      (_old, (_,r)) <- IORef a -> (a -> (a, b)) -> IO (a, (a, b))
    forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))
    atomicModifyIORef2 IORef a
    ref a -> (a, b)
    f
      pure r

    -- | Atomically apply a function to the contents of an
    -- 'IORef' and return the old and new values. The result
    -- of the function is not forced. As this can lead to a
    -- memory leak, it is usually better to use `atomicModifyIORef'_`.
    atomicModifyIORefLazy_ :: IORef a -> (a -> a) -> IO (a, a)
    atomicModifyIORefLazy_ :: forall a. IORef a -> (a -> a) -> IO (a, a)
    atomicModifyIORefLazy_ (IORef (STRef MutVar# RealWorld a
    ref)) a -> a
    f = (State# RealWorld -> (# State# RealWorld, (a, a) #)) -> IO (a, a)
    forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    IO ((State# RealWorld -> (# State# RealWorld, (a, a) #)) -> IO (a, a))
    -> (State# RealWorld -> (# State# RealWorld, (a, a) #))
    -> IO (a, a)
    forall a b. (a -> b) -> a -> b
    $ \State# RealWorld
    s ->
      case MutVar# RealWorld a
    -> (a -> a) -> State# RealWorld -> (# State# RealWorld, a, a #)
    forall d a.
    MutVar# d a -> (a -> a) -> State# d -> (# State# d, a, a #)
    atomicModifyMutVar_# MutVar# RealWorld a
    ref a -> a
    f State# RealWorld
    s of
        (# State# RealWorld
    s', a
    old, a
    new #) -> (# State# RealWorld
    s', (a
    old, a
    new) #)

    -- | Atomically apply a function to the contents of an
    -- 'IORef' and return the old and new values. The result
    -- of the function is forced.
    atomicModifyIORef'_ :: IORef a -> (a -> a) -> IO (a, a)
    atomicModifyIORef'_ :: forall a. IORef a -> (a -> a) -> IO (a, a)
    atomicModifyIORef'_ IORef a
    ref a -> a
    f = do
      (old, !new) <- IORef a -> (a -> a) -> IO (a, a)
    forall a. IORef a -> (a -> a) -> IO (a, a)
    atomicModifyIORefLazy_ IORef a
    ref a -> a
    f
      return (old, new)

    -- | Atomically replace the contents of an 'IORef', returning
    -- the old contents.
    atomicSwapIORef :: IORef a -> a -> IO a
    atomicSwapIORef :: forall a. IORef a -> a -> IO a
    atomicSwapIORef (IORef (STRef MutVar# RealWorld a
    ref)) a
    new = (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    IO (MutVar# RealWorld a
    -> a -> State# RealWorld -> (# State# RealWorld, a #)
    forall d a. MutVar# d a -> a -> State# d -> (# State# d, a #)
    atomicSwapMutVar# MutVar# RealWorld a
    ref a
    new)

    -- | A strict version of 'GHC.Internal.Data.IORef.atomicModifyIORef'.  This forces both the
    -- value stored in the 'IORef' and the value returned.
    --
    -- Conceptually,
    --
    -- @
    -- atomicModifyIORef' ref f = do
    --   -- Begin atomic block
    --   old <- 'readIORef' ref
    --   let r = f old
    --       new = fst r
    --   'writeIORef' ref new
    --   -- End atomic block
    --   case r of
    --     (!_new, !res) -> pure res
    -- @
    --
    -- The actions in the \"atomic block\" are not subject to interference
    -- by other threads. In particular, the value in the 'IORef' cannot
    -- change between the 'readIORef' and 'writeIORef' invocations.
    --
    -- The new value is installed in the 'IORef' before either value is forced.
    -- So
    --
    -- @atomicModifyIORef' ref (\x -> (x+1, undefined))@
    --
    -- will increment the 'IORef' and then throw an exception in the calling
    -- thread.
    --
    -- @atomicModifyIORef' ref (\x -> (undefined, x))@
    --
    -- and
    --
    -- @atomicModifyIORef' ref (\_ -> undefined)@
    --
    -- will each raise an exception in the calling thread, but will /also/
    -- install the bottoming value in the 'IORef', where it may be read by
    -- other threads.
    --
    -- This function imposes a memory barrier, preventing reordering around
    -- the \"atomic block\"; see "Data.IORef#memmodel" for details.
    --
    -- @since base-4.6.0.0
    atomicModifyIORef' :: IORef a -> (a -> (a,b)) -> IO b
    -- See Note [atomicModifyIORef' definition]
    atomicModifyIORef' :: forall a b. IORef a -> (a -> (a, b)) -> IO b
    atomicModifyIORef' IORef a
    ref a -> (a, b)
    f = do
      (_old, (_new, !res)) <- IORef a -> (a -> (a, b)) -> IO (a, (a, b))
    forall a b. IORef a -> (a -> (a, b)) -> IO (a, (a, b))
    atomicModifyIORef2 IORef a
    ref ((a -> (a, b)) -> IO (a, (a, b)))
    -> (a -> (a, b)) -> IO (a, (a, b))
    forall a b. (a -> b) -> a -> b
    $
        \a
    old -> case a -> (a, b)
    f a
    old of
           r :: (a, b)
    r@(!a
    _new, b
    _res) -> (a, b)
    r
      pure res

    -- Note [atomicModifyIORef' definition]
    -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    -- atomicModifyIORef' was historically defined
    --
    --    atomicModifyIORef' ref f = do
    --        b <- atomicModifyIORef ref $ \a ->
    --                case f a of
    --                    v@(a',_) -> a' `seq` v
    --        b `seq` return b
    --
    -- The most obvious definition, now that we have atomicModifyMutVar2#,
    -- would be
    --
    --    atomicModifyIORef' ref f = do
    --      (_old, (!_new, !res)) <- atomicModifyIORef2 ref f
    --      pure res
    --
    -- Why do we force the new value on the "inside" instead of afterwards?
    -- I initially thought the latter would be okay, but then I realized
    -- that if we write
    --
    --   atomicModifyIORef' ref $ \x -> (x + 5, x - 5)
    --
    -- then we'll end up building a pair of thunks to calculate x + 5
    -- and x - 5. That's no good! With the more complicated definition,
    -- we avoid this problem; the result pair is strict in the new IORef
    -- contents. Of course, if the function passed to atomicModifyIORef'
    -- doesn't inline, we'll build a closure for it. But that was already
    -- true for the historical definition of atomicModifyIORef' (in terms
    -- of atomicModifyIORef), so we shouldn't lose anything. Note that
    -- in keeping with the historical behavior, we *don't* propagate the
    -- strict demand on the result inwards. In particular,
    --
    --   atomicModifyIORef' ref (\x -> (x + 1, undefined))
    --
    -- will increment the IORef and throw an exception; it will not
    -- install an undefined value in the IORef.
    --
    -- A clearer version, in my opinion (but one quite incompatible with
    -- the traditional one) would only force the new IORef value and not
    -- the result. This version would have been relatively inefficient
    -- to implement using atomicModifyMutVar#, but is just fine now.