2 % (c) The AQUA Project, Glasgow University, 1994-1996
5 \section[ConcBase]{Module @ConcBase@}
7 Basic concurrency stuff
10 {-# OPTIONS -fno-implicit-prelude #-}
12 -- Forking and suchlike
17 threadDelay, threadWaitRead, threadWaitWrite,
20 MVar, newMVar, newEmptyMVar, takeMVar, putMVar, readMVar, swapMVar
24 import STBase ( PrimIO(..), ST(..), State(..), StateAndPtr#(..) )
25 import IOBase ( IO(..), MVar(..) )
26 import GHCerr ( parError )
27 import PrelBase ( Int(..) )
28 import GHC ( fork#, delay#, waitRead#, waitWrite#,
29 SynchVar#, newSynchVar#, takeMVar#, putMVar#,
30 State#, RealWorld, par#
33 infixr 0 `par`, `fork`
38 %************************************************************************
40 \subsection{@par@, and @fork@}
42 %************************************************************************
45 forkST :: ST s a -> ST s a
47 forkST (ST action) = ST $ \ s ->
53 fork__ x y = case (fork# x) of { 0# -> parError; _ -> y }
55 forkPrimIO :: PrimIO a -> PrimIO a
58 forkIO :: IO () -> IO ()
59 forkIO (IO (ST action)) = IO $ ST $ \ s ->
63 new_s `fork` (Right (), s)
65 par, fork :: Eval a => a -> b -> b
70 #if defined(__PARALLEL_HASKELL__) || defined (__GRANSIM__)
71 par x y = case (par# x) of { 0# -> parError; _ -> y }
76 #if defined(__CONCURRENT_HASKELL__) || defined (__GRANSIM__)
77 fork x y = case (fork# x) of { 0# -> parError; _ -> y }
84 %************************************************************************
86 \subsection[PreludeGlaST-mvars]{M-Structures}
88 %************************************************************************
90 M-Vars are rendezvous points for concurrent threads. They begin
91 empty, and any attempt to read an empty M-Var blocks. When an M-Var
92 is written, a single blocked thread may be freed. Reading an M-Var
93 toggles its state from full back to empty. Therefore, any value
94 written to an M-Var may only be read once. Multiple reads and writes
95 are allowed, but there must be at least one read between any two
99 --Defined in IOBase to avoid cycle: data MVar a = MVar (SynchVar# RealWorld a)
101 newEmptyMVar :: IO (MVar a)
103 newEmptyMVar = IO $ ST $ \ (S# s#) ->
104 case newSynchVar# s# of
105 StateAndSynchVar# s2# svar# -> (Right (MVar svar#), S# s2#)
107 takeMVar :: MVar a -> IO a
109 takeMVar (MVar mvar#) = IO $ ST $ \ (S# s#) ->
110 case takeMVar# mvar# s# of
111 StateAndPtr# s2# r -> (Right r, S# s2#)
113 putMVar :: MVar a -> a -> IO ()
115 putMVar (MVar mvar#) x = IO $ ST $ \ (S# s#) ->
116 case putMVar# mvar# x s# of
117 s2# -> (Right (), S# s2#)
119 newMVar :: a -> IO (MVar a)
122 newEmptyMVar >>= \ mvar ->
123 putMVar mvar value >>
126 readMVar :: MVar a -> IO a
129 takeMVar mvar >>= \ value ->
130 putMVar mvar value >>
133 swapMVar :: MVar a -> a -> IO a
136 takeMVar mvar >>= \ old ->
142 %************************************************************************
144 \subsection{Thread waiting}
146 %************************************************************************
148 @threadDelay@ delays rescheduling of a thread until the indicated
149 number of microseconds have elapsed. Generally, the microseconds are
150 counted by the context switch timer, which ticks in virtual time;
151 however, when there are no runnable threads, we don't accumulate any
152 virtual time, so we start ticking in real time. (The granularity is
153 the effective resolution of the context switch timer, so it is
154 affected by the RTS -C option.)
156 @threadWaitRead@ delays rescheduling of a thread until input on the
157 specified file descriptor is available for reading (just like select).
158 @threadWaitWrite@ is similar, but for writing on a file descriptor.
161 threadDelay, threadWaitRead, threadWaitWrite :: Int -> IO ()
163 threadDelay (I# x#) = IO $ ST $ \ (S# s#) ->
165 s2# -> (Right (), S# s2#)
167 threadWaitRead (I# x#) = IO $ ST $ \ (S# s#) ->
168 case waitRead# x# s# of
169 s2# -> (Right (), S# s2#)
171 threadWaitWrite (I# x#) = IO $ ST $ \ (S# s#) ->
172 case waitWrite# x# s# of
173 s2# -> (Right (), S# s2#)
176 %*********************************************************
178 \subsection{Ghastly return types}
180 %*********************************************************
183 data StateAndSynchVar# s elt = StateAndSynchVar# (State# s) (SynchVar# s elt)