
It seems like the real difference between TChan and the Ch code below is that TChan is, basically, [TVar a] whereas Ch is MVar [a], plus the order is guaranteed for a TChan. Now why would it matter so much speed-wise? This is the CVS code. newTChanIO is exported but undocumented in GHC 6.4.1. I'm not sure what purpose it serves. -- | 'TChan' is an abstract type representing an unbounded FIFO channel. data TChan a = TChan (TVar (TVarList a)) (TVar (TVarList a)) type TVarList a = TVar (TList a) data TList a = TNil | TCons a (TVarList a) newTChan :: STM (TChan a) newTChan = do hole <- newTVar TNil read <- newTVar hole write <- newTVar hole return (TChan read write) newTChanIO :: IO (TChan a) newTChanIO = do hole <- newTVarIO TNil read <- newTVarIO hole write <- newTVarIO hole return (TChan read write) writeTChan :: TChan a -> a -> STM () writeTChan (TChan _read write) a = do listend <- readTVar write -- listend == TVar pointing to TNil new_listend <- newTVar TNil writeTVar listend (TCons a new_listend) writeTVar write new_listend readTChan :: TChan a -> STM a readTChan (TChan read _write) = do listhead <- readTVar read head <- readTVar listhead case head of TNil -> retry TCons a tail -> do writeTVar read tail return a On Jan 3, 2006, at 11:25 AM, Chris Kuklewicz wrote:
The latest Ch code is very very short:
{- Ch : fast unordered channel implementation -} newtype Ch a = Ch (MVar [a], MVar a)
newCh = liftM2 (,) (newMVar []) newEmptyMVar >>= return.Ch
readCh (Ch (w,r)) = takeMVar w >>= \lst -> case lst of (x:xs) -> putMVar w xs >> return x [] -> putMVar w [] >> takeMVar r
writeCh (Ch (w,r)) x = do ok <- tryPutMVar r x -- opportunistic, helps for this problem unless ok $ takeMVar w >>= \lst -> do ok <- tryPutMVar r x -- safe inside take/put putMVar w $ if ok then lst else (x:lst)
It could be used in general purpose code, note the parametric type "a" in "Ch a". It makes absolutely no guarantees about the order of values. That means that the order they are written is unlikely to be the order in which they are read. Writes to the channel are non-blocking and the "MVar [a]" holds some items waiting to be read (in LIFO order).