%
-% (c) The GRASP/AQUA Project, Glasgow University, 1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1995-97
%
\section[Channel]{Unbounded Channels}
unGetChan, -- :: Chan a -> a -> IO ()
{- stream interface -}
- readChanContents, -- :: Chan a -> IO [a]
- putList2Chan -- :: Chan a -> [a] -> IO ()
+ getChanContents, -- :: Chan a -> IO [a]
+ writeList2Chan -- :: Chan a -> [a] -> IO ()
) where
import Prelude
-import IOBase ( IO(..), ioToST, stToIO ) -- Suspicious!
import ConcBase
import STBase
import Unsafe ( unsafeInterleaveIO )
are used to handle consumers trying to read from an empty channel.
\begin{code}
-
data Chan a
= Chan (MVar (Stream a))
(MVar (Stream a))
type Stream a = MVar (ChItem a)
data ChItem a = ChItem a (Stream a)
-
-
\end{code}
See the Concurrent Haskell paper for a diagram explaining the
these two @MVar@s with an empty @MVar@.
\begin{code}
-
newChan :: IO (Chan a)
-newChan
- = newEmptyMVar >>= \ hole ->
- newMVar hole >>= \ read ->
- newMVar hole >>= \ write ->
+newChan = do
+ hole <- newEmptyMVar
+ read <- newMVar hole
+ write <- newMVar hole
return (Chan read write)
-
\end{code}
To put an element on a channel, a new hole at the write end is created.
new hole.
\begin{code}
-
writeChan :: Chan a -> a -> IO ()
-writeChan (Chan read write) val
- = newEmptyMVar >>= \ new_hole ->
- takeMVar write >>= \ old_hole ->
- putMVar write new_hole >>
- putMVar old_hole (ChItem val new_hole) >>
- return ()
-
+writeChan (Chan read write) val = do
+ new_hole <- newEmptyMVar
+ old_hole <- takeMVar write
+ putMVar write new_hole
+ putMVar old_hole (ChItem val new_hole)
readChan :: Chan a -> IO a
-readChan (Chan read write)
- = takeMVar read >>= \ rend ->
- takeMVar rend >>= \ (ChItem val new_rend) ->
- putMVar read new_rend >>
- return val
+readChan (Chan read write) = do
+ read_end <- takeMVar read
+ (ChItem val new_read_end) <- takeMVar read_end
+ putMVar read new_read_end
+ return val
dupChan :: Chan a -> IO (Chan a)
-dupChan (Chan read write)
- = newEmptyMVar >>= \ new_read ->
- readMVar write >>= \ hole ->
- putMVar new_read hole >>
+dupChan (Chan read write) = do
+ new_read <- newEmptyMVar
+ hole <- readMVar write
+ putMVar new_read hole
return (Chan new_read write)
unGetChan :: Chan a -> a -> IO ()
-unGetChan (Chan read write) val
- = newEmptyMVar >>= \ new_rend ->
- takeMVar read >>= \ rend ->
- putMVar new_rend (ChItem val rend) >>
- putMVar read new_rend >>
- return ()
+unGetChan (Chan read write) val = do
+ new_read_end <- newEmptyMVar
+ read_end <- takeMVar read
+ putMVar new_read_end (ChItem val read_end)
+ putMVar read new_read_end
\end{code}
Operators for interfacing with functional streams.
\begin{code}
-
-readChanContents :: Chan a -> IO [a]
-readChanContents ch
+getChanContents :: Chan a -> IO [a]
+getChanContents ch
= unsafeInterleaveIO (do
- x <- readChan ch
- xs <- readChanContents ch
+ x <- readChan ch
+ xs <- getChanContents ch
return (x:xs)
)
-------------
-putList2Chan :: Chan a -> [a] -> IO ()
-putList2Chan ch ls = sequence (map (writeChan ch) ls)
+writeList2Chan :: Chan a -> [a] -> IO ()
+writeList2Chan ch ls = sequence (map (writeChan ch) ls)
\end{code}