{-# LANGUAGE MagicHash #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE Trustworthy #-} {-# LANGUAGE UnboxedTuples #-} ----------------------------------------------------------------------------- -- | -- Module : GHC.Internal.Data.IORef -- Copyright : (c) The University of Glasgow 2001 -- License : BSD-style (see the file libraries/base/LICENSE) -- -- Maintainer : libraries@haskell.org -- Stability : stable -- Portability : portable -- -- Mutable references in the IO monad. -- ----------------------------------------------------------------------------- module GHC.Internal.Data.IORef ( -- * IORefs IORef, -- abstract, instance of: Eq, Typeable newIORef, readIORef, writeIORef, modifyIORef, modifyIORef', atomicModifyIORef, atomicModifyIORef', atomicWriteIORef, mkWeakIORef, ) where import GHC.Internal.Base import GHC.Internal.STRef import GHC.Internal.IORef import GHC.Internal.Weak -- |Make a 'Weak' pointer to an 'IORef', using the second argument as a finalizer -- to run when 'IORef' is garbage-collected mkWeakIORef :: IORef a -> IO () -> IO (Weak (IORef a)) mkWeakIORef :: forall a. IORef a -> IO () -> IO (Weak (IORef a)) mkWeakIORef r :: IORef a r@(IORef (STRef MutVar# RealWorld a r#)) (IO State# RealWorld -> (# State# RealWorld, () #) finalizer) = (State# RealWorld -> (# State# RealWorld, Weak (IORef a) #)) -> IO (Weak (IORef a)) forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a IO ((State# RealWorld -> (# State# RealWorld, Weak (IORef a) #)) -> IO (Weak (IORef a))) -> (State# RealWorld -> (# State# RealWorld, Weak (IORef a) #)) -> IO (Weak (IORef a)) forall a b. (a -> b) -> a -> b $ \State# RealWorld s -> case MutVar# RealWorld a -> IORef a -> (State# RealWorld -> (# State# RealWorld, () #)) -> State# RealWorld -> (# State# RealWorld, Weak# (IORef a) #) forall a b c. a -> b -> (State# RealWorld -> (# State# RealWorld, c #)) -> State# RealWorld -> (# State# RealWorld, Weak# b #) mkWeak# MutVar# RealWorld a r# IORef a r State# RealWorld -> (# State# RealWorld, () #) finalizer State# RealWorld s of (# State# RealWorld s1, Weak# (IORef a) w #) -> (# State# RealWorld s1, Weak# (IORef a) -> Weak (IORef a) forall v. Weak# v -> Weak v Weak Weak# (IORef a) w #) -- |Mutate the contents of an 'IORef', combining 'readIORef' and 'writeIORef'. -- This is not an atomic update, consider using 'atomicModifyIORef' when -- operating in a multithreaded environment. -- -- Be warned that 'modifyIORef' does not apply the function strictly. This -- means if the program calls 'modifyIORef' many times, but seldom uses the -- value, thunks will pile up in memory resulting in a space leak. This is a -- common mistake made when using an IORef as a counter. For example, the -- following will likely produce a stack overflow: -- -- >ref <- newIORef 0 -- >replicateM_ 1000000 $ modifyIORef ref (+1) -- >readIORef ref >>= print -- -- To avoid this problem, use 'modifyIORef'' instead. modifyIORef :: IORef a -> (a -> a) -> IO () modifyIORef :: forall a. IORef a -> (a -> a) -> IO () modifyIORef IORef a ref a -> a f = IORef a -> IO a forall a. IORef a -> IO a readIORef IORef a ref IO a -> (a -> IO ()) -> IO () forall a b. IO a -> (a -> IO b) -> IO b forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= IORef a -> a -> IO () forall a. IORef a -> a -> IO () writeIORef IORef a ref (a -> IO ()) -> (a -> a) -> a -> IO () forall b c a. (b -> c) -> (a -> b) -> a -> c . a -> a f -- |Strict version of 'modifyIORef'. -- This is not an atomic update, consider using 'atomicModifyIORef'' when -- operating in a multithreaded environment. -- -- @since base-4.6.0.0 modifyIORef' :: IORef a -> (a -> a) -> IO () modifyIORef' :: forall a. IORef a -> (a -> a) -> IO () modifyIORef' IORef a ref a -> a f = do x <- IORef a -> IO a forall a. IORef a -> IO a readIORef IORef a ref let x' = a -> a f a x x' `seq` writeIORef ref x' -- |Atomically modifies the contents of an 'IORef'. -- -- This function is useful for using 'IORef' in a safe way in a multithreaded -- program. If you only have one 'IORef', then using 'atomicModifyIORef' to -- access and modify it will prevent race conditions. -- -- Extending the atomicity to multiple 'IORef's is problematic, so it -- is recommended that if you need to do anything more complicated -- then using 'Control.Concurrent.MVar.MVar' instead is a good idea. -- -- 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 section labeled \"atomic block\" are not subject to -- interference from other threads. In particular, it is impossible for the -- value in the 'IORef' to change between the 'readIORef' and 'writeIORef' -- invocations. -- -- The user-supplied function is applied to the value stored in the 'IORef', -- yielding a new value to store in the 'IORef' and a value to return. After -- the new value is (lazily) stored in the 'IORef', @atomicModifyIORef@ forces -- the result pair, but does not force either component of the result. To force -- /both/ components, use 'atomicModifyIORef''. -- -- Note that -- -- @atomicModifyIORef ref (\_ -> undefined)@ -- -- will 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. -- atomicModifyIORef :: IORef a -> (a -> (a,b)) -> IO b 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) f pure res -- | Variant of 'writeIORef'. The prefix "atomic" relates to a fact that -- it imposes a reordering barrier, similar to 'atomicModifyIORef'. -- Such a write will not be reordered with other reads -- or writes even on CPUs with weak memory model. -- -- @since base-4.6.0.0 atomicWriteIORef :: IORef a -> a -> IO () atomicWriteIORef :: forall a. IORef a -> a -> IO () atomicWriteIORef IORef a ref a a = do _ <- IORef a -> a -> IO a forall a. IORef a -> a -> IO a atomicSwapIORef IORef a ref a a pure ()