module Control.Concurrent.Classy.BoundedChan
( BoundedChan
, newBoundedChan
, writeBoundedChan
, trywriteBoundedChan
, readBoundedChan
, tryreadBoundedChan
, isEmptyBoundedChan
, writeList2BoundedChan
) where
import Control.Monad (replicateM)
import Data.Array (Array, listArray, (!))
import qualified Control.Concurrent.Classy.MVar as MVar
import Control.Monad.Catch (mask_, onException)
import Control.Monad.Conc.Class (MonadConc(MVar))
data BoundedChan m a
= BoundedChan
{ forall (m :: * -> *) a. BoundedChan m a -> Int
_size :: Int
, forall (m :: * -> *) a. BoundedChan m a -> Array Int (MVar m a)
_contents :: Array Int (MVar m a)
, forall (m :: * -> *) a. BoundedChan m a -> MVar m Int
_writePos :: MVar m Int
, forall (m :: * -> *) a. BoundedChan m a -> MVar m Int
_readPos :: MVar m Int
}
deriving ()
{-# INLINE modifyMVarMask #-}
modifyMVarMask :: (MonadConc m) => MVar m a -> (a -> m (a, b)) -> m b
modifyMVarMask :: forall (m :: * -> *) a b.
MonadConc m =>
MVar m a -> (a -> m (a, b)) -> m b
modifyMVarMask MVar m a
m a -> m (a, b)
callback = forall (m :: * -> *) a. MonadMask m => m a -> m a
mask_ forall a b. (a -> b) -> a -> b
$ do
a
a <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m a
MVar.takeMVar MVar m a
m
(a
a', b
b) <- a -> m (a, b)
callback a
a forall (m :: * -> *) a b. MonadCatch m => m a -> m b -> m a
`onException` forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
MVar.putMVar MVar m a
m a
a
forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
MVar.putMVar MVar m a
m forall a b. (a -> b) -> a -> b
$! a
a'
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
b
{-# INLINE modifyMVarMask_ #-}
modifyMVarMask_ :: (MonadConc m) => MVar m a -> (a -> m a) -> m ()
modifyMVarMask_ :: forall (m :: * -> *) a.
MonadConc m =>
MVar m a -> (a -> m a) -> m ()
modifyMVarMask_ MVar m a
m a -> m a
callback =
forall (m :: * -> *) a. MonadMask m => m a -> m a
mask_ forall a b. (a -> b) -> a -> b
$ do
a
a <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m a
MVar.takeMVar MVar m a
m
a
a' <- a -> m a
callback a
a forall (m :: * -> *) a b. MonadCatch m => m a -> m b -> m a
`onException` forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
MVar.putMVar MVar m a
m a
a
forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
MVar.putMVar MVar m a
m forall a b. (a -> b) -> a -> b
$! a
a'
{-# INLINE withMVarMask #-}
withMVarMask :: (MonadConc m) => MVar m a -> (a -> m b) -> m b
withMVarMask :: forall (m :: * -> *) a b.
MonadConc m =>
MVar m a -> (a -> m b) -> m b
withMVarMask MVar m a
m a -> m b
callback =
forall (m :: * -> *) a. MonadMask m => m a -> m a
mask_ forall a b. (a -> b) -> a -> b
$ do
a
a <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m a
MVar.takeMVar MVar m a
m
b
b <- a -> m b
callback a
a forall (m :: * -> *) a b. MonadCatch m => m a -> m b -> m a
`onException` forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
MVar.putMVar MVar m a
m a
a
forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
MVar.putMVar MVar m a
m a
a
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
b
newBoundedChan :: (MonadConc m) => Int -> m (BoundedChan m a)
newBoundedChan :: forall (m :: * -> *) a. MonadConc m => Int -> m (BoundedChan m a)
newBoundedChan Int
x = do
[MVar m a]
entls <- forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
x forall (m :: * -> *) a. MonadConc m => m (MVar m a)
MVar.newEmptyMVar
MVar m Int
wpos <- forall (m :: * -> *) a. MonadConc m => a -> m (MVar m a)
MVar.newMVar Int
0
MVar m Int
rpos <- forall (m :: * -> *) a. MonadConc m => a -> m (MVar m a)
MVar.newMVar Int
0
let entries :: Array Int (MVar m a)
entries = forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, Int
x forall a. Num a => a -> a -> a
- Int
1) [MVar m a]
entls
forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall (m :: * -> *) a.
Int
-> Array Int (MVar m a)
-> MVar m Int
-> MVar m Int
-> BoundedChan m a
BoundedChan Int
x Array Int (MVar m a)
entries MVar m Int
wpos MVar m Int
rpos)
writeBoundedChan :: (MonadConc m) => BoundedChan m a -> a -> m ()
writeBoundedChan :: forall (m :: * -> *) a. MonadConc m => BoundedChan m a -> a -> m ()
writeBoundedChan (BoundedChan Int
size Array Int (MVar m a)
contents MVar m Int
wposMV MVar m Int
_) a
x =
forall (m :: * -> *) a.
MonadConc m =>
MVar m a -> (a -> m a) -> m ()
modifyMVarMask_ MVar m Int
wposMV forall a b. (a -> b) -> a -> b
$ \Int
wpos -> do
forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
MVar.putMVar (Array Int (MVar m a)
contents forall i e. Ix i => Array i e -> i -> e
! Int
wpos) a
x
forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Enum a => a -> a
succ Int
wpos forall a. Integral a => a -> a -> a
`mod` Int
size)
trywriteBoundedChan :: (MonadConc m) => BoundedChan m a -> a -> m Bool
trywriteBoundedChan :: forall (m :: * -> *) a.
MonadConc m =>
BoundedChan m a -> a -> m Bool
trywriteBoundedChan (BoundedChan Int
size Array Int (MVar m a)
contents MVar m Int
wposMV MVar m Int
_) a
x =
forall (m :: * -> *) a b.
MonadConc m =>
MVar m a -> (a -> m (a, b)) -> m b
modifyMVarMask MVar m Int
wposMV forall a b. (a -> b) -> a -> b
$ \Int
wpos -> do
Bool
success <- forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m Bool
MVar.tryPutMVar (Array Int (MVar m a)
contents forall i e. Ix i => Array i e -> i -> e
! Int
wpos) a
x
let wpos' :: Int
wpos' = if Bool
success then forall a. Enum a => a -> a
succ Int
wpos forall a. Integral a => a -> a -> a
`mod` Int
size else Int
wpos
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
wpos', Bool
success)
readBoundedChan :: (MonadConc m) => BoundedChan m a -> m a
readBoundedChan :: forall (m :: * -> *) a. MonadConc m => BoundedChan m a -> m a
readBoundedChan (BoundedChan Int
size Array Int (MVar m a)
contents MVar m Int
_ MVar m Int
rposMV) =
forall (m :: * -> *) a b.
MonadConc m =>
MVar m a -> (a -> m (a, b)) -> m b
modifyMVarMask MVar m Int
rposMV forall a b. (a -> b) -> a -> b
$ \Int
rpos -> do
a
a <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m a
MVar.takeMVar (Array Int (MVar m a)
contents forall i e. Ix i => Array i e -> i -> e
! Int
rpos)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Enum a => a -> a
succ Int
rpos forall a. Integral a => a -> a -> a
`mod` Int
size, a
a)
tryreadBoundedChan :: (MonadConc m) => BoundedChan m a -> m (Maybe a)
tryreadBoundedChan :: forall (m :: * -> *) a.
MonadConc m =>
BoundedChan m a -> m (Maybe a)
tryreadBoundedChan (BoundedChan Int
size Array Int (MVar m a)
contents MVar m Int
_ MVar m Int
rposMV) =
forall (m :: * -> *) a b.
MonadConc m =>
MVar m a -> (a -> m (a, b)) -> m b
modifyMVarMask MVar m Int
rposMV forall a b. (a -> b) -> a -> b
$ \Int
rpos -> do
Maybe a
ma <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m (Maybe a)
MVar.tryTakeMVar (Array Int (MVar m a)
contents forall i e. Ix i => Array i e -> i -> e
! Int
rpos)
let rpos' :: Int
rpos' = case Maybe a
ma of
Just a
_ -> forall a. Enum a => a -> a
succ Int
rpos forall a. Integral a => a -> a -> a
`mod` Int
size
Maybe a
Nothing -> Int
rpos
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
rpos', Maybe a
ma)
{-# DEPRECATED isEmptyBoundedChan
"This isEmptyBoundedChan can block, no non-blocking substitute yet" #-}
isEmptyBoundedChan :: (MonadConc m) => BoundedChan m a -> m Bool
isEmptyBoundedChan :: forall (m :: * -> *) a. MonadConc m => BoundedChan m a -> m Bool
isEmptyBoundedChan (BoundedChan Int
_ Array Int (MVar m a)
contents MVar m Int
_ MVar m Int
rposMV) =
forall (m :: * -> *) a b.
MonadConc m =>
MVar m a -> (a -> m b) -> m b
withMVarMask MVar m Int
rposMV forall a b. (a -> b) -> a -> b
$ \Int
rpos ->
forall (m :: * -> *) a. MonadConc m => MVar m a -> m Bool
MVar.isEmptyMVar (Array Int (MVar m a)
contents forall i e. Ix i => Array i e -> i -> e
! Int
rpos)
writeList2BoundedChan :: (MonadConc m) => BoundedChan m a -> [a] -> m ()
writeList2BoundedChan :: forall (m :: * -> *) a.
MonadConc m =>
BoundedChan m a -> [a] -> m ()
writeList2BoundedChan = forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. MonadConc m => BoundedChan m a -> a -> m ()
writeBoundedChan