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 putChan, -- :: Chan a -> a -> IO ()
19 getChan, -- :: Chan a -> IO a
20 dupChan, -- :: Chan a -> IO (Chan a)
21 unGetChan, -- :: Chan a -> a -> IO ()
23 {- stream interface -}
24 getChanContents, -- :: Chan a -> IO [a]
25 putList2Chan -- :: Chan a -> [a] -> IO ()
30 import PreludePrimIO ( newEmptyMVar, newMVar, putMVar,
31 readMVar, takeMVar, _MVar
35 A channel is represented by two @MVar@s keeping track of the two ends
36 of the channel contents,i.e., the read- and write ends. Empty @MVar@s
37 are used to handle consumers trying to read from an empty channel.
42 = Chan (_MVar (Stream a))
45 type Stream a = _MVar (ChItem a)
47 data ChItem a = ChItem a (Stream a)
52 See the Concurrent Haskell paper for a diagram explaining the
53 how the different channel operations proceed.
55 @newChan@ sets up the read and write end of a channel by initialising
56 these two @MVar@s with an empty @MVar@.
60 newChan :: IO (Chan a)
62 = newEmptyMVar >>= \ hole ->
63 newMVar hole >>= \ read ->
64 newMVar hole >>= \ write ->
65 return (Chan read write)
69 To put an element on a channel, a new hole at the write end is created.
70 What was previously the empty @MVar@ at the back of the channel is then
71 filled in with a new stream element holding the entered value and the
76 putChan :: Chan a -> a -> IO ()
77 putChan (Chan read write) val
78 = newEmptyMVar >>= \ new_hole ->
79 takeMVar write >>= \ old_hole ->
80 putMVar write new_hole >>
81 putMVar old_hole (ChItem val new_hole) >>
88 getChan :: Chan a -> IO a
89 getChan (Chan read write)
90 = takeMVar read >>= \ rend ->
91 takeMVar rend >>= \ (ChItem val new_rend) ->
92 putMVar read new_rend >>
99 dupChan :: Chan a -> IO (Chan a)
100 dupChan (Chan read write)
101 = newEmptyMVar >>= \ new_read ->
102 readMVar write >>= \ hole ->
103 putMVar new_read hole >>
104 return (Chan new_read write)
106 unGetChan :: Chan a -> a -> IO ()
107 unGetChan (Chan read write) val
108 = newEmptyMVar >>= \ new_rend ->
109 takeMVar read >>= \ rend ->
110 putMVar new_rend (ChItem val rend) >>
111 putMVar read new_rend >>
116 Operators for interfacing with functional streams.
120 getChanContents :: Chan a -> IO [a]
122 unsafeInterleavePrimIO (
123 getChan ch `thenPrimIO` \ ~(Right x) ->
124 unsafeInterleavePrimIO (getChanContents ch) `thenPrimIO` \ ~(Right xs) ->
125 returnPrimIO (Right (x:xs)))
127 putList2Chan :: Chan a -> [a] -> IO ()
128 putList2Chan ch ls = sequence (map (putChan ch) ls)