+-- read value out of _immutable_ memory
+indexCharOffAddr :: Addr -> Int -> Char
+indexIntOffAddr :: Addr -> Int -> Int -- should we drop this?
+indexAddrOffAddr :: Addr -> Int -> Addr
+indexFloatOffAddr :: Addr -> Int -> Float
+indexDoubleOffAddr :: Addr -> Int -> Double
+indexWord8OffAddr :: Addr -> Int -> Word8
+indexWord16OffAddr :: Addr -> Int -> Word16
+indexWord32OffAddr :: Addr -> Int -> Word32
+indexWord64OffAddr :: Addr -> Int -> Word64
+indexInt8OffAddr :: Addr -> Int -> Int8
+indexInt16OffAddr :: Addr -> Int -> Int16
+indexInt32OffAddr :: Addr -> Int -> Int32
+indexInt64OffAddr :: Addr -> Int -> Int64
+
+-- read value out of mutable memory
+readCharOffAddr :: Addr -> Int -> IO Char
+readIntOffAddr :: Addr -> Int -> IO Int -- should we drop this?
+readAddrOffAddr :: Addr -> Int -> IO Addr
+readFloatOffAddr :: Addr -> Int -> IO Float
+readDoubleOffAddr :: Addr -> Int -> IO Double
+readWord8OffAddr :: Addr -> Int -> IO Word8
+readWord16OffAddr :: Addr -> Int -> IO Word16
+readWord32OffAddr :: Addr -> Int -> IO Word32
+readWord64OffAddr :: Addr -> Int -> IO Word64
+readInt8OffAddr :: Addr -> Int -> IO Int8
+readInt16OffAddr :: Addr -> Int -> IO Int16
+readInt32OffAddr :: Addr -> Int -> IO Int32
+readInt64OffAddr :: Addr -> Int -> IO Int64
+
+-- write value into mutable memory
+writeCharOffAddr :: Addr -> Int -> Char -> IO ()
+writeIntOffAddr :: Addr -> Int -> Int -> IO () -- should we drop this?
+writeAddrOffAddr :: Addr -> Int -> Addr -> IO ()
+writeFloatOffAddr :: Addr -> Int -> Float -> IO ()
+writeDoubleOffAddr :: Addr -> Int -> Double -> IO ()
+writeWord8OffAddr :: Addr -> Int -> Word8 -> IO ()
+writeWord16OffAddr :: Addr -> Int -> Word16 -> IO ()
+writeWord32OffAddr :: Addr -> Int -> Word32 -> IO ()
+writeWord64OffAddr :: Addr -> Int -> Word64 -> IO ()
+writeInt8OffAddr :: Addr -> Int -> Int8 -> IO ()
+writeInt16OffAddr :: Addr -> Int -> Int16 -> IO ()
+writeInt32OffAddr :: Addr -> Int -> Int32 -> IO ()
+writeInt64OffAddr :: Addr -> Int -> Int64 -> IO ()
+\end{verbatim}
+
+
+Hugs and GHC provide {\tt Addr} and {\tt nullAddr} but do not provide
+any of the index, read or write functions. They can be implemented
+using GreenCard if required.
+
+
+
+
+\subsubsection{@Concurrent@}
+\index{Concurrent module}
+
+
+
+This library provides the Concurrent Haskell extensions.
+
+We are grateful to the Glasgow Haskell Project for allowing us to
+redistribute their implementation of this module.
+
+\begin{verbatim}
+module Concurrent where
+
+data ThreadId -- thread identifiers
+instance Eq ThreadId
+
+forkIO :: IO () -> IO ThreadId
+killThread :: ThreadId -> IO ()
+
+data MVar a -- Synchronisation variables
+newEmptyMVar :: IO (MVar a)
+newMVar :: a -> IO (MVar a)
+takeMVar :: MVar a -> IO a
+putMVar :: MVar a -> a -> IO ()
+swapMVar :: MVar a -> a -> IO a
+readMVar :: MVar a -> IO a
+instance Eq (MVar a)
+
+data Chan a -- channels
+newChan :: IO (Chan a)
+writeChan :: Chan a -> a -> IO ()
+readChan :: Chan a -> IO a
+dupChan :: Chan a -> IO (Chan a)
+unReadChan :: Chan a -> a -> IO ()
+readChanContents :: Chan a -> IO [a]
+writeList2Chan :: Chan a -> [a] -> IO ()
+
+data CVar a -- one element channels
+newCVar :: IO (CVar a)
+putCVar :: CVar a -> a -> IO ()
+getCVar :: CVar a -> IO a
+
+data QSem -- General/quantity semaphores
+newQSem :: Int -> IO QSem
+waitQSem :: QSem -> IO ()
+signalQSem :: QSem -> IO ()
+
+data QSemN -- General/quantity semaphores
+newQSemN :: Int -> IO QSemN
+waitQSemN :: QSemN -> Int -> IO ()
+signalQSemN :: QSemN -> Int -> IO ()
+
+type SampleVar a -- Sample variables
+newEmptySampleVar:: IO (SampleVar a)
+newSampleVar :: a -> IO (SampleVar a)
+emptySampleVar :: SampleVar a -> IO ()
+readSampleVar :: SampleVar a -> IO a
+writeSampleVar :: SampleVar a -> a -> IO ()
+\end{verbatim}
+
+
+Notes:
+\begin{itemize}
+\item
+GHC uses preemptive multitasking:
+Context switches can occur at any time, except if you call a C
+function (like \verb"getchar") that blocks waiting for input.