X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Control%2FConcurrent%2FChan.hs;h=6b48e33c5cabbb2385eeee68d0d4885ef80bf2f8;hb=edc5c57d653289a1cf8dd2b05bf94ed25975e28a;hp=d6c1107f2c7a930d50e0baa1905712ce4fdbfee1;hpb=746ef6a7fd71bb1e9ebe3cd107c5f9f79f3b7a68;p=ghc-base.git diff --git a/Control/Concurrent/Chan.hs b/Control/Concurrent/Chan.hs index d6c1107..6b48e33 100644 --- a/Control/Concurrent/Chan.hs +++ b/Control/Concurrent/Chan.hs @@ -2,49 +2,53 @@ -- | -- Module : Control.Concurrent.Chan -- Copyright : (c) The University of Glasgow 2001 --- License : BSD-style (see the file libraries/core/LICENSE) +-- License : BSD-style (see the file libraries/base/LICENSE) -- -- Maintainer : libraries@haskell.org -- Stability : experimental --- Portability : non-portable +-- Portability : non-portable (concurrency). -- --- Standard, unbounded channel abstraction. +-- Unbounded channels. -- ----------------------------------------------------------------------------- module Control.Concurrent.Chan - ( Chan -- abstract - - -- creator - , newChan -- :: IO (Chan a) - - -- operators - , writeChan -- :: Chan a -> a -> IO () - , readChan -- :: Chan a -> IO a - , dupChan -- :: Chan a -> IO (Chan a) - , unGetChan -- :: Chan a -> a -> IO () - - , isEmptyChan -- :: Chan a -> IO Bool - - -- stream interface - , getChanContents -- :: Chan a -> IO [a] - , writeList2Chan -- :: Chan a -> [a] -> IO () - - ) where + ( + -- * The 'Chan' type + Chan, -- abstract + + -- * Operations + newChan, -- :: IO (Chan a) + writeChan, -- :: Chan a -> a -> IO () + readChan, -- :: Chan a -> IO a + dupChan, -- :: Chan a -> IO (Chan a) + unGetChan, -- :: Chan a -> a -> IO () + isEmptyChan, -- :: Chan a -> IO Bool + + -- * Stream interface + getChanContents, -- :: Chan a -> IO [a] + writeList2Chan, -- :: Chan a -> [a] -> IO () + ) where import Prelude import System.IO.Unsafe ( unsafeInterleaveIO ) import Control.Concurrent.MVar +import Data.Typeable + +#include "Typeable.h" -- A channel is represented by two @MVar@s keeping track of the two ends -- of the channel contents,i.e., the read- and write ends. Empty @MVar@s -- are used to handle consumers trying to read from an empty channel. +-- |'Chan' is an abstract type representing an unbounded FIFO channel. data Chan a = Chan (MVar (Stream a)) (MVar (Stream a)) +INSTANCE_TYPEABLE1(Chan,chanTc,"Chan") + type Stream a = MVar (ChItem a) data ChItem a = ChItem a (Stream a) @@ -55,6 +59,7 @@ data ChItem a = ChItem a (Stream a) -- @newChan@ sets up the read and write end of a channel by initialising -- these two @MVar@s with an empty @MVar@. +-- |Build and returns a new instance of 'Chan'. newChan :: IO (Chan a) newChan = do hole <- newEmptyMVar @@ -67,6 +72,7 @@ newChan = do -- filled in with a new stream element holding the entered value and the -- new hole. +-- |Write a value to a 'Chan'. writeChan :: Chan a -> a -> IO () writeChan (Chan _read write) val = do new_hole <- newEmptyMVar @@ -74,6 +80,7 @@ writeChan (Chan _read write) val = do putMVar old_hole (ChItem val new_hole) return new_hole +-- |Read the next value from the 'Chan'. readChan :: Chan a -> IO a readChan (Chan read _write) = do modifyMVar read $ \read_end -> do @@ -82,12 +89,17 @@ readChan (Chan read _write) = do -- else dupChan doesn't work return (new_read_end, val) +-- |Duplicate a 'Chan': the duplicate channel begins empty, but data written to +-- either channel from then on will be available from both. Hence this creates +-- a kind of broadcast channel, where data written by anyone is seen by +-- everyone else. dupChan :: Chan a -> IO (Chan a) dupChan (Chan _read write) = do hole <- readMVar write new_read <- newMVar hole return (Chan new_read write) +-- |Put a data item back onto a channel, where it will be the next item read. unGetChan :: Chan a -> a -> IO () unGetChan (Chan read _write) val = do new_read_end <- newEmptyMVar @@ -95,6 +107,7 @@ unGetChan (Chan read _write) val = do putMVar new_read_end (ChItem val read_end) return new_read_end +-- |Returns 'True' if the supplied 'Chan' is empty. isEmptyChan :: Chan a -> IO Bool isEmptyChan (Chan read write) = do withMVar read $ \r -> do @@ -104,6 +117,8 @@ isEmptyChan (Chan read write) = do -- Operators for interfacing with functional streams. +-- |Return a lazy list representing the contents of the supplied +-- 'Chan', much like 'System.IO.hGetContents'. getChanContents :: Chan a -> IO [a] getChanContents ch = unsafeInterleaveIO (do @@ -112,6 +127,6 @@ getChanContents ch return (x:xs) ) -------------- +-- |Write an entire list of items to a 'Chan'. writeList2Chan :: Chan a -> [a] -> IO () writeList2Chan ch ls = sequence_ (map (writeChan ch) ls)