module Control.Concurrent.Classy.QSemN
(
QSemN
, newQSemN
, waitQSemN
, signalQSemN
) where
import Control.Concurrent.Classy.MVar
import Control.Monad.Catch (mask_, onException,
uninterruptibleMask_)
import Control.Monad.Conc.Class (MonadConc)
import Control.Monad.Fail (MonadFail)
import Data.Maybe
newtype QSemN m = QSemN (MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())]))
newQSemN :: (MonadConc m, MonadFail m) => Int -> m (QSemN m)
newQSemN :: forall (m :: * -> *).
(MonadConc m, MonadFail m) =>
Int -> m (QSemN m)
newQSemN Int
initial
| Int
initial forall a. Ord a => a -> a -> Bool
< Int
0 = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"newQSemN: Initial quantity must be non-negative"
| Bool
otherwise = forall (m :: * -> *).
MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())]) -> QSemN m
QSemN forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadConc m => a -> m (MVar m a)
newMVar (Int
initial, [], [])
waitQSemN :: MonadConc m => QSemN m -> Int -> m ()
waitQSemN :: forall (m :: * -> *). MonadConc m => QSemN m -> Int -> m ()
waitQSemN (QSemN MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
m) Int
sz = forall (m :: * -> *) a. MonadMask m => m a -> m a
mask_ forall a b. (a -> b) -> a -> b
$ do
(Int
quantity, [(Int, MVar m ())]
b1, [(Int, MVar m ())]
b2) <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m a
takeMVar MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
m
let remaining :: Int
remaining = Int
quantity forall a. Num a => a -> a -> a
- Int
sz
if Int
remaining forall a. Ord a => a -> a -> Bool
< Int
0
then do
MVar m ()
b <- forall (m :: * -> *) a. MonadConc m => m (MVar m a)
newEmptyMVar
forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
putMVar MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
m (Int
quantity, [(Int, MVar m ())]
b1, (Int
sz,MVar m ()
b)forall a. a -> [a] -> [a]
:[(Int, MVar m ())]
b2)
MVar m () -> m ()
wait MVar m ()
b
else
forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
putMVar MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
m (Int
remaining, [(Int, MVar m ())]
b1, [(Int, MVar m ())]
b2)
where
wait :: MVar m () -> m ()
wait MVar m ()
b = forall (m :: * -> *) a. MonadConc m => MVar m a -> m a
takeMVar MVar m ()
b forall (m :: * -> *) a b. MonadCatch m => m a -> m b -> m a
`onException` forall (m :: * -> *) a. MonadMask m => m a -> m a
uninterruptibleMask_ (do
(Int
quantity, [(Int, MVar m ())]
b1, [(Int, MVar m ())]
b2) <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m a
takeMVar MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
m
Maybe ()
r <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m (Maybe a)
tryTakeMVar MVar m ()
b
(Int, [(Int, MVar m ())], [(Int, MVar m ())])
r' <- if forall a. Maybe a -> Bool
isJust Maybe ()
r
then forall (m :: * -> *).
MonadConc m =>
Int
-> (Int, [(Int, MVar m ())], [(Int, MVar m ())])
-> m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
signal Int
sz (Int
quantity, [(Int, MVar m ())]
b1, [(Int, MVar m ())]
b2)
else forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
putMVar MVar m ()
b () forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
quantity, [(Int, MVar m ())]
b1, [(Int, MVar m ())]
b2)
forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
putMVar MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
r')
signalQSemN :: MonadConc m => QSemN m -> Int -> m ()
signalQSemN :: forall (m :: * -> *). MonadConc m => QSemN m -> Int -> m ()
signalQSemN (QSemN MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
m) Int
sz = forall (m :: * -> *) a. MonadMask m => m a -> m a
uninterruptibleMask_ forall a b. (a -> b) -> a -> b
$ do
(Int, [(Int, MVar m ())], [(Int, MVar m ())])
r <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m a
takeMVar MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
m
(Int, [(Int, MVar m ())], [(Int, MVar m ())])
r' <- forall (m :: * -> *).
MonadConc m =>
Int
-> (Int, [(Int, MVar m ())], [(Int, MVar m ())])
-> m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
signal Int
sz (Int, [(Int, MVar m ())], [(Int, MVar m ())])
r
forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m ()
putMVar MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
r'
signal :: MonadConc m
=> Int
-> (Int, [(Int,MVar m ())], [(Int,MVar m ())])
-> m (Int, [(Int,MVar m ())], [(Int,MVar m ())])
signal :: forall (m :: * -> *).
MonadConc m =>
Int
-> (Int, [(Int, MVar m ())], [(Int, MVar m ())])
-> m (Int, [(Int, MVar m ())], [(Int, MVar m ())])
signal Int
sz0 (Int
i,[(Int, MVar m ())]
a1,[(Int, MVar m ())]
a2) = forall {a} {f :: * -> *}.
(Num a, MonadConc f, Ord a) =>
a
-> [(a, MVar f ())]
-> [(a, MVar f ())]
-> f (a, [(a, MVar f ())], [(a, MVar f ())])
loop (Int
sz0 forall a. Num a => a -> a -> a
+ Int
i) [(Int, MVar m ())]
a1 [(Int, MVar m ())]
a2 where
loop :: a
-> [(a, MVar f ())]
-> [(a, MVar f ())]
-> f (a, [(a, MVar f ())], [(a, MVar f ())])
loop a
0 [(a, MVar f ())]
bs [(a, MVar f ())]
b2 = forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
0, [(a, MVar f ())]
bs, [(a, MVar f ())]
b2)
loop a
sz [] [] = forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
sz, [], [])
loop a
sz [] [(a, MVar f ())]
b2 = a
-> [(a, MVar f ())]
-> [(a, MVar f ())]
-> f (a, [(a, MVar f ())], [(a, MVar f ())])
loop a
sz (forall a. [a] -> [a]
reverse [(a, MVar f ())]
b2) []
loop a
sz ((a
j,MVar f ()
b):[(a, MVar f ())]
bs) [(a, MVar f ())]
b2
| a
j forall a. Ord a => a -> a -> Bool
> a
sz = do
Bool
r <- forall (m :: * -> *) a. MonadConc m => MVar m a -> m Bool
isEmptyMVar MVar f ()
b
if Bool
r then forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
sz, (a
j,MVar f ()
b)forall a. a -> [a] -> [a]
:[(a, MVar f ())]
bs, [(a, MVar f ())]
b2)
else a
-> [(a, MVar f ())]
-> [(a, MVar f ())]
-> f (a, [(a, MVar f ())], [(a, MVar f ())])
loop a
sz [(a, MVar f ())]
bs [(a, MVar f ())]
b2
| Bool
otherwise = do
Bool
r <- forall (m :: * -> *) a. MonadConc m => MVar m a -> a -> m Bool
tryPutMVar MVar f ()
b ()
if Bool
r then a
-> [(a, MVar f ())]
-> [(a, MVar f ())]
-> f (a, [(a, MVar f ())], [(a, MVar f ())])
loop (a
szforall a. Num a => a -> a -> a
-a
j) [(a, MVar f ())]
bs [(a, MVar f ())]
b2
else a
-> [(a, MVar f ())]
-> [(a, MVar f ())]
-> f (a, [(a, MVar f ())], [(a, MVar f ())])
loop a
sz [(a, MVar f ())]
bs [(a, MVar f ())]
b2