Again, check Simon's Web page for publications about Parallel Haskell
(including ``GUM'', the key bits of the runtime system).
-Some details about Concurrent and Parallel Haskell follow.
-
-%************************************************************************
-%* *
-<sect2>Language features specific to Concurrent Haskell
-<label id="concurrent-haskell">
-<p>
-<nidx>Concurrent Haskell---features</nidx>
-%* *
-%************************************************************************
-
-%************************************************************************
-%* *
-<sect3>The @Concurrent@ interface (recommended)
-<label id="concurrent-interface">
-<p>
-<nidx>Concurrent interface</nidx>
-%* *
-%************************************************************************
-
-GHC provides a @Concurrent@ module, a common interface to a
-collection of useful concurrency abstractions, including those
-mentioned in the ``concurrent paper''.
-
-Just add the flag @-syslib concurrent@ to your GHC command line and
-put @import Concurrent@ into your modules, and away you go. To create
-a ``required thread'':
-
-<tscreen><verb>
-forkIO :: IO () -> IO ThreadId
-</verb></tscreen>
-
-where @ThreadId@ is an abstract type representing a handle to the
-newly created thread. Threads may also be killed:
-
-<tscreen><verb>
-killThread :: ThreadId -> IO ()
-</verb></tscreen>
-
-this terminates the given thread. Any work already done by the thread
-isn't lost: the computation is suspended until required by another
-thread. The memory used by the thread will be garbage collected if it
-isn't referenced from anywhere else.
-
-More generally, an arbitrary exception may be raised in any thread for
-which we have a <tt/ThreadId/, with <tt/raiseInThread/:
-
-<tscreen><verb>
-raiseInThread :: ThreadId -> Exception -> IO ()
-</verb></tscreen>
-
-Actually <tt/killThread/ just raises the <tt/ThreadKilled/ exception
-in the target thread, the normal action of which is to just terminate
-the thread. The target thread will stop whatever it was doing (even
-if it was blocked on an <tt/MVar/ or other computation) and handle the
-exception.
-
-The <tt/ThreadId/ for the current thread can be obtained with
-<tt/myThreadId/:
-
-<tscreen><verb>
-myThreadId :: IO ThreadId
-</verb></tscreen>
-
-NOTE: if you have a @ThreadId@, you essentially have a pointer to the
-thread itself. This means the thread itself can't be garbage
-collected until you drop the @ThreadId@. This misfeature will
-hopefully be corrected at a later date.
-
-The @Concurrent@ interface also provides access to ``M-Vars'', which
-are <em>synchronising variables</em>.
-
-<nidx>synchronising variables (Glasgow extension)</nidx>
-<nidx>concurrency -- synchronising variables</nidx>
-
-@MVars@<nidx>MVars (Glasgow extension)</nidx> are rendezvous points,
-mostly for concurrent threads. They begin either empty or full, 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:
-
-<tscreen><verb>
-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
-</verb></tscreen>
-
-A <em>channel variable</em> (@CVar@) is a one-element channel, as
-described in the paper:
-
-<tscreen><verb>
-data CVar a
-newCVar :: IO (CVar a)
-putCVar :: CVar a -> a -> IO ()
-getCVar :: CVar a -> IO a
-</verb></tscreen>
-
-A @Channel@ is an unbounded channel:
-
-<tscreen><verb>
-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]
-</verb></tscreen>
-
-General and quantity semaphores:
-
-<tscreen><verb>
-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 ()
-</verb></tscreen>
-
-Merging streams---binary and n-ary:
-
-<tscreen><verb>
-mergeIO :: [a] -> [a] -> IO [a]
-nmergeIO :: [[a]] -> IO [a]
-</verb></tscreen>
-
-A <em>Sample variable</em> (@SampleVar@) is slightly different from a
-normal @MVar@:
-
-<itemize>
-<item> Reading an empty @SampleVar@ causes the reader to block
- (same as @takeMVar@ on empty @MVar@).
-<item> Reading a filled @SampleVar@ empties it and returns value.
- (same as @takeMVar@)
-<item> Writing to an empty @SampleVar@ fills it with a value, and
-potentially, wakes up a blocked reader (same as for @putMVar@ on empty @MVar@).
-<item> Writing to a filled @SampleVar@ overwrites the current value.
- (different from @putMVar@ on full @MVar@.)
-</itemize>
-
-<tscreen><verb>
-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 ()
-</verb></tscreen>
-
-Finally, there are operations to delay a concurrent thread, and to
-make one wait:<nidx>delay a concurrent thread</nidx>
-<nidx>wait for a file descriptor</nidx>
-<tscreen><verb>
-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).
-</verb></tscreen>
+Some details about Parallel Haskell follow. For more information
+about concurrent Haskell, see the Concurrent section in the <htmlurl
+name="GHC/Hugs Extension Libraries" url="libs.html"> documentation.
%************************************************************************
%* *