2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[ConcBase]{Module @ConcBase@}
7 Basic concurrency stuff
11 -- Forking and suchlike
16 threadDelay, threadWaitRead, threadWaitWrite,
19 MVar, newMVar, newEmptyMVar, takeMVar, putMVar, readMVar, swapMVar
23 import STBase ( PrimIO(..), ST(..), State(..), StateAndPtr#(..) )
24 import IOBase ( IO(..) )
25 import GHCerr ( parError )
26 import PrelBase ( Int(..) )
27 import GHC ( fork#, delay#, waitRead#, waitWrite#,
28 SynchVar#, newSynchVar#, takeMVar#, putMVar#,
32 infixr 0 `par`, `fork`
37 %************************************************************************
39 \subsection{@par@, and @fork@}
41 %************************************************************************
44 forkST :: ST s a -> ST s a
46 forkST (ST action) = ST $ \ s ->
52 fork__ x y = case (fork# x) of { 0# -> parError; _ -> y }
54 forkPrimIO :: PrimIO a -> PrimIO a
57 forkIO :: IO () -> IO ()
58 forkIO (IO (ST action)) = IO $ ST $ \ s ->
62 new_s `fork` (Right (), s)
64 par, fork :: Eval a => a -> b -> b
69 #ifdef __CONCURRENT_HASKELL__
70 par x y = case (par# x) of { 0# -> parError; _ -> y }
71 fork x y = case (fork# x) of { 0# -> parError; _ -> y }
78 %************************************************************************
80 \subsection[PreludeGlaST-mvars]{M-Structures}
82 %************************************************************************
84 M-Vars are rendezvous points for concurrent threads. They begin
85 empty, and any attempt to read an empty M-Var blocks. When an M-Var
86 is written, a single blocked thread may be freed. Reading an M-Var
87 toggles its state from full back to empty. Therefore, any value
88 written to an M-Var may only be read once. Multiple reads and writes
89 are allowed, but there must be at least one read between any two
93 data MVar a = MVar (SynchVar# RealWorld a)
95 newEmptyMVar :: IO (MVar a)
97 newEmptyMVar = IO $ ST $ \ (S# s#) ->
98 case newSynchVar# s# of
99 StateAndSynchVar# s2# svar# -> (Right (MVar svar#), S# s2#)
101 takeMVar :: MVar a -> IO a
103 takeMVar (MVar mvar#) = IO $ ST $ \ (S# s#) ->
104 case takeMVar# mvar# s# of
105 StateAndPtr# s2# r -> (Right r, S# s2#)
107 putMVar :: MVar a -> a -> IO ()
109 putMVar (MVar mvar#) x = IO $ ST $ \ (S# s#) ->
110 case putMVar# mvar# x s# of
111 s2# -> (Right (), S# s2#)
113 newMVar :: a -> IO (MVar a)
116 newEmptyMVar >>= \ mvar ->
117 putMVar mvar value >>
120 readMVar :: MVar a -> IO a
123 takeMVar mvar >>= \ value ->
124 putMVar mvar value >>
127 swapMVar :: MVar a -> a -> IO a
130 takeMVar mvar >>= \ old ->
136 %************************************************************************
138 \subsection{Thread waiting}
140 %************************************************************************
142 @threadDelay@ delays rescheduling of a thread until the indicated
143 number of microseconds have elapsed. Generally, the microseconds are
144 counted by the context switch timer, which ticks in virtual time;
145 however, when there are no runnable threads, we don't accumulate any
146 virtual time, so we start ticking in real time. (The granularity is
147 the effective resolution of the context switch timer, so it is
148 affected by the RTS -C option.)
150 @threadWait@ delays rescheduling of a thread until input on the
151 specified file descriptor is available for reading (just like select).
154 threadDelay, threadWaitRead, threadWaitWrite :: Int -> IO ()
156 threadDelay (I# x#) = IO $ ST $ \ (S# s#) ->
158 s2# -> (Right (), S# s2#)
160 threadWaitRead (I# x#) = IO $ ST $ \ (S# s#) ->
161 case waitRead# x# s# of
162 s2# -> (Right (), S# s2#)
164 threadWaitWrite (I# x#) = IO $ ST $ \ (S# s#) ->
165 case waitWrite# x# s# of
166 s2# -> (Right (), S# s2#)
169 %*********************************************************
171 \subsection{Ghastly return types}
173 %*********************************************************
176 data StateAndSynchVar# s elt = StateAndSynchVar# (State# s) (SynchVar# s elt)