2 % (c) The GRASP/AQUA Project, Glasgow University, 1995-97
4 \section[Channel]{Unbounded Channels}
6 Standard, unbounded channel abstraction.
11 {- abstract type defined -}
15 newChan, -- :: IO (Chan a)
18 writeChan, -- :: Chan a -> a -> IO ()
19 readChan, -- :: Chan a -> IO a
20 dupChan, -- :: Chan a -> IO (Chan a)
21 unGetChan, -- :: Chan a -> a -> IO ()
23 isEmptyChan, -- :: Chan a -> IO Bool
25 {- stream interface -}
26 getChanContents, -- :: Chan a -> IO [a]
27 writeList2Chan -- :: Chan a -> [a] -> IO ()
34 import PrelIOBase ( unsafeInterleaveIO )
37 A channel is represented by two @MVar@s keeping track of the two ends
38 of the channel contents,i.e., the read- and write ends. Empty @MVar@s
39 are used to handle consumers trying to read from an empty channel.
43 = Chan (MVar (Stream a))
46 type Stream a = MVar (ChItem a)
48 data ChItem a = ChItem a (Stream a)
51 See the Concurrent Haskell paper for a diagram explaining the
52 how the different channel operations proceed.
54 @newChan@ sets up the read and write end of a channel by initialising
55 these two @MVar@s with an empty @MVar@.
58 newChan :: IO (Chan a)
63 return (Chan read write)
66 To put an element on a channel, a new hole at the write end is created.
67 What was previously the empty @MVar@ at the back of the channel is then
68 filled in with a new stream element holding the entered value and the
72 writeChan :: Chan a -> a -> IO ()
73 writeChan (Chan read write) val = do
74 new_hole <- newEmptyMVar
75 old_hole <- takeMVar write
76 putMVar write new_hole
77 putMVar old_hole (ChItem val new_hole)
79 readChan :: Chan a -> IO a
80 readChan (Chan read write) = do
81 read_end <- takeMVar read
82 (ChItem val new_read_end) <- takeMVar read_end
83 putMVar read new_read_end
87 dupChan :: Chan a -> IO (Chan a)
88 dupChan (Chan read write) = do
89 new_read <- newEmptyMVar
90 hole <- readMVar write
92 return (Chan new_read write)
94 unGetChan :: Chan a -> a -> IO ()
95 unGetChan (Chan read write) val = do
96 new_read_end <- newEmptyMVar
97 read_end <- takeMVar read
98 putMVar new_read_end (ChItem val read_end)
99 putMVar read new_read_end
101 isEmptyChan :: Chan a -> IO Bool
102 isEmptyChan (Chan read write) = do
106 eq `seq` putMVar read r
111 Operators for interfacing with functional streams.
114 getChanContents :: Chan a -> IO [a]
116 = unsafeInterleaveIO (do
118 xs <- getChanContents ch
123 writeList2Chan :: Chan a -> [a] -> IO ()
124 writeList2Chan ch ls = sequence_ (map (writeChan ch) ls)