{-# OPTIONS_GHC -Wall -fwarn-tabs #-}
{-# LANGUAGE CPP, DeriveDataTypeable #-}
#if __GLASGOW_HASKELL__ >= 701
{-# LANGUAGE Safe #-}
#endif
module Control.Concurrent.STM.TBChan
(
TBChan()
, newTBChan
, newTBChanIO
, readTBChan
, tryReadTBChan
, peekTBChan
, tryPeekTBChan
, writeTBChan
, tryWriteTBChan
, unGetTBChan
, isEmptyTBChan
, isFullTBChan
, estimateFreeSlotsTBChan
, freeSlotsTBChan
) where
import Prelude hiding (reads)
import Data.Typeable (Typeable)
import Control.Monad.STM (STM, retry)
import Control.Concurrent.STM.TVar
import Control.Concurrent.STM.TChan
data TBChan a = TBChan
{-# UNPACK #-} !(TVar Int)
{-# UNPACK #-} !(TVar Int)
{-# UNPACK #-} !(TChan a)
deriving (Typeable)
newTBChan :: Int -> STM (TBChan a)
newTBChan :: Int -> STM (TBChan a)
newTBChan Int
n = do
TVar Int
slots <- Int -> STM (TVar Int)
forall a. a -> STM (TVar a)
newTVar Int
n
TVar Int
reads <- Int -> STM (TVar Int)
forall a. a -> STM (TVar a)
newTVar Int
0
TChan a
chan <- STM (TChan a)
forall a. STM (TChan a)
newTChan
TBChan a -> STM (TBChan a)
forall (m :: * -> *) a. Monad m => a -> m a
return (TVar Int -> TVar Int -> TChan a -> TBChan a
forall a. TVar Int -> TVar Int -> TChan a -> TBChan a
TBChan TVar Int
slots TVar Int
reads TChan a
chan)
newTBChanIO :: Int -> IO (TBChan a)
newTBChanIO :: Int -> IO (TBChan a)
newTBChanIO Int
n = do
TVar Int
slots <- Int -> IO (TVar Int)
forall a. a -> IO (TVar a)
newTVarIO Int
n
TVar Int
reads <- Int -> IO (TVar Int)
forall a. a -> IO (TVar a)
newTVarIO Int
0
TChan a
chan <- IO (TChan a)
forall a. IO (TChan a)
newTChanIO
TBChan a -> IO (TBChan a)
forall (m :: * -> *) a. Monad m => a -> m a
return (TVar Int -> TVar Int -> TChan a -> TBChan a
forall a. TVar Int -> TVar Int -> TChan a -> TBChan a
TBChan TVar Int
slots TVar Int
reads TChan a
chan)
readTBChan :: TBChan a -> STM a
readTBChan :: TBChan a -> STM a
readTBChan (TBChan TVar Int
_slots TVar Int
reads TChan a
chan) = do
a
x <- TChan a -> STM a
forall a. TChan a -> STM a
readTChan TChan a
chan
TVar Int -> (Int -> Int) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar Int
reads (Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+)
a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
tryReadTBChan :: TBChan a -> STM (Maybe a)
tryReadTBChan :: TBChan a -> STM (Maybe a)
tryReadTBChan (TBChan TVar Int
_slots TVar Int
reads TChan a
chan) = do
Maybe a
mx <- TChan a -> STM (Maybe a)
forall a. TChan a -> STM (Maybe a)
tryReadTChan TChan a
chan
case Maybe a
mx of
Maybe a
Nothing -> Maybe a -> STM (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
Just a
_x -> do
TVar Int -> (Int -> Int) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar Int
reads (Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+)
Maybe a -> STM (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
mx
peekTBChan :: TBChan a -> STM a
peekTBChan :: TBChan a -> STM a
peekTBChan (TBChan TVar Int
_slots TVar Int
_reads TChan a
chan) =
TChan a -> STM a
forall a. TChan a -> STM a
peekTChan TChan a
chan
tryPeekTBChan :: TBChan a -> STM (Maybe a)
tryPeekTBChan :: TBChan a -> STM (Maybe a)
tryPeekTBChan (TBChan TVar Int
_slots TVar Int
_reads TChan a
chan) =
TChan a -> STM (Maybe a)
forall a. TChan a -> STM (Maybe a)
tryPeekTChan TChan a
chan
writeTBChan :: TBChan a -> a -> STM ()
writeTBChan :: TBChan a -> a -> STM ()
writeTBChan self :: TBChan a
self@(TBChan TVar Int
slots TVar Int
_reads TChan a
chan) a
x = do
Int
n <- TBChan a -> STM Int
forall a. TBChan a -> STM Int
estimateFreeSlotsTBChan TBChan a
self
if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
then STM ()
forall a. STM a
retry
else do
TVar Int -> Int -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
slots (Int -> STM ()) -> Int -> STM ()
forall a b. (a -> b) -> a -> b
$! Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
TChan a -> a -> STM ()
forall a. TChan a -> a -> STM ()
writeTChan TChan a
chan a
x
tryWriteTBChan :: TBChan a -> a -> STM Bool
tryWriteTBChan :: TBChan a -> a -> STM Bool
tryWriteTBChan self :: TBChan a
self@(TBChan TVar Int
slots TVar Int
_reads TChan a
chan) a
x = do
Int
n <- TBChan a -> STM Int
forall a. TBChan a -> STM Int
estimateFreeSlotsTBChan TBChan a
self
if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
then Bool -> STM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
else do
TVar Int -> Int -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
slots (Int -> STM ()) -> Int -> STM ()
forall a b. (a -> b) -> a -> b
$! Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
TChan a -> a -> STM ()
forall a. TChan a -> a -> STM ()
writeTChan TChan a
chan a
x
Bool -> STM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
unGetTBChan :: TBChan a -> a -> STM ()
unGetTBChan :: TBChan a -> a -> STM ()
unGetTBChan (TBChan TVar Int
slots TVar Int
_reads TChan a
chan) a
x = do
TVar Int -> (Int -> Int) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar Int
slots (Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
1)
TChan a -> a -> STM ()
forall a. TChan a -> a -> STM ()
unGetTChan TChan a
chan a
x
isEmptyTBChan :: TBChan a -> STM Bool
isEmptyTBChan :: TBChan a -> STM Bool
isEmptyTBChan (TBChan TVar Int
_slots TVar Int
_reads TChan a
chan) =
TChan a -> STM Bool
forall a. TChan a -> STM Bool
isEmptyTChan TChan a
chan
isFullTBChan :: TBChan a -> STM Bool
isFullTBChan :: TBChan a -> STM Bool
isFullTBChan (TBChan TVar Int
slots TVar Int
reads TChan a
_chan) = do
Int
n <- TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
slots
if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
then do
Int
m <- TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
reads
let n' :: Int
n' = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
m
TVar Int -> Int -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
slots (Int -> STM ()) -> Int -> STM ()
forall a b. (a -> b) -> a -> b
$! Int
n'
TVar Int -> Int -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
reads Int
0
Bool -> STM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> STM Bool) -> Bool -> STM Bool
forall a b. (a -> b) -> a -> b
$! Int
n' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
else Bool -> STM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
estimateFreeSlotsTBChan :: TBChan a -> STM Int
estimateFreeSlotsTBChan :: TBChan a -> STM Int
estimateFreeSlotsTBChan (TBChan TVar Int
slots TVar Int
reads TChan a
_chan) = do
Int
n <- TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
slots
if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
then Int -> STM Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
n
else do
Int
m <- TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
reads
let n' :: Int
n' = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
m
TVar Int -> Int -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
slots (Int -> STM ()) -> Int -> STM ()
forall a b. (a -> b) -> a -> b
$! Int
n'
TVar Int -> Int -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
reads Int
0
Int -> STM Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
n'
freeSlotsTBChan :: TBChan a -> STM Int
freeSlotsTBChan :: TBChan a -> STM Int
freeSlotsTBChan (TBChan TVar Int
slots TVar Int
reads TChan a
_chan) = do
Int
n <- TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
slots
Int
m <- TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
reads
let n' :: Int
n' = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
m
TVar Int -> Int -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
slots (Int -> STM ()) -> Int -> STM ()
forall a b. (a -> b) -> a -> b
$! Int
n'
TVar Int -> Int -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
reads Int
0
Int -> STM Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
n'