module Control.Concurrent.Classy.Chan
(
Chan
, newChan
, writeChan
, readChan
, dupChan
, writeList2Chan
) where
import Control.Concurrent.Classy.MVar
import Control.Monad.Catch (mask_)
import Control.Monad.Conc.Class (MonadConc)
data Chan m a
= Chan (MVar m (Stream m a))
(MVar m (Stream m a))
type Stream m a = MVar m (ChItem m a)
data ChItem m a = ChItem a (Stream m a)
newChan :: MonadConc m => m (Chan m a)
newChan = do
hole <- newEmptyMVar
readVar <- newMVar hole
writeVar <- newMVar hole
pure (Chan readVar writeVar)
writeChan :: MonadConc m => Chan m a -> a -> m ()
writeChan (Chan _ writeVar) val = do
new_hole <- newEmptyMVar
mask_ $ do
old_hole <- takeMVar writeVar
putMVar old_hole (ChItem val new_hole)
putMVar writeVar new_hole
readChan :: MonadConc m => Chan m a -> m a
readChan (Chan readVar _) = modifyMVarMasked readVar $ \read_end -> do
(ChItem val new_read_end) <- readMVar read_end
pure (new_read_end, val)
dupChan :: MonadConc m => Chan m a -> m (Chan m a)
dupChan (Chan _ writeVar) = do
hole <- readMVar writeVar
newReadVar <- newMVar hole
pure (Chan newReadVar writeVar)
writeList2Chan :: MonadConc m => Chan m a -> [a] -> m ()
writeList2Chan = mapM_ . writeChan