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
22 import STBase ( PrimIO(..), ST(..), State(..), StateAndPtr#(..) )
23 import IOBase ( IO(..) )
24 import GHCerr ( parError )
25 import PrelBase ( Int(..) )
26 import GHC ( fork#, delay#, waitRead#, waitWrite#,
27 SynchVar#, newSynchVar#, takeMVar#, putMVar#,
31 infixr 0 `par`, `fork`
36 %************************************************************************
38 \subsection{@par@, and @fork@}
40 %************************************************************************
43 forkST :: ST s a -> ST s a
45 forkST (ST action) = ST $ \ s ->
51 fork__ x y = case (fork# x) of { 0# -> parError; _ -> y }
53 forkPrimIO :: PrimIO a -> PrimIO a
56 forkIO :: IO () -> IO ()
57 forkIO (IO (ST action)) = IO $ ST $ \ s ->
61 new_s `fork` (Right (), s)
63 par, fork :: Eval a => a -> b -> b
68 #ifdef __CONCURRENT_HASKELL__
69 par x y = case (par# x) of { 0# -> parError; _ -> y }
70 fork x y = case (fork# x) of { 0# -> parError; _ -> y }
77 %************************************************************************
79 \subsection[PreludeGlaST-mvars]{M-Structures}
81 %************************************************************************
83 M-Vars are rendezvous points for concurrent threads. They begin
84 empty, and any attempt to read an empty M-Var blocks. When an M-Var
85 is written, a single blocked thread may be freed. Reading an M-Var
86 toggles its state from full back to empty. Therefore, any value
87 written to an M-Var may only be read once. Multiple reads and writes
88 are allowed, but there must be at least one read between any two
92 data MVar a = MVar (SynchVar# RealWorld a)
94 newEmptyMVar :: IO (MVar a)
96 newEmptyMVar = IO $ ST $ \ (S# s#) ->
97 case newSynchVar# s# of
98 StateAndSynchVar# s2# svar# -> (Right (MVar svar#), S# s2#)
100 takeMVar :: MVar a -> IO a
102 takeMVar (MVar mvar#) = IO $ ST $ \ (S# s#) ->
103 case takeMVar# mvar# s# of
104 StateAndPtr# s2# r -> (Right r, S# s2#)
106 putMVar :: MVar a -> a -> IO ()
108 putMVar (MVar mvar#) x = IO $ ST $ \ (S# s#) ->
109 case putMVar# mvar# x s# of
110 s2# -> (Right (), S# s2#)
112 newMVar :: a -> IO (MVar a)
115 newEmptyMVar >>= \ mvar ->
116 putMVar mvar value >>
119 readMVar :: MVar a -> IO a
122 takeMVar mvar >>= \ value ->
123 putMVar mvar value >>
126 swapMVar :: MVar a -> a -> IO a
129 takeMVar mvar >>= \ old ->
135 %************************************************************************
137 \subsection{Thread waiting}
139 %************************************************************************
141 @threadDelay@ delays rescheduling of a thread until the indicated
142 number of microseconds have elapsed. Generally, the microseconds are
143 counted by the context switch timer, which ticks in virtual time;
144 however, when there are no runnable threads, we don't accumulate any
145 virtual time, so we start ticking in real time. (The granularity is
146 the effective resolution of the context switch timer, so it is
147 affected by the RTS -C option.)
149 @threadWait@ delays rescheduling of a thread until input on the
150 specified file descriptor is available for reading (just like select).
153 threadDelay, threadWaitRead, threadWaitWrite :: Int -> IO ()
155 threadDelay (I# x#) = IO $ ST $ \ (S# s#) ->
157 s2# -> (Right (), S# s2#)
159 threadWaitRead (I# x#) = IO $ ST $ \ (S# s#) ->
160 case waitRead# x# s# of
161 s2# -> (Right (), S# s2#)
163 threadWaitWrite (I# x#) = IO $ ST $ \ (S# s#) ->
164 case waitWrite# x# s# of
165 s2# -> (Right (), S# s2#)
168 %*********************************************************
170 \subsection{Ghastly return types}
172 %*********************************************************
175 data StateAndSynchVar# s elt = StateAndSynchVar# (State# s) (SynchVar# s elt)