2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
4 \section[Channel]{Unbounded Channels}
6 Standard, unbounded channel abstraction.
14 newChan, -- :: IO (Chan a)
15 putChan, -- :: Chan a -> a -> IO ()
16 getChan, -- :: Chan a -> IO a
17 dupChan, -- :: Chan a -> IO (Chan a)
18 unGetChan, -- :: Chan a -> a -> IO ()
19 getChanContents -- :: Chan a -> IO [a]
24 import PreludePrimIO ( newEmptyMVar, newMVar, putMVar,
25 readMVar, takeMVar, _MVar
29 A channel is represented by two @MVar@s keeping track of the two ends
30 of the channel contents,i.e., the read- and write ends. Empty @MVar@s
31 are used to handle consumers trying to read from an empty channel.
36 = Chan (_MVar (Stream a))
39 type Stream a = _MVar (ChItem a)
41 data ChItem a = ChItem a (Stream a)
46 See the Concurrent Haskell paper for a diagram explaining the
47 how the different channel operations proceed.
49 @newChan@ sets up the read and write end of a channel by initialising
50 these two @MVar@s with an empty @MVar@.
54 newChan :: IO (Chan a)
56 = newEmptyMVar >>= \ hole ->
57 newMVar hole >>= \ read ->
58 newMVar hole >>= \ write ->
59 return (Chan read write)
63 To put an element on a channel, a new hole at the write end is created.
64 What was previously the empty @MVar@ at the back of the channel is then
65 filled in with a new stream element holding the entered value and the
70 putChan :: Chan a -> a -> IO ()
71 putChan (Chan read write) val
72 = newEmptyMVar >>= \ new_hole ->
73 takeMVar write >>= \ old_hole ->
74 putMVar write new_hole >>
75 putMVar old_hole (ChItem val new_hole) >>
82 getChan :: Chan a -> IO a
83 getChan (Chan read write)
84 = takeMVar read >>= \ rend ->
85 takeMVar rend >>= \ (ChItem val new_rend) ->
86 putMVar read new_rend >>
93 dupChan :: Chan a -> IO (Chan a)
94 dupChan (Chan read write)
95 = newEmptyMVar >>= \ new_read ->
96 readMVar write >>= \ hole ->
97 putMVar new_read hole >>
98 return (Chan new_read write)
100 unGetChan :: Chan a -> a -> IO ()
101 unGetChan (Chan read write) val
102 = newEmptyMVar >>= \ new_rend ->
103 takeMVar read >>= \ rend ->
104 putMVar new_rend (ChItem val rend) >>
105 putMVar read new_rend >>
112 getChanContents :: Chan a -> IO [a]
114 = unsafeInterleavePrimIO (
115 getChan ch) `thenPrimIO` \ ~(Right x) ->
116 unsafeInterleavePrimIO (
117 getChanContents ch) `thenPrimIO` \ ~(Right xs) ->