Skip to content

Commit 2006f03

Browse files
committed
Add QSem to IOSim
1 parent 2f0b883 commit 2006f03

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed

io-classes/io-classes.cabal

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

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

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ import Control.Monad.Fix (MonadFix (..))
8484

8585
import Control.Concurrent.Class.MonadChan hiding (Chan)
8686
import Control.Concurrent.Class.MonadChan qualified as MonadAsync
87+
import Control.Concurrent.Class.MonadQSem hiding (QSem)
88+
import Control.Concurrent.Class.MonadQSem qualified as MonadQSem
8789
import Control.Concurrent.Class.MonadMVar
8890
import Control.Concurrent.Class.MonadSTM.Strict.TVar (StrictTVar)
8991
import Control.Concurrent.Class.MonadSTM.Strict.TVar qualified as StrictTVar
@@ -120,7 +122,7 @@ import Data.Bifunctor (bimap)
120122
import Data.Dynamic (Dynamic, toDyn)
121123
import Data.List.Trace qualified as Trace
122124
import Data.Map.Strict (Map)
123-
import Data.Maybe (fromMaybe)
125+
import Data.Maybe (fromMaybe, isJust)
124126
import Data.Monoid (Endo (..))
125127
import Data.Semigroup (Max (..))
126128
import Data.STRef.Lazy
@@ -817,6 +819,61 @@ instance MonadChan (IOSim s) where
817819
xs <- getChanContents ch
818820
return (x:xs)
819821

822+
newtype QSem m = QSem (MVar m (Int, [MVar m ()], [MVar m ()]))
823+
824+
signal
825+
:: MonadMVar m
826+
=> (Int, [MVar m ()], [MVar m ()])
827+
-> m (Int, [MVar m ()], [MVar m ()])
828+
signal (i,a1,a2) =
829+
if i == 0
830+
then loop a1 a2
831+
else let !z = i+1 in return (z, a1, a2)
832+
where
833+
loop [] [] = return (1, [], [])
834+
loop [] b2 = loop (reverse b2) []
835+
loop (b:bs) b2 = do
836+
r <- tryPutMVar b ()
837+
if r then return (0, bs, b2)
838+
else loop bs b2
839+
840+
instance MonadQSem (IOSim s) where
841+
type QSem (IOSim s) = QSem (IOSim s)
842+
843+
newQSem initial
844+
| initial < 0 = fail "newQSem: Initial quantity must be non-negative"
845+
| otherwise = do
846+
sem <- newMVar (initial, [], [])
847+
return (QSem sem)
848+
849+
waitQSem (QSem m) =
850+
mask_ $ do
851+
(i,b1,b2) <- takeMVar m
852+
if i == 0
853+
then do
854+
b <- newEmptyMVar
855+
putMVar m (i, b1, b:b2)
856+
uninterruptibleWait b
857+
else do
858+
let !z = i-1
859+
putMVar m (z, b1, b2)
860+
return ()
861+
where
862+
uninterruptibleWait b =
863+
takeMVar b `onException`
864+
uninterruptibleMask_ (do
865+
(i,b1,b2) <- takeMVar m
866+
r <- tryTakeMVar b
867+
r' <- if isJust r
868+
then signal (i,b1,b2)
869+
else do putMVar b (); return (i,b1,b2)
870+
putMVar m r')
871+
signalQSem (QSem m) =
872+
uninterruptibleMask_ $ do
873+
r <- takeMVar m
874+
r' <- signal r
875+
putMVar m r'
876+
820877
-- | 'Trace' is a recursive data type, it is the trace of a 'IOSim'
821878
-- computation. The trace will contain information about thread scheduling,
822879
-- blocking on 'TVar's, and other internal state changes of 'IOSim'. More

0 commit comments

Comments
 (0)