3 % (c) The GRASP/AQUA Project, Glasgow University, 1995
5 \section[Channel]{Unbounded Channels}
7 Standard, unbounded channel abstraction.
13 {- abstract type defined -}
17 newChan, -- :: IO (Chan a)
20 putChan, -- :: Chan a -> a -> IO ()
21 getChan, -- :: Chan a -> IO a
22 dupChan, -- :: Chan a -> IO (Chan a)
23 unGetChan, -- :: Chan a -> a -> IO ()
25 {- stream interface -}
26 getChanContents, -- :: Chan a -> IO [a]
27 putList2Chan -- :: Chan a -> [a] -> IO ()
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.
43 = Chan (MVar (Stream a))
46 type Stream a = MVar (ChItem a)
48 data ChItem a = ChItem a (Stream a)
54 See the Concurrent Haskell paper for a diagram explaining the
55 how the different channel operations proceed.
57 @newChan@ sets up the read and write end of a channel by initialising
58 these two @MVar@s with an empty @MVar@.
63 newChan :: IO (Chan a)
65 = newEmptyMVar >>= \ hole ->
66 newMVar hole >>= \ read ->
67 newMVar hole >>= \ write ->
68 return (Chan read write)
73 To put an element on a channel, a new hole at the write end is created.
74 What was previously the empty @MVar@ at the back of the channel is then
75 filled in with a new stream element holding the entered value and the
81 putChan :: Chan a -> a -> IO ()
82 putChan (Chan read write) val
83 = newEmptyMVar >>= \ new_hole ->
84 takeMVar write >>= \ old_hole ->
85 putMVar write new_hole >>
86 putMVar old_hole (ChItem val new_hole) >>
90 getChan :: Chan a -> IO a
91 getChan (Chan read write)
92 = takeMVar read >>= \ rend ->
93 takeMVar rend >>= \ (ChItem val new_rend) ->
94 putMVar read new_rend >>
98 dupChan :: Chan a -> IO (Chan a)
99 dupChan (Chan read write)
100 = newEmptyMVar >>= \ new_read ->
101 readMVar write >>= \ hole ->
102 putMVar new_read hole >>
103 return (Chan new_read write)
105 unGetChan :: Chan a -> a -> IO ()
106 unGetChan (Chan read write) val
107 = newEmptyMVar >>= \ new_rend ->
108 takeMVar read >>= \ rend ->
109 putMVar new_rend (ChItem val rend) >>
110 putMVar read new_rend >>
116 Operators for interfacing with functional streams.
121 getChanContents :: Chan a -> IO [a]
124 = unsafeInterleavePrimIO (
125 getChan ch `thenPrimIO` \ ~(Right x) ->
126 unsafeInterleavePrimIO (getChanContents ch) `thenPrimIO` \ ~(Right xs) ->
127 returnPrimIO (Right (x:xs)))
129 = my_2_IO $ unsafeInterleavePrimIO (
130 getChan_prim ch >>= \ ~(Right x) ->
131 unsafeInterleavePrimIO (getChanContents_prim ch) >>= \ ~(Right xs) ->
132 returnPrimIO (Right (x:xs)))
134 my_2_IO :: PrimIO (Either IOError a) -> IO a -- simple; primIOToIO does too much!
137 getChan_prim :: Chan a -> PrimIO (Either IOError a)
138 getChanContents_prim :: Chan a -> PrimIO (Either IOError [a])
140 getChan_prim ch = ST $ \ s ->
141 case (getChan ch) of { IO (ST get) ->
144 getChanContents_prim ch = ST $ \ s ->
145 case (getChanContents ch) of { IO (ST get) ->
149 putList2Chan :: Chan a -> [a] -> IO ()
150 putList2Chan ch ls = sequence (map (putChan ch) ls)