2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
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 {- stream interface -}
24 readChanContents, -- :: Chan a -> IO [a]
25 putList2Chan -- :: Chan a -> [a] -> IO ()
30 import IOBase ( IO(..), ioToST, stToIO ) -- Suspicious!
33 import Unsafe ( unsafeInterleaveIO )
36 A channel is represented by two @MVar@s keeping track of the two ends
37 of the channel contents,i.e., the read- and write ends. Empty @MVar@s
38 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)
53 See the Concurrent Haskell paper for a diagram explaining the
54 how the different channel operations proceed.
56 @newChan@ sets up the read and write end of a channel by initialising
57 these two @MVar@s with an empty @MVar@.
61 newChan :: IO (Chan a)
63 = newEmptyMVar >>= \ hole ->
64 newMVar hole >>= \ read ->
65 newMVar hole >>= \ write ->
66 return (Chan read write)
70 To put an element on a channel, a new hole at the write end is created.
71 What was previously the empty @MVar@ at the back of the channel is then
72 filled in with a new stream element holding the entered value and the
77 writeChan :: Chan a -> a -> IO ()
78 writeChan (Chan read write) val
79 = newEmptyMVar >>= \ new_hole ->
80 takeMVar write >>= \ old_hole ->
81 putMVar write new_hole >>
82 putMVar old_hole (ChItem val new_hole) >>
86 readChan :: Chan a -> IO a
87 readChan (Chan read write)
88 = takeMVar read >>= \ rend ->
89 takeMVar rend >>= \ (ChItem val new_rend) ->
90 putMVar read new_rend >>
94 dupChan :: Chan a -> IO (Chan a)
95 dupChan (Chan read write)
96 = newEmptyMVar >>= \ new_read ->
97 readMVar write >>= \ hole ->
98 putMVar new_read hole >>
99 return (Chan new_read write)
101 unGetChan :: Chan a -> a -> IO ()
102 unGetChan (Chan read write) val
103 = newEmptyMVar >>= \ new_rend ->
104 takeMVar read >>= \ rend ->
105 putMVar new_rend (ChItem val rend) >>
106 putMVar read new_rend >>
111 Operators for interfacing with functional streams.
115 readChanContents :: Chan a -> IO [a]
117 = unsafeInterleaveIO (do
119 xs <- readChanContents ch
124 putList2Chan :: Chan a -> [a] -> IO ()
125 putList2Chan ch ls = sequence (map (writeChan ch) ls)