2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[PrelConc]{Module @PrelConc@}
7 Basic concurrency stuff
10 {-# OPTIONS -fno-implicit-prelude #-}
17 -- Forking and suchlike
21 {-threadDelay, threadWaitRead, threadWaitWrite,-}
31 -- use with care (see comment.)
36 import PrelErr ( parError, seqError )
37 import PrelST ( liftST )
38 import PrelIOBase ( IO(..), MVar(..), unsafePerformIO )
39 import PrelBase ( Int(..) )
41 infixr 0 `par`, `fork`
44 %************************************************************************
46 \subsection{@ThreadId@, @par@, and @fork@}
48 %************************************************************************
51 data ThreadId = ThreadId ThreadId#
52 -- ToDo: data ThreadId = ThreadId (WeakPair ThreadId# ())
53 -- But since ThreadId# is unlifted, the WeakPair type must use open
56 forkIO :: IO () -> IO ThreadId
57 forkIO action = IO $ \ s ->
58 case (fork# action s) of (# s1, id #) -> (# s1, ThreadId id #)
60 killThread :: ThreadId -> IO ()
61 killThread (ThreadId id) = IO $ \ s ->
62 case (killThread# id s) of s1 -> (# s1, () #)
64 -- "seq" is defined a bit wierdly (see below)
66 -- The reason for the strange "0# -> parError" case is that
67 -- it fools the compiler into thinking that seq is non-strict in
68 -- its second argument (even if it inlines seq at the call site).
69 -- If it thinks seq is strict in "y", then it often evaluates
70 -- "y" before "x", which is totally wrong.
72 -- Just before converting from Core to STG there's a bit of magic
73 -- that recognises the seq# and eliminates the duff case.
77 seq x y = case (seq# x) of { 0# -> seqError; _ -> y }
79 par, fork :: a -> b -> b
83 #if defined(__PARALLEL_HASKELL__) || defined (__GRANSIM__)
84 par x y = case (par# x) of { 0# -> parError; _ -> y }
89 fork x y = unsafePerformIO (forkIO (x `seq` return ())) `seq` y
93 %************************************************************************
95 \subsection[mvars]{M-Structures}
97 %************************************************************************
99 M-Vars are rendezvous points for concurrent threads. They begin
100 empty, and any attempt to read an empty M-Var blocks. When an M-Var
101 is written, a single blocked thread may be freed. Reading an M-Var
102 toggles its state from full back to empty. Therefore, any value
103 written to an M-Var may only be read once. Multiple reads and writes
104 are allowed, but there must be at least one read between any two
108 --Defined in IOBase to avoid cycle: data MVar a = MVar (SynchVar# RealWorld a)
110 instance Eq (MVar a) where
111 (MVar mvar1#) == (MVar mvar2#) = sameMVar# mvar1# mvar2#
113 newEmptyMVar :: IO (MVar a)
115 newEmptyMVar = IO $ \ s# ->
117 (# s2#, svar# #) -> (# s2#, MVar svar# #)
119 takeMVar :: MVar a -> IO a
121 takeMVar (MVar mvar#) = IO $ \ s# -> takeMVar# mvar# s#
123 putMVar :: MVar a -> a -> IO ()
125 putMVar (MVar mvar#) x = IO $ \ s# ->
126 case putMVar# mvar# x s# of
129 newMVar :: a -> IO (MVar a)
132 newEmptyMVar >>= \ mvar ->
133 putMVar mvar value >>
136 readMVar :: MVar a -> IO a
139 takeMVar mvar >>= \ value ->
140 putMVar mvar value >>
143 swapMVar :: MVar a -> a -> IO a
146 takeMVar mvar >>= \ old ->
151 Low-level op. for checking whether an MVar is filled-in or not.
152 Notice that the boolean value returned is just a snapshot of
153 the state of the MVar. By the time you get to react on its result,
154 the MVar may have been filled (or emptied) - so be extremely
155 careful when using this operation.
157 If you can re-work your abstractions to avoid having to
158 depend on isEmptyMVar, then you're encouraged to do so,
159 i.e., consider yourself warned about the imprecision in
160 general of isEmptyMVar :-)
162 isEmptyMVar :: MVar a -> IO Bool
163 isEmptyMVar (MVar mv#) = IO $ \ s# ->
164 case isEmptyMVar# mv# s# of
165 (# s2#, flg #) -> (# s2#, not (flg ==# 0#) #)
169 %************************************************************************
171 \subsection{Thread waiting}
173 %************************************************************************
175 @threadDelay@ delays rescheduling of a thread until the indicated
176 number of microseconds have elapsed. Generally, the microseconds are
177 counted by the context switch timer, which ticks in virtual time;
178 however, when there are no runnable threads, we don't accumulate any
179 virtual time, so we start ticking in real time. (The granularity is
180 the effective resolution of the context switch timer, so it is
181 affected by the RTS -C option.)
183 @threadWaitRead@ delays rescheduling of a thread until input on the
184 specified file descriptor is available for reading (just like select).
185 @threadWaitWrite@ is similar, but for writing on a file descriptor.
189 threadDelay, threadWaitRead, threadWaitWrite :: Int -> IO ()
191 threadDelay (I# x#) = IO $ \ s# ->
195 threadWaitRead (I# x#) = IO $ \ s# ->
196 case waitRead# x# s# of
199 threadWaitWrite (I# x#) = IO $ \ s# ->
200 case waitWrite# x# s# of