Go to the first, previous, next, last section, table of contents.
GHC provides a `Concurrent' module, a common interface to a
collection of useful concurrency abstractions, including those
mentioned in the "concurrent paper".
Just put `import Concurrent' into your modules, and away you go.
To create a "required thread":
forkIO :: IO a -> IO a
The `Concurrent' interface also provides access to "I-Vars"
and "M-Vars", which are two flavours of synchronising variables.
`IVars' are write-once
variables. They start out empty, and any threads that attempt to read
them will block until they are filled. Once they are written, any
blocked threads are freed, and additional reads are permitted.
Attempting to write a value to a full `IVar' results in a runtime
error. Interface:
newIVar :: IO (IVar a)
readIVar :: IVar a -> IO a
writeIVar :: IVar a -> a -> IO ()
`MVars' are rendezvous points,
mostly for concurrent threads. They begin empty, and any attempt to
read an empty `MVar' blocks. When an `MVar' is written, a
single blocked thread may be freed. Reading an `MVar' toggles its
state from full back to empty. Therefore, any value written to an
`MVar' may only be read once. Multiple reads and writes are
allowed, but there must be at least one read between any two
writes. Interface:
newEmptyMVar :: IO (MVar a)
newMVar :: a -> IO (MVar a)
takeMVar :: MVar a -> IO a
putMVar :: MVar a -> a -> IO ()
readMVar :: MVar a -> IO a
swapMVar :: MVar a -> a -> IO a
A channel variable (`CVar') is a one-element channel, as
described in the paper:
data CVar a
newCVar :: IO (CVar a)
putCVar :: CVar a -> a -> IO ()
getCVar :: CVar a -> IO a
A `Channel' is an unbounded channel:
data Chan a
newChan :: IO (Chan a)
putChan :: Chan a -> a -> IO ()
getChan :: Chan a -> IO a
dupChan :: Chan a -> IO (Chan a)
unGetChan :: Chan a -> a -> IO ()
getChanContents :: Chan a -> IO [a]
General and quantity semaphores:
data QSem
newQSem :: Int -> IO QSem
waitQSem :: QSem -> IO ()
signalQSem :: QSem -> IO ()
data QSemN
newQSemN :: Int -> IO QSemN
signalQSemN :: QSemN -> Int -> IO ()
waitQSemN :: QSemN -> Int -> IO ()
Merging streams -- binary and n-ary:
mergeIO :: [a] -> [a] -> IO [a]
nmergeIO :: [[a]] -> IO [a]
A Sample variable (`SampleVar') is slightly different from a
normal `MVar':
-
Reading an empty `SampleVar' causes the reader to block
(same as `takeMVar' on empty `MVar').
-
Reading a filled `SampleVar' empties it and returns value.
(same as `takeMVar')
-
Writing to an empty `SampleVar' fills it with a value, and
potentially, wakes up a blocked reader (same as for `putMVar' on empty `MVar').
-
Writing to a filled `SampleVar' overwrites the current value.
(different from `putMVar' on full `MVar'.)
type SampleVar a = MVar (Int, MVar a)
emptySampleVar :: SampleVar a -> IO ()
newSampleVar :: IO (SampleVar a)
readSample :: SampleVar a -> IO a
writeSample :: SampleVar a -> a -> IO ()
Finally, there are operations to delay a concurrent thread, and to
make one wait:
threadDelay :: Int -> IO () -- delay rescheduling for N microseconds
threadWaitRead :: Int -> IO () -- wait for input on specified file descriptor
threadWaitWrite :: Int -> IO () -- (read and write, respectively).
Go to the first, previous, next, last section, table of contents.