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(..), STret(..), StateAndPtr#(..) )
25 import IOBase ( IO(..), IOResult(..), 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 ->
48 let d@(STret _ r) = action s in
51 forkPrimIO :: PrimIO a -> PrimIO a
54 forkIO :: IO () -> IO ()
55 forkIO (IO action) = IO $ \ s -> (action s) `fork` IOok s ()
57 par, fork :: Eval a => a -> b -> b
62 #if defined(__PARALLEL_HASKELL__) || defined (__GRANSIM__)
63 par x y = case (par# x) of { 0# -> parError; _ -> y }
68 #if defined(__CONCURRENT_HASKELL__) || defined (__GRANSIM__)
69 fork x y = case (fork# x) of { 0# -> parError; _ -> y }
76 %************************************************************************
78 \subsection[PreludeGlaST-mvars]{M-Structures}
80 %************************************************************************
82 M-Vars are rendezvous points for concurrent threads. They begin
83 empty, and any attempt to read an empty M-Var blocks. When an M-Var
84 is written, a single blocked thread may be freed. Reading an M-Var
85 toggles its state from full back to empty. Therefore, any value
86 written to an M-Var may only be read once. Multiple reads and writes
87 are allowed, but there must be at least one read between any two
91 --Defined in IOBase to avoid cycle: data MVar a = MVar (SynchVar# RealWorld a)
93 newEmptyMVar :: IO (MVar a)
95 newEmptyMVar = IO $ \ s# ->
96 case newSynchVar# s# of
97 StateAndSynchVar# s2# svar# -> IOok s2# (MVar svar#)
99 takeMVar :: MVar a -> IO a
101 takeMVar (MVar mvar#) = IO $ \ s# ->
102 case takeMVar# mvar# s# of
103 StateAndPtr# s2# r -> IOok s2# r
105 putMVar :: MVar a -> a -> IO ()
107 putMVar (MVar mvar#) x = IO $ \ s# ->
108 case putMVar# mvar# x s# of
111 newMVar :: a -> IO (MVar a)
114 newEmptyMVar >>= \ mvar ->
115 putMVar mvar value >>
118 readMVar :: MVar a -> IO a
121 takeMVar mvar >>= \ value ->
122 putMVar mvar value >>
125 swapMVar :: MVar a -> a -> IO a
128 takeMVar mvar >>= \ old ->
134 %************************************************************************
136 \subsection{Thread waiting}
138 %************************************************************************
140 @threadDelay@ delays rescheduling of a thread until the indicated
141 number of microseconds have elapsed. Generally, the microseconds are
142 counted by the context switch timer, which ticks in virtual time;
143 however, when there are no runnable threads, we don't accumulate any
144 virtual time, so we start ticking in real time. (The granularity is
145 the effective resolution of the context switch timer, so it is
146 affected by the RTS -C option.)
148 @threadWaitRead@ delays rescheduling of a thread until input on the
149 specified file descriptor is available for reading (just like select).
150 @threadWaitWrite@ is similar, but for writing on a file descriptor.
153 threadDelay, threadWaitRead, threadWaitWrite :: Int -> IO ()
155 threadDelay (I# x#) = IO $ \ s# ->
159 threadWaitRead (I# x#) = IO $ \ s# ->
160 case waitRead# x# s# of
163 threadWaitWrite (I# x#) = IO $ \ s# ->
164 case waitWrite# x# s# of
168 %*********************************************************
170 \subsection{Ghastly return types}
172 %*********************************************************
175 data StateAndSynchVar# s elt = StateAndSynchVar# (State# s) (SynchVar# s elt)