@@ -34,6 +34,8 @@ module Control.Monad.Class.MonadSTM
34
34
, TBQueueDefault (.. )
35
35
-- * Default 'TArray' implementation
36
36
, TArrayDefault (.. )
37
+ -- * Default 'TSem' implementation
38
+ , TSemDefault (.. )
37
39
-- * MonadThrow aliases
38
40
, throwSTM
39
41
, catchSTM
@@ -53,8 +55,9 @@ import qualified Control.Concurrent.STM.TArray as STM
53
55
import qualified Control.Concurrent.STM.TBQueue as STM
54
56
import qualified Control.Concurrent.STM.TMVar as STM
55
57
import qualified Control.Concurrent.STM.TQueue as STM
58
+ import qualified Control.Concurrent.STM.TSem as STM
56
59
import qualified Control.Concurrent.STM.TVar as STM
57
- import Control.Monad (MonadPlus (.. ))
60
+ import Control.Monad (MonadPlus (.. ), when )
58
61
import qualified Control.Monad.STM as STM
59
62
60
63
import Control.Monad.Cont (ContT (.. ))
@@ -160,6 +163,12 @@ class ( Monad m
160
163
161
164
type TArray m :: Type -> Type -> Type
162
165
166
+ type TSem m :: Type
167
+ newTSem :: Integer -> STM m (TSem m )
168
+ waitTSem :: TSem m -> STM m ()
169
+ signalTSem :: TSem m -> STM m ()
170
+ signalTSemN :: Natural -> TSem m -> STM m ()
171
+
163
172
-- Helpful derived functions with default implementations
164
173
165
174
newTVarIO :: a -> m (TVar m a )
@@ -294,6 +303,22 @@ class ( Monad m
294
303
=> TBQueue m a -> a -> STM m ()
295
304
unGetTBQueue = unGetTBQueueDefault
296
305
306
+ default newTSem :: TSem m ~ TSemDefault m
307
+ => Integer -> STM m (TSem m)
308
+ newTSem = newTSemDefault
309
+
310
+ default waitTSem :: TSem m ~ TSemDefault m
311
+ => TSem m -> STM m ()
312
+ waitTSem = waitTSemDefault
313
+
314
+ default signalTSem :: TSem m ~ TSemDefault m
315
+ => TSem m -> STM m ()
316
+ signalTSem = signalTSemDefault
317
+
318
+ default signalTSemN :: TSem m ~ TSemDefault m
319
+ => Natural -> TSem m -> STM m ()
320
+ signalTSemN = signalTSemNDefault
321
+
297
322
298
323
stateTVarDefault :: MonadSTM m => TVar m s -> (s -> (a , s )) -> STM m a
299
324
stateTVarDefault var f = do
@@ -332,13 +357,15 @@ class MonadSTM m
332
357
labelTBQueue :: TBQueue m a -> String -> STM m ()
333
358
labelTArray :: (Ix i , Show i )
334
359
=> TArray m i e -> String -> STM m ()
360
+ labelTSem :: TSem m -> String -> STM m ()
335
361
336
362
labelTVarIO :: TVar m a -> String -> m ()
337
363
labelTMVarIO :: TMVar m a -> String -> m ()
338
364
labelTQueueIO :: TQueue m a -> String -> m ()
339
365
labelTBQueueIO :: TBQueue m a -> String -> m ()
340
366
labelTArrayIO :: (Ix i , Show i )
341
367
=> TArray m i e -> String -> m ()
368
+ labelTSemIO :: TSem m -> String -> m ()
342
369
343
370
--
344
371
-- default implementations
@@ -356,6 +383,10 @@ class MonadSTM m
356
383
=> TBQueue m a -> String -> STM m ()
357
384
labelTBQueue = labelTBQueueDefault
358
385
386
+ default labelTSem :: TSem m ~ TSemDefault m
387
+ => TSem m -> String -> STM m ()
388
+ labelTSem = labelTSemDefault
389
+
359
390
default labelTArray :: ( TArray m ~ TArrayDefault m
360
391
, Ix i
361
392
, Show i
@@ -379,6 +410,9 @@ class MonadSTM m
379
410
=> TArray m i e -> String -> m ()
380
411
labelTArrayIO = \ v l -> atomically (labelTArray v l)
381
412
413
+ default labelTSemIO :: TSem m -> String -> m ()
414
+ labelTSemIO = \ v l -> atomically (labelTSem v l)
415
+
382
416
383
417
-- | This type class is indented for 'io-sim', where one might want to access
384
418
-- 'TVar' in the underlying 'ST' monad.
@@ -471,14 +505,25 @@ class MonadInspectSTM m
471
505
-> (Maybe [a ] -> [a ] -> InspectMonad m TraceValue )
472
506
-> STM m ()
473
507
474
- default traceTMVar :: ( TMVar m a ~ TMVarDefault m a
475
- )
508
+ traceTSem :: proxy m
509
+ -> TSem m
510
+ -> (Maybe Integer -> Integer -> InspectMonad m TraceValue )
511
+ -> STM m ()
512
+
513
+ default traceTMVar :: TMVar m a ~ TMVarDefault m a
476
514
=> proxy m
477
515
-> TMVar m a
478
516
-> (Maybe (Maybe a) -> (Maybe a) -> InspectMonad m TraceValue )
479
517
-> STM m ()
480
518
traceTMVar = traceTMVarDefault
481
519
520
+ default traceTSem :: TSem m ~ TSemDefault m
521
+ => proxy m
522
+ -> TSem m
523
+ -> (Maybe Integer -> Integer -> InspectMonad m TraceValue )
524
+ -> STM m ()
525
+ traceTSem = traceTSemDefault
526
+
482
527
483
528
traceTVarIO :: proxy m
484
529
-> TVar m a
@@ -500,6 +545,11 @@ class MonadInspectSTM m
500
545
-> (Maybe [a ] -> [a ] -> InspectMonad m TraceValue )
501
546
-> m ()
502
547
548
+ traceTSemIO :: proxy m
549
+ -> TSem m
550
+ -> (Maybe Integer -> Integer -> InspectMonad m TraceValue )
551
+ -> m ()
552
+
503
553
default traceTVarIO :: proxy m
504
554
-> TVar m a
505
555
-> (Maybe a -> a -> InspectMonad m TraceValue )
@@ -524,6 +574,12 @@ class MonadInspectSTM m
524
574
-> m ()
525
575
traceTBQueueIO = \ p v f -> atomically (traceTBQueue p v f)
526
576
577
+ default traceTSemIO :: proxy m
578
+ -> TSem m
579
+ -> (Maybe Integer -> Integer -> InspectMonad m TraceValue )
580
+ -> m ()
581
+ traceTSemIO = \ p v f -> atomically (traceTSem p v f)
582
+
527
583
528
584
--
529
585
-- Instance for IO uses the existing STM library implementations
@@ -539,6 +595,7 @@ instance MonadSTM IO where
539
595
type TQueue IO = STM. TQueue
540
596
type TBQueue IO = STM. TBQueue
541
597
type TArray IO = STM. TArray
598
+ type TSem IO = STM. TSem
542
599
543
600
newTVar = STM. newTVar
544
601
readTVar = STM. readTVar
@@ -579,6 +636,10 @@ instance MonadSTM IO where
579
636
isEmptyTBQueue = STM. isEmptyTBQueue
580
637
isFullTBQueue = STM. isFullTBQueue
581
638
unGetTBQueue = STM. unGetTBQueue
639
+ newTSem = STM. newTSem
640
+ waitTSem = STM. waitTSem
641
+ signalTSem = STM. signalTSem
642
+ signalTSemN = STM. signalTSemN
582
643
583
644
newTVarIO = STM. newTVarIO
584
645
readTVarIO = STM. readTVarIO
@@ -595,12 +656,14 @@ instance MonadLabelledSTM IO where
595
656
labelTQueue = \ _ _ -> return ()
596
657
labelTBQueue = \ _ _ -> return ()
597
658
labelTArray = \ _ _ -> return ()
659
+ labelTSem = \ _ _ -> return ()
598
660
599
661
labelTVarIO = \ _ _ -> return ()
600
662
labelTMVarIO = \ _ _ -> return ()
601
663
labelTQueueIO = \ _ _ -> return ()
602
664
labelTBQueueIO = \ _ _ -> return ()
603
665
labelTArrayIO = \ _ _ -> return ()
666
+ labelTSemIO = \ _ _ -> return ()
604
667
605
668
-- | noop instance
606
669
--
@@ -609,11 +672,13 @@ instance MonadTraceSTM IO where
609
672
traceTMVar = \ _ _ _ -> return ()
610
673
traceTQueue = \ _ _ _ -> return ()
611
674
traceTBQueue = \ _ _ _ -> return ()
675
+ traceTSem = \ _ _ _ -> return ()
612
676
613
677
traceTVarIO = \ _ _ _ -> return ()
614
678
traceTMVarIO = \ _ _ _ -> return ()
615
679
traceTQueueIO = \ _ _ _ -> return ()
616
680
traceTBQueueIO = \ _ _ _ -> return ()
681
+ traceTSemIO = \ _ _ _ -> return ()
617
682
618
683
-- | Wrapper around 'BlockedIndefinitelyOnSTM' that stores a call stack
619
684
data BlockedIndefinitely = BlockedIndefinitely {
@@ -981,6 +1046,44 @@ labelTArrayDefault (TArray arr) name = do
981
1046
let as = Array. assocs arr
982
1047
traverse_ (\ (i, v) -> labelTVar v (name ++ " :" ++ show i)) as
983
1048
1049
+
1050
+ --
1051
+ -- Default `TSem` implementation
1052
+ --
1053
+
1054
+ newtype TSemDefault m = TSem (TVar m Integer )
1055
+
1056
+ labelTSemDefault :: MonadLabelledSTM m => TSemDefault m -> String -> STM m ()
1057
+ labelTSemDefault (TSem t) = labelTVar t
1058
+
1059
+ traceTSemDefault :: MonadTraceSTM m
1060
+ => proxy m
1061
+ -> TSemDefault m
1062
+ -> (Maybe Integer -> Integer -> InspectMonad m TraceValue )
1063
+ -> STM m ()
1064
+ traceTSemDefault proxy (TSem t) k = traceTVar proxy t k
1065
+
1066
+ newTSemDefault :: MonadSTM m => Integer -> STM m (TSemDefault m )
1067
+ newTSemDefault i = TSem <$> (newTVar $! i)
1068
+
1069
+ waitTSemDefault :: MonadSTM m => TSemDefault m -> STM m ()
1070
+ waitTSemDefault (TSem t) = do
1071
+ i <- readTVar t
1072
+ when (i <= 0 ) retry
1073
+ writeTVar t $! (i- 1 )
1074
+
1075
+ signalTSemDefault :: MonadSTM m => TSemDefault m -> STM m ()
1076
+ signalTSemDefault (TSem t) = do
1077
+ i <- readTVar t
1078
+ writeTVar t $! i+ 1
1079
+
1080
+ signalTSemNDefault :: MonadSTM m => Natural -> TSemDefault m -> STM m ()
1081
+ signalTSemNDefault 0 _ = return ()
1082
+ signalTSemNDefault 1 s = signalTSemDefault s
1083
+ signalTSemNDefault n (TSem t) = do
1084
+ i <- readTVar t
1085
+ writeTVar t $! i+ (toInteger n)
1086
+
984
1087
-- | 'throwIO' specialised to @stm@ monad.
985
1088
--
986
1089
throwSTM :: (MonadSTM m , MonadThrow. MonadThrow (STM m ), Exception e )
@@ -1094,6 +1197,12 @@ instance MonadSTM m => MonadSTM (ContT r m) where
1094
1197
1095
1198
type TArray (ContT r m ) = TArray m
1096
1199
1200
+ type TSem (ContT r m ) = TSem m
1201
+ newTSem = WrappedSTM . newTSem
1202
+ waitTSem = WrappedSTM . waitTSem
1203
+ signalTSem = WrappedSTM . signalTSem
1204
+ signalTSemN = WrappedSTM .: signalTSemN
1205
+
1097
1206
1098
1207
instance MonadSTM m => MonadSTM (ReaderT r m ) where
1099
1208
type STM (ReaderT r m ) = WrappedSTM Reader r m
@@ -1149,6 +1258,12 @@ instance MonadSTM m => MonadSTM (ReaderT r m) where
1149
1258
1150
1259
type TArray (ReaderT r m ) = TArray m
1151
1260
1261
+ type TSem (ReaderT r m ) = TSem m
1262
+ newTSem = WrappedSTM . newTSem
1263
+ waitTSem = WrappedSTM . waitTSem
1264
+ signalTSem = WrappedSTM . signalTSem
1265
+ signalTSemN = WrappedSTM .: signalTSemN
1266
+
1152
1267
1153
1268
instance (Monoid w , MonadSTM m ) => MonadSTM (WriterT w m ) where
1154
1269
type STM (WriterT w m ) = WrappedSTM Writer w m
@@ -1204,6 +1319,12 @@ instance (Monoid w, MonadSTM m) => MonadSTM (WriterT w m) where
1204
1319
1205
1320
type TArray (WriterT w m ) = TArray m
1206
1321
1322
+ type TSem (WriterT w m ) = TSem m
1323
+ newTSem = WrappedSTM . newTSem
1324
+ waitTSem = WrappedSTM . waitTSem
1325
+ signalTSem = WrappedSTM . signalTSem
1326
+ signalTSemN = WrappedSTM .: signalTSemN
1327
+
1207
1328
1208
1329
instance MonadSTM m => MonadSTM (StateT s m ) where
1209
1330
type STM (StateT s m ) = WrappedSTM State s m
@@ -1259,6 +1380,12 @@ instance MonadSTM m => MonadSTM (StateT s m) where
1259
1380
1260
1381
type TArray (StateT s m ) = TArray m
1261
1382
1383
+ type TSem (StateT s m ) = TSem m
1384
+ newTSem = WrappedSTM . newTSem
1385
+ waitTSem = WrappedSTM . waitTSem
1386
+ signalTSem = WrappedSTM . signalTSem
1387
+ signalTSemN = WrappedSTM .: signalTSemN
1388
+
1262
1389
1263
1390
instance MonadSTM m => MonadSTM (ExceptT e m ) where
1264
1391
type STM (ExceptT e m ) = WrappedSTM Except e m
@@ -1314,6 +1441,12 @@ instance MonadSTM m => MonadSTM (ExceptT e m) where
1314
1441
1315
1442
type TArray (ExceptT e m ) = TArray m
1316
1443
1444
+ type TSem (ExceptT e m ) = TSem m
1445
+ newTSem = WrappedSTM . newTSem
1446
+ waitTSem = WrappedSTM . waitTSem
1447
+ signalTSem = WrappedSTM . signalTSem
1448
+ signalTSemN = WrappedSTM .: signalTSemN
1449
+
1317
1450
1318
1451
instance (Monoid w , MonadSTM m ) => MonadSTM (RWST r w s m ) where
1319
1452
type STM (RWST r w s m ) = WrappedSTM RWS (r , w , s ) m
@@ -1369,6 +1502,12 @@ instance (Monoid w, MonadSTM m) => MonadSTM (RWST r w s m) where
1369
1502
1370
1503
type TArray (RWST r w s m ) = TArray m
1371
1504
1505
+ type TSem (RWST r w s m ) = TSem m
1506
+ newTSem = WrappedSTM . newTSem
1507
+ waitTSem = WrappedSTM . waitTSem
1508
+ signalTSem = WrappedSTM . signalTSem
1509
+ signalTSemN = WrappedSTM .: signalTSemN
1510
+
1372
1511
1373
1512
(.:) :: (c -> d ) -> (a -> b -> c ) -> (a -> b -> d )
1374
1513
(f .: g) x y = f (g x y)
0 commit comments