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

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

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

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

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

-- |A mutable variable in the 'IO' monad
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
/= :: IORef a -> IORef a -> Bool
$c/= :: forall a. IORef a -> IORef a -> Bool
== :: IORef a -> IORef a -> Bool
$c== :: forall a. IORef a -> IORef a -> Bool
Eq
  -- ^ Pointer equality.
  --
  -- @since 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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ STRef RealWorld a
var -> IORef a -> IO (IORef 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'
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'
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 :: (a, (a, b))
r@(a
_old, (a
_new, b
_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
  (a, (a, b)) -> IO (a, (a, b))
forall (m :: * -> *) a. Monad m => a -> m a
return (a, (a, b))
r

-- | A version of '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
  (a
_old, (a
_,b
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
  b -> IO b
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
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
  (a
old, !a
new) <- IORef a -> (a -> a) -> IO (a, a)
forall a. IORef a -> (a -> a) -> IO (a, a)
atomicModifyIORefLazy_ IORef a
ref a -> a
f
  (a, a) -> IO (a, a)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
old, a
new)

-- | Atomically replace the contents of an 'IORef', returning
-- the old contents.
atomicSwapIORef :: IORef a -> a -> IO a
-- Bad implementation! This will be a primop shortly.
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 ((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)
-> (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s ->
  case MutVar# RealWorld a
-> (a -> Box a)
-> State# RealWorld
-> (# State# RealWorld, a, Box a #)
forall d a c.
MutVar# d a -> (a -> c) -> State# d -> (# State# d, a, c #)
atomicModifyMutVar2# MutVar# RealWorld a
ref (\a
_old -> a -> Box a
forall a. a -> Box a
Box a
new) State# RealWorld
s of
    (# State# RealWorld
s', a
old, Box a
_new #) -> (# State# RealWorld
s', a
old #)

data Box a = Box a

-- | Strict version of 'Data.IORef.atomicModifyIORef'. This forces both
-- the value stored in the 'IORef' and the value returned. The new value
-- is installed in the 'IORef' before the returned value is forced.
-- So
--
-- @atomicModifyIORef' ref (\x -> (x+1, undefined))@
--
-- will increment the 'IORef' and then throw an exception in the calling
-- thread.
--
-- @since 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
  (a
_old, (a
_new, !b
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
  b -> IO b
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
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.