Skip to content

Commit bbc1e1f

Browse files
committed
Add QSemN to IOSim
1 parent 2006f03 commit bbc1e1f

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

io-classes/io-classes.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ library
6969
-- This has to be tidied up once the design becomes clear.
7070
exposed-modules: Control.Concurrent.Class.MonadChan
7171
Control.Concurrent.Class.MonadQSem
72+
Control.Concurrent.Class.MonadQSemN
7273
Control.Concurrent.Class.MonadMVar
7374
Control.Concurrent.Class.MonadSTM
7475
Control.Concurrent.Class.MonadSTM.TArray
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{-# LANGUAGE TypeFamilies #-}
2+
3+
module Control.Concurrent.Class.MonadQSemN
4+
( MonadQSemN (..)
5+
) where
6+
7+
import Control.Concurrent.QSemN qualified as IO
8+
9+
import Data.Kind (Type)
10+
11+
class Monad m => MonadQSemN m where
12+
{-# MINIMAL newQSemN, waitQSemN, signalQSemN #-}
13+
14+
type QSemN m :: Type
15+
16+
-- | See 'IO.newQSemN.
17+
newQSemN :: Int -> m (QSemN m)
18+
-- | See 'IO.waitQSemN'.
19+
waitQSemN :: QSemN m -> Int -> m ()
20+
-- | See 'IO.signalQSemN'.
21+
signalQSemN :: QSemN m -> Int -> m ()
22+
23+
--
24+
-- IO instance
25+
--
26+
27+
instance MonadQSemN IO where
28+
type QSemN IO = IO.QSemN
29+
30+
newQSemN = IO.newQSemN
31+
waitQSemN = IO.waitQSemN
32+
signalQSemN = IO.signalQSemN
33+

io-sim/src/Control/Monad/IOSim/Types.hs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ import Control.Concurrent.Class.MonadChan hiding (Chan)
8686
import Control.Concurrent.Class.MonadChan qualified as MonadAsync
8787
import Control.Concurrent.Class.MonadQSem hiding (QSem)
8888
import Control.Concurrent.Class.MonadQSem qualified as MonadQSem
89+
import Control.Concurrent.Class.MonadQSemN hiding (QSemN)
90+
import Control.Concurrent.Class.MonadQSemN qualified as MonadQSemN
8991
import Control.Concurrent.Class.MonadMVar
9092
import Control.Concurrent.Class.MonadSTM.Strict.TVar (StrictTVar)
9193
import Control.Concurrent.Class.MonadSTM.Strict.TVar qualified as StrictTVar
@@ -874,6 +876,57 @@ instance MonadQSem (IOSim s) where
874876
r' <- signal r
875877
putMVar m r'
876878

879+
newtype QSemN m = QSemN (MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())]))
880+
881+
data MaybeMV m a = JustMV !(MVarDefault m a)
882+
| NothingMV
883+
884+
instance MonadQSemN (IOSim s) where
885+
type QSemN (IOSim s) = QSemN (IOSim s)
886+
887+
newQSemN initial
888+
| initial < 0 = fail "newQSemN: Initial quantity must be non-negative"
889+
| otherwise = do
890+
sem <- newMVar (initial, [], [])
891+
return (QSemN sem)
892+
893+
waitQSemN qs@(QSemN m) sz = mask_ $ do
894+
mmvar <- modifyMVar m $ \ (i,b1,b2) -> do
895+
let z = i-sz
896+
if z < 0
897+
then do
898+
b <- newEmptyMVar
899+
return ((i, b1, (sz,b):b2), JustMV b)
900+
else return ((z, b1, b2), NothingMV)
901+
902+
case mmvar of
903+
NothingMV -> return ()
904+
JustMV b -> wait' b
905+
where
906+
wait' :: MVar (IOSim s) () -> IOSim s ()
907+
wait' b =
908+
takeMVar b `onException` do
909+
already_filled <- not <$> tryPutMVar b ()
910+
when already_filled $ signalQSemN qs sz
911+
912+
signalQSemN (QSemN m) sz0 = do
913+
unit <- modifyMVar m $ \(i,a1,a2) -> loop (sz0 + i) a1 a2
914+
915+
evaluate unit
916+
where
917+
loop 0 bs b2 = return ((0, bs, b2), ())
918+
loop sz [] [] = return ((sz, [], []), ())
919+
loop sz [] b2 = loop sz (reverse b2) []
920+
loop sz ((j,b):bs) b2
921+
| j > sz = do
922+
r <- isEmptyMVar b
923+
if r then return ((sz, (j,b):bs, b2), ())
924+
else loop sz bs b2
925+
| otherwise = do
926+
r <- tryPutMVar b ()
927+
if r then loop (sz-j) bs b2
928+
else loop sz bs b2
929+
877930
-- | 'Trace' is a recursive data type, it is the trace of a 'IOSim'
878931
-- computation. The trace will contain information about thread scheduling,
879932
-- blocking on 'TVar's, and other internal state changes of 'IOSim'. More

0 commit comments

Comments
 (0)