4 ( -- * Channel conversions |
4 ( -- * Channel conversions |
5 inputToChan |
5 inputToChan |
6 , chanToInput |
6 , chanToInput |
7 , chanToOutput |
7 , chanToOutput |
8 , makeChanPipe |
8 , makeChanPipe |
9 , dupStream |
|
10 , DupHandle |
|
11 ) where |
9 ) where |
12 |
10 |
13 |
11 |
14 ------------------------------------------------------------------------------ |
12 ------------------------------------------------------------------------------ |
15 import Control.Applicative (pure, (<$>), (<*>)) |
13 import Control.Applicative ((<$>), (<*>)) |
16 import Control.Concurrent.Chan.Unagi.Bounded (InChan, OutChan, |
14 import Control.Concurrent.Chan.Unagi.Bounded (InChan, OutChan, |
17 dupChan, newChan, |
15 newChan, readChan, |
18 readChan, writeChan) |
16 writeChan) |
19 import Control.Monad ((>=>)) |
|
20 import Prelude hiding (read) |
17 import Prelude hiding (read) |
21 import System.IO.Streams.Internal (InputStream, |
18 import System.IO.Streams.Internal (InputStream, |
22 OutputStream, |
19 OutputStream, |
23 makeInputStream, |
20 makeInputStream, |
24 makeOutputStream, read) |
21 makeOutputStream, read) |
25 |
22 |
26 |
|
27 newtype DupHandle a = DupHandle { unDupHandle :: InChan (Maybe a) } |
|
28 |
23 |
29 ------------------------------------------------------------------------------ |
24 ------------------------------------------------------------------------------ |
30 -- | Writes the contents of an input stream to a channel until the input stream |
25 -- | Writes the contents of an input stream to a channel until the input stream |
31 -- yields end-of-stream. |
26 -- yields end-of-stream. |
32 inputToChan :: InputStream a -> InChan (Maybe a) -> IO () |
27 inputToChan :: InputStream a -> InChan (Maybe a) -> IO () |
56 -- | Create a new pair of streams using an underlying 'Chan'. Everything written |
51 -- | Create a new pair of streams using an underlying 'Chan'. Everything written |
57 -- to the 'OutputStream' will appear as-is on the 'InputStream'. |
52 -- to the 'OutputStream' will appear as-is on the 'InputStream'. |
58 -- |
53 -- |
59 -- Since reading from the 'InputStream' and writing to the 'OutputStream' are |
54 -- Since reading from the 'InputStream' and writing to the 'OutputStream' are |
60 -- blocking calls, be sure to do so in different threads. |
55 -- blocking calls, be sure to do so in different threads. |
61 makeChanPipe :: Int -> IO (InputStream a, OutputStream a, DupHandle a) |
56 makeChanPipe :: Int -> IO (InputStream a, OutputStream a) |
62 makeChanPipe size = do |
57 makeChanPipe size = do |
63 (inChan, outChan) <- newChan size |
58 (inChan, outChan) <- newChan size |
64 (,,) <$> chanToInput outChan <*> chanToOutput inChan <*> pure (DupHandle inChan) |
59 (,) <$> chanToInput outChan <*> chanToOutput inChan |
65 |
|
66 |
|
67 ------------------------------------------------------------------------------ |
|
68 -- | Use a 'DupHandle' to replicate everything written on the |
|
69 -- associated 'OutputStream' to the 'InputStream'. |
|
70 -- |
|
71 dupStream :: DupHandle a -> IO (InputStream a) |
|
72 dupStream = dupChan . unDupHandle >=> chanToInput |
|