7
7
{-# LANGUAGE FlexibleInstances #-}
8
8
{-# LANGUAGE GADTSyntax #-}
9
9
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10
+ {-# LANGUAGE LambdaCase #-}
10
11
{-# LANGUAGE MultiParamTypeClasses #-}
11
12
{-# LANGUAGE NamedFieldPuns #-}
12
13
{-# LANGUAGE RankNTypes #-}
@@ -24,6 +25,7 @@ module Control.Monad.IOSim.Internal (
24
25
runIOSim ,
25
26
runSimTraceST ,
26
27
traceM ,
28
+ traceSTM ,
27
29
STM ,
28
30
STMSim ,
29
31
SimSTM ,
@@ -97,6 +99,9 @@ runIOSim (IOSim k) = k Return
97
99
traceM :: Typeable a => a -> IOSim s ()
98
100
traceM x = IOSim $ \ k -> Output (toDyn x) (k () )
99
101
102
+ traceSTM :: Typeable a => a -> STMSim s ()
103
+ traceSTM x = STM $ \ k -> OutputStm (toDyn x) (k () )
104
+
100
105
data SimA s a where
101
106
Return :: a -> SimA s a
102
107
@@ -146,6 +151,9 @@ data StmA s a where
146
151
Retry :: StmA s b
147
152
OrElse :: StmA s a -> StmA s a -> (a -> StmA s b ) -> StmA s b
148
153
154
+ SayStm :: String -> StmA s b -> StmA s b
155
+ OutputStm :: Dynamic -> StmA s b -> StmA s b
156
+
149
157
-- Exported type
150
158
type STMSim = STM
151
159
@@ -314,6 +322,9 @@ instance MonadFork (IOSim s) where
314
322
forkIOWithUnmask f = forkIO (f unblock)
315
323
throwTo tid e = IOSim $ \ k -> ThrowTo (toException e) tid (k () )
316
324
325
+ instance MonadSay (STMSim s ) where
326
+ say msg = STM $ \ k -> SayStm msg (k () )
327
+
317
328
instance MonadSTMTx (STM s ) where
318
329
type TVar_ (STM s ) = TVar s
319
330
type TMVar_ (STM s ) = TMVarDefault (IOSim s )
@@ -866,8 +877,7 @@ schedule thread@Thread{
866
877
, nextTid = succ nextTid }
867
878
return (Trace time tid tlbl (EventThreadForked tid') trace)
868
879
869
- Atomically a k -> do
870
- res <- execAtomically nextVid (runSTM a)
880
+ Atomically a k -> execAtomically time tid tlbl nextVid (runSTM a) $ \ res ->
871
881
case res of
872
882
StmTxCommitted x written nextVid' -> do
873
883
(wakeup, wokeby) <- threadsUnblockedByWrites written
@@ -897,13 +907,13 @@ schedule thread@Thread{
897
907
-- schedule this thread to immediately raise the exception
898
908
let thread' = thread { threadControl = ThreadControl (Throw e) ctl }
899
909
trace <- schedule thread' simstate
900
- return ( Trace time tid tlbl EventTxAborted trace)
910
+ return $ Trace time tid tlbl EventTxAborted trace
901
911
902
912
StmTxBlocked read -> do
903
913
mapM_ (\ (SomeTVar tvar) -> blockThreadOnTVar tid tvar) read
904
914
vids <- traverse (\ (SomeTVar tvar) -> labelledTVarId tvar) read
905
915
trace <- deschedule Blocked thread simstate
906
- return ( Trace time tid tlbl (EventTxBlocked vids) trace)
916
+ return $ Trace time tid tlbl (EventTxBlocked vids) trace
907
917
908
918
GetThreadId k -> do
909
919
let thread' = thread { threadControl = ThreadControl (k tid) ctl }
@@ -1278,12 +1288,16 @@ data StmStack s b a where
1278
1288
-> StmStack s b c
1279
1289
-> StmStack s a c
1280
1290
1281
- execAtomically :: forall s a .
1282
- TVarId
1291
+ execAtomically :: forall s a c .
1292
+ Time
1293
+ -> ThreadId
1294
+ -> Maybe ThreadLabel
1295
+ -> TVarId
1283
1296
-> StmA s a
1284
- -> ST s (StmTxResult s a )
1285
- execAtomically =
1286
- go AtomicallyFrame Map. empty Map. empty []
1297
+ -> (StmTxResult s a -> ST s (Trace c ))
1298
+ -> ST s (Trace c )
1299
+ execAtomically time tid tlbl nextVid0 action0 k0 =
1300
+ go AtomicallyFrame Map. empty Map. empty [] nextVid0 action0
1287
1301
where
1288
1302
go :: forall b .
1289
1303
StmStack s b a
@@ -1292,7 +1306,7 @@ execAtomically =
1292
1306
-> [SomeTVar s ] -- vars written in order (no dups)
1293
1307
-> TVarId -- var fresh name supply
1294
1308
-> StmA s b
1295
- -> ST s (StmTxResult s a )
1309
+ -> ST s (Trace c )
1296
1310
go ctl ! read ! written writtenSeq ! nextVid action = assert localInvariant $
1297
1311
case action of
1298
1312
ReturnStm x -> case ctl of
@@ -1307,7 +1321,7 @@ execAtomically =
1307
1321
) written
1308
1322
1309
1323
-- Return the vars written, so readers can be unblocked
1310
- return ( StmTxCommitted x (reverse writtenSeq) nextVid)
1324
+ k0 $ StmTxCommitted x (reverse writtenSeq) nextVid
1311
1325
1312
1326
OrElseLeftFrame _b k writtenOuter writtenOuterSeq ctl' -> do
1313
1327
-- Commit the TVars written in this sub-transaction that are also
@@ -1340,14 +1354,14 @@ execAtomically =
1340
1354
ThrowStm e -> do
1341
1355
-- Revert all the TVar writes
1342
1356
traverse_ (\ (SomeTVar tvar) -> revertTVar tvar) written
1343
- return ( StmTxAborted (toException e) )
1357
+ k0 $ StmTxAborted (toException e)
1344
1358
1345
1359
Retry -> case ctl of
1346
1360
AtomicallyFrame -> do
1347
1361
-- Revert all the TVar writes
1348
1362
traverse_ (\ (SomeTVar tvar) -> revertTVar tvar) written
1349
1363
-- Return vars read, so the thread can block on them
1350
- return ( StmTxBlocked (Map. elems read ) )
1364
+ k0 $ StmTxBlocked (Map. elems read )
1351
1365
1352
1366
OrElseLeftFrame b k writtenOuter writtenOuterSeq ctl' -> do
1353
1367
-- Revert all the TVar writes within this orElse
@@ -1394,6 +1408,15 @@ execAtomically =
1394
1408
execWriteTVar v x
1395
1409
let written' = Map. insert (tvarId v) (SomeTVar v) written
1396
1410
go ctl read written' (SomeTVar v : writtenSeq) nextVid k
1411
+
1412
+ SayStm msg k -> do
1413
+ trace <- go ctl read written writtenSeq nextVid k
1414
+ return $ Trace time tid tlbl (EventSay msg) trace
1415
+
1416
+ OutputStm x k -> do
1417
+ trace <- go ctl read written writtenSeq nextVid k
1418
+ return $ Trace time tid tlbl (EventLog x) trace
1419
+
1397
1420
where
1398
1421
localInvariant =
1399
1422
Map. keysSet written
0 commit comments