X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Control%2FConcurrent%2FChan.hs;h=2255c4e49c9450566bbd1dfbe7980e80c499b615;hb=41e8fba828acbae1751628af50849f5352b27873;hp=6b48e33c5cabbb2385eeee68d0d4885ef80bf2f8;hpb=edc5c57d653289a1cf8dd2b05bf94ed25975e28a;p=ghc-base.git diff --git a/Control/Concurrent/Chan.hs b/Control/Concurrent/Chan.hs index 6b48e33..2255c4e 100644 --- a/Control/Concurrent/Chan.hs +++ b/Control/Concurrent/Chan.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE CPP #-} + ----------------------------------------------------------------------------- -- | -- Module : Control.Concurrent.Chan @@ -6,7 +8,7 @@ -- -- Maintainer : libraries@haskell.org -- Stability : experimental --- Portability : non-portable (concurrency). +-- Portability : non-portable (concurrency) -- -- Unbounded channels. -- @@ -14,25 +16,25 @@ module Control.Concurrent.Chan ( - -- * 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 () + -- * 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 System.IO.Unsafe ( unsafeInterleaveIO ) import Control.Concurrent.MVar import Data.Typeable @@ -46,6 +48,7 @@ import Data.Typeable data Chan a = Chan (MVar (Stream a)) (MVar (Stream a)) + deriving Eq INSTANCE_TYPEABLE1(Chan,chanTc,"Chan") @@ -63,9 +66,9 @@ data ChItem a = ChItem a (Stream a) newChan :: IO (Chan a) newChan = do hole <- newEmptyMVar - read <- newMVar hole - write <- newMVar hole - return (Chan read write) + readVar <- newMVar hole + writeVar <- newMVar hole + return (Chan readVar writeVar) -- To put an element on a channel, a new hole at the write end is created. -- What was previously the empty @MVar@ at the back of the channel is then @@ -74,46 +77,51 @@ newChan = do -- |Write a value to a 'Chan'. writeChan :: Chan a -> a -> IO () -writeChan (Chan _read write) val = do +writeChan (Chan _ writeVar) val = do new_hole <- newEmptyMVar - modifyMVar_ write $ \old_hole -> do + modifyMVar_ writeVar $ \old_hole -> 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 +readChan (Chan readVar _) = do + modifyMVar readVar $ \read_end -> do (ChItem val new_read_end) <- readMVar read_end - -- Use readMVar here, not takeMVar, - -- else dupChan doesn't work + -- Use readMVar here, not takeMVar, + -- 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. +-- +-- (Note that a duplicated channel is not equal to its original. +-- So: @fmap (c /=) $ dupChan c@ returns @True@ for all @c@.) dupChan :: Chan a -> IO (Chan a) -dupChan (Chan _read write) = do - hole <- readMVar write - new_read <- newMVar hole - return (Chan new_read write) +dupChan (Chan _ writeVar) = do + hole <- readMVar writeVar + newReadVar <- newMVar hole + return (Chan newReadVar writeVar) -- |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 +unGetChan (Chan readVar _) val = do new_read_end <- newEmptyMVar - modifyMVar_ read $ \read_end -> do + modifyMVar_ readVar $ \read_end -> do putMVar new_read_end (ChItem val read_end) return new_read_end +{-# DEPRECATED unGetChan "if you need this operation, use Control.Concurrent.STM.TChan instead. See http://hackage.haskell.org/trac/ghc/ticket/4154 for details" #-} -- |Returns 'True' if the supplied 'Chan' is empty. isEmptyChan :: Chan a -> IO Bool -isEmptyChan (Chan read write) = do - withMVar read $ \r -> do - w <- readMVar write +isEmptyChan (Chan readVar writeVar) = do + withMVar readVar $ \r -> do + w <- readMVar writeVar let eq = r == w eq `seq` return eq +{-# DEPRECATED isEmptyChan "if you need this operation, use Control.Concurrent.STM.TChan instead. See http://hackage.haskell.org/trac/ghc/ticket/4154 for details" #-} -- Operators for interfacing with functional streams. @@ -122,9 +130,9 @@ isEmptyChan (Chan read write) = do getChanContents :: Chan a -> IO [a] getChanContents ch = unsafeInterleaveIO (do - x <- readChan ch - xs <- getChanContents ch - return (x:xs) + x <- readChan ch + xs <- getChanContents ch + return (x:xs) ) -- |Write an entire list of items to a 'Chan'.