module Control.Concurrent.STM.BTChan
( BTChan
, newBTChan
, newBTChanIO
, writeBTChan
, readBTChan
, isEmptyBTChan
, sizeOfBTChan
, setMaxOfBTChan
, maxOfBTChan
) where
import Control.Concurrent.STM
import Control.Monad (when)
data BTChan a = BTChan !Int (TChan a) (TVar Int)
newBTChanIO :: Int -> IO (BTChan a)
newBTChanIO m = do
szTV <- newTVarIO 0
c <- newTChanIO
return (BTChan m c szTV)
newBTChan :: Int -> STM (BTChan a)
newBTChan m = do
szTV <- newTVar 0
c <- newTChan
return (BTChan m c szTV)
writeBTChan :: BTChan a -> a -> STM ()
writeBTChan (BTChan mx c szTV) x = do
sz <- readTVar szTV
when (sz >= mx) retry
writeTVar szTV (sz + 1) >> writeTChan c x
readBTChan :: BTChan a -> STM a
readBTChan (BTChan _ c szTV) = do
x <- readTChan c
sz <- readTVar szTV
let !sz' = sz 1
writeTVar szTV sz'
return x
unGetBTChan :: BTChan a -> a -> STM ()
unGetBTChan (BTChan m c sTV) a = do
s <- readTVar sTV
when (s >= m) retry
let !s' = s+1
writeTVar sTV s'
unGetTChan c a
isEmptyBTChan :: BTChan a -> STM Bool
isEmptyBTChan (BTChan _ c _) = isEmptyTChan c
sizeOfBTChan :: BTChan a -> STM Int
sizeOfBTChan (BTChan _ _ sTV) = readTVar sTV
setMaxOfBTChan :: BTChan a -> Int -> BTChan a
setMaxOfBTChan (BTChan _ c s) m = BTChan m c s
maxOfBTChan :: BTChan a -> Int
maxOfBTChan (BTChan m _ _) = m