1 {-# LANGUAGE CPP, NoImplicitPrelude, MagicHash, UnboxedTuples #-}
3 -----------------------------------------------------------------------------
6 -- Copyright : (c) The University of Glasgow 2001
7 -- License : BSD-style (see the file libraries/base/LICENSE)
9 -- Maintainer : libraries@haskell.org
10 -- Stability : experimental
11 -- Portability : portable
13 -- Mutable references in the IO monad.
15 -----------------------------------------------------------------------------
20 IORef, -- abstract, instance of: Eq, Typeable
21 newIORef, -- :: a -> IO (IORef a)
22 readIORef, -- :: IORef a -> IO a
23 writeIORef, -- :: IORef a -> a -> IO ()
24 modifyIORef, -- :: IORef a -> (a -> a) -> IO ()
25 atomicModifyIORef, -- :: IORef a -> (a -> (a,b)) -> IO b
27 #if !defined(__PARALLEL_HASKELL__) && defined(__GLASGOW_HASKELL__)
28 mkWeakIORef, -- :: IORef a -> IO () -> IO (Weak (IORef a))
40 #ifdef __GLASGOW_HASKELL__
44 import GHC.IORef hiding (atomicModifyIORef)
45 import qualified GHC.IORef
46 #if !defined(__PARALLEL_HASKELL__)
49 #endif /* __GLASGOW_HASKELL__ */
61 #if defined(__GLASGOW_HASKELL__) && !defined(__PARALLEL_HASKELL__)
62 -- |Make a 'Weak' pointer to an 'IORef', using the second argument as a finalizer
63 -- to run when 'IORef' is garbage-collected
64 mkWeakIORef :: IORef a -> IO () -> IO (Weak (IORef a))
65 mkWeakIORef r@(IORef (STRef r#)) f = IO $ \s ->
66 case mkWeak# r# r f s of (# s1, w #) -> (# s1, Weak w #)
69 -- |Mutate the contents of an 'IORef'
70 modifyIORef :: IORef a -> (a -> a) -> IO ()
71 modifyIORef ref f = readIORef ref >>= writeIORef ref . f
74 -- |Atomically modifies the contents of an 'IORef'.
76 -- This function is useful for using 'IORef' in a safe way in a multithreaded
77 -- program. If you only have one 'IORef', then using 'atomicModifyIORef' to
78 -- access and modify it will prevent race conditions.
80 -- Extending the atomicity to multiple 'IORef's is problematic, so it
81 -- is recommended that if you need to do anything more complicated
82 -- then using 'Control.Concurrent.MVar.MVar' instead is a good idea.
84 atomicModifyIORef :: IORef a -> (a -> (a,b)) -> IO b
85 #if defined(__GLASGOW_HASKELL__)
86 atomicModifyIORef = GHC.IORef.atomicModifyIORef
88 #elif defined(__HUGS__)
89 atomicModifyIORef = plainModifyIORef -- Hugs has no preemption
90 where plainModifyIORef r f = do
92 case f a of (a',b) -> writeIORef r a' >> return b
93 #elif defined(__NHC__)
94 atomicModifyIORef r f =
95 excludeFinalisers $ do
104 In a concurrent program, 'IORef' operations may appear out-of-order
105 to another thread, depending on the memory model of the underlying
106 processor architecture. For example, on x86, loads can move ahead
107 of stores, so in the following example:
109 > maybePrint :: IORef Bool -> IORef Bool -> IO ()
110 > maybePrint myRef yourRef = do
111 > writeIORef myRef True
112 > yourVal <- readIORef yourRef
113 > unless yourVal $ putStrLn "critical section"
117 > r1 <- newIORef False
118 > r2 <- newIORef False
119 > forkIO $ maybePrint r1 r2
120 > forkIO $ maybePrint r2 r1
121 > threadDelay 1000000
123 it is possible that the string @"critical section"@ is printed
124 twice, even though there is no interleaving of the operations of the
125 two threads that allows that outcome. The memory model of x86
126 allows 'readIORef' to happen before the earlier 'writeIORef'.
128 The implementation is required to ensure that reordering of memory
129 operations cannot cause type-correct code to go wrong. In
130 particular, when inspecting the value read from an 'IORef', the
131 memory writes that created that value must have occurred from the
132 point of view of the current therad.
134 'atomicModifyIORef' acts as a barrier to reordering. Multiple
135 'atomicModifyIORef' operations occur in strict program order. An
136 'atomicModifyIORef' is never observed to take place ahead of any
137 earlier (in program order) 'IORef' operations, or after any later