Skip to content

Commit 389ebe4

Browse files
committed
io-sim: MonadLabelledSTM instance
1 parent 944d46e commit 389ebe4

File tree

3 files changed

+71
-36
lines changed

3 files changed

+71
-36
lines changed

io-sim-classes/src/Control/Monad/Class/MonadSTM.hs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,9 @@ class MonadSTMTx stm => MonadLabelledSTMTx stm where
199199
labelTQueue :: TQueue_ stm a -> String -> stm ()
200200
labelTBQueue :: TBQueue_ stm a -> String -> stm ()
201201

202-
-- | A convenience class which provides 'MonadSTM' and 'MonadLabelledSTMTx' constraints.
202+
-- | A convenience class which provides 'MonadSTM' and 'MonadLabelledSTMTx'
203+
-- constraints.
204+
--
203205
class (MonadSTM m, MonadLabelledSTMTx (STM m))
204206
=> MonadLabelledSTM m where
205207
labelTVarIO :: TVar m a -> String -> m ()
@@ -272,12 +274,16 @@ instance MonadSTM IO where
272274
newTMVarIO = STM.newTMVarIO
273275
newEmptyTMVarIO = STM.newEmptyTMVarIO
274276

277+
-- | noop instance
278+
--
275279
instance MonadLabelledSTMTx STM.STM where
276280
labelTVar = \_ _ -> return ()
277281
labelTMVar = \_ _ -> return ()
278282
labelTQueue = \_ _ -> return ()
279283
labelTBQueue = \_ _ -> return ()
280284

285+
-- | noop instance
286+
--
281287
instance MonadLabelledSTM IO where
282288
labelTVarIO = \_ _ -> return ()
283289
labelTMVarIO = \_ _ -> return ()

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module Control.Monad.IOSim (
2121
Trace(..),
2222
TraceEvent(..),
2323
ThreadLabel,
24-
LabelledThread (..),
24+
Labelled (..),
2525
traceEvents,
2626
traceResult,
2727
selectTraceEvents,
@@ -104,12 +104,12 @@ data Failure =
104104
FailureException SomeException
105105

106106
-- | The threads all deadlocked
107-
| FailureDeadlock ![LabelledThread]
107+
| FailureDeadlock ![Labelled ThreadId]
108108

109109
-- | The main thread terminated normally but other threads were still
110110
-- alive, and strict shutdown checking was requested.
111111
-- See 'runSimStrictShutdown'
112-
| FailureSloppyShutdown [LabelledThread]
112+
| FailureSloppyShutdown [Labelled ThreadId]
113113
deriving Show
114114

115115
instance Exception Failure where

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

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ module Control.Monad.IOSim.Internal (
3434
EventlogMarker (..),
3535
ThreadId,
3636
ThreadLabel,
37-
LabelledThread (..),
37+
Labelled (..),
3838
Trace (..),
3939
TraceEvent (..),
4040
liftST,
@@ -139,7 +139,8 @@ data StmA s a where
139139
ReturnStm :: a -> StmA s a
140140
ThrowStm :: SomeException -> StmA s a
141141

142-
NewTVar :: x -> (TVar s x -> StmA s b) -> StmA s b
142+
NewTVar :: Maybe String -> x -> (TVar s x -> StmA s b) -> StmA s b
143+
LabelTVar :: String -> TVar s a -> StmA s b -> StmA s b
143144
ReadTVar :: TVar s a -> (a -> StmA s b) -> StmA s b
144145
WriteTVar :: TVar s a -> a -> StmA s b -> StmA s b
145146
Retry :: StmA s b
@@ -319,7 +320,7 @@ instance MonadSTMTx (STM s) where
319320
type TQueue_ (STM s) = TQueueDefault (IOSim s)
320321
type TBQueue_ (STM s) = TBQueueDefault (IOSim s)
321322

322-
newTVar x = STM $ \k -> NewTVar x k
323+
newTVar x = STM $ \k -> NewTVar Nothing x k
323324
readTVar tvar = STM $ \k -> ReadTVar tvar k
324325
writeTVar tvar x = STM $ \k -> WriteTVar tvar x (k ())
325326
retry = STM $ \_ -> Retry
@@ -351,6 +352,14 @@ instance MonadSTMTx (STM s) where
351352
isEmptyTBQueue = isEmptyTBQueueDefault
352353
isFullTBQueue = isFullTBQueueDefault
353354

355+
instance MonadLabelledSTMTx (STM s) where
356+
labelTVar tvar label = STM $ \k -> LabelTVar label tvar (k ())
357+
labelTMVar = labelTMVarDefault
358+
labelTQueue = labelTQueueDefault
359+
labelTBQueue = labelTBQueueDefault
360+
361+
instance MonadLabelledSTM (IOSim s) where
362+
354363
instance MonadSTM (IOSim s) where
355364
type STM (IOSim s) = STM s
356365

@@ -485,7 +494,7 @@ data Thread s a = Thread {
485494
threadBlocked :: !Bool,
486495
threadMasking :: !MaskingState,
487496
-- other threads blocked in a ThrowTo to us because we are or were masked
488-
threadThrowTo :: ![(SomeException, ThreadId)],
497+
threadThrowTo :: ![(SomeException, Labelled ThreadId)],
489498
threadClockId :: !ClockId,
490499
threadLabel :: Maybe ThreadLabel
491500
}
@@ -516,22 +525,29 @@ newtype TVarId = TVarId Int deriving (Eq, Ord, Enum, Show)
516525
newtype TimeoutId = TimeoutId Int deriving (Eq, Ord, Enum, Show)
517526
newtype ClockId = ClockId Int deriving (Eq, Ord, Enum, Show)
518527

528+
unTimeoutId :: TimeoutId -> Int
529+
unTimeoutId (TimeoutId a) = a
530+
519531
type ThreadLabel = String
532+
type TVarLabel = String
520533

521-
data LabelledThread = LabelledThread {
522-
labelledThreadId :: ThreadId,
523-
labelledThreadLabel :: Maybe ThreadLabel
534+
data Labelled a = Labelled {
535+
l_labelled :: !a,
536+
l_label :: !(Maybe String)
524537
}
525538
deriving (Eq, Ord, Generic)
526-
deriving Show via Quiet LabelledThread
539+
deriving Show via Quiet (Labelled a)
527540

528-
labelledThreads :: Map ThreadId (Thread s a) -> [LabelledThread]
541+
labelledTVarId :: TVar s a -> ST s (Labelled TVarId)
542+
labelledTVarId TVar { tvarId, tvarLabel } = (Labelled tvarId) <$> readSTRef tvarLabel
543+
544+
labelledThreads :: Map ThreadId (Thread s a) -> [Labelled ThreadId]
529545
labelledThreads threadMap =
530546
-- @Map.foldr'@ (and alikes) are not strict enough, to not ratain the
531547
-- original thread map we need to evaluate the spine of the list.
532548
-- TODO: https://github.com/haskell/containers/issues/749
533549
Map.foldr'
534-
(\Thread { threadId, threadLabel } !acc -> LabelledThread threadId threadLabel : acc)
550+
(\Thread { threadId, threadLabel } !acc -> Labelled threadId threadLabel : acc)
535551
[] threadMap
536552

537553

@@ -547,9 +563,9 @@ labelledThreads threadMap =
547563
-- 'selectTraceEventsDynamic' and 'printTraceEventsSay'.
548564
--
549565
data Trace a = Trace !Time !ThreadId !(Maybe ThreadLabel) !TraceEvent (Trace a)
550-
| TraceMainReturn !Time a ![LabelledThread]
551-
| TraceMainException !Time SomeException ![LabelledThread]
552-
| TraceDeadlock !Time ![LabelledThread]
566+
| TraceMainReturn !Time a ![Labelled ThreadId]
567+
| TraceMainException !Time SomeException ![Labelled ThreadId]
568+
| TraceDeadlock !Time ![Labelled ThreadId]
553569
deriving Show
554570

555571
data TraceEvent
@@ -560,17 +576,17 @@ data TraceEvent
560576
| EventThrowTo SomeException ThreadId -- This thread used ThrowTo
561577
| EventThrowToBlocked -- The ThrowTo blocked
562578
| EventThrowToWakeup -- The ThrowTo resumed
563-
| EventThrowToUnmasked ThreadId -- A pending ThrowTo was activated
579+
| EventThrowToUnmasked (Labelled ThreadId) -- A pending ThrowTo was activated
564580

565581
| EventThreadForked ThreadId
566582
| EventThreadFinished -- terminated normally
567583
| EventThreadUnhandled SomeException -- terminated due to unhandled exception
568584

569-
| EventTxCommitted [TVarId] -- tx wrote to these
570-
[TVarId] -- and created these
585+
| EventTxCommitted [Labelled TVarId] -- tx wrote to these
586+
[TVarId] -- and created these
571587
| EventTxAborted
572-
| EventTxBlocked [TVarId] -- tx blocked reading these
573-
| EventTxWakeup [TVarId] -- changed vars causing retry
588+
| EventTxBlocked [Labelled TVarId] -- tx blocked reading these
589+
| EventTxWakeup [Labelled TVarId] -- changed vars causing retry
574590

575591
| EventTimerCreated TimeoutId TVarId Time
576592
| EventTimerUpdated TimeoutId Time
@@ -781,8 +797,12 @@ schedule thread@Thread{
781797
trace)
782798

783799
NewTimeout d k -> do
784-
tvar <- execNewTVar nextVid TimeoutPending
785-
tvar' <- execNewTVar (succ nextVid) False
800+
tvar <- execNewTVar nextVid
801+
(Just $ "<<timeout-state " ++ show (unTimeoutId nextTmid) ++ ">>")
802+
TimeoutPending
803+
tvar' <- execNewTVar (succ nextVid)
804+
(Just $ "<<timeout " ++ show (unTimeoutId nextTmid) ++ ">>")
805+
False
786806
let expiry = d `addTime` time
787807
t = Timeout tvar tvar' nextTmid
788808
timers' = PSQ.insert nextTmid expiry (TimerVars tvar tvar') timers
@@ -855,7 +875,7 @@ schedule thread@Thread{
855875
let thread' = thread { threadControl = ThreadControl (k x) ctl }
856876
(unblocked,
857877
simstate') = unblockThreads wakeup simstate
858-
vids = [ tvarId tvar | SomeTVar tvar <- written ]
878+
vids <- traverse (\(SomeTVar tvar) -> labelledTVarId tvar) written
859879
-- We don't interrupt runnable threads to provide fairness
860880
-- anywhere else. We do it here by putting the tx that committed
861881
-- a transaction to the back of the runqueue, behind all other
@@ -881,7 +901,7 @@ schedule thread@Thread{
881901

882902
StmTxBlocked read -> do
883903
mapM_ (\(SomeTVar tvar) -> blockThreadOnTVar tid tvar) read
884-
let vids = [ tvarId tvar | SomeTVar tvar <- read ]
904+
vids <- traverse (\(SomeTVar tvar) -> labelledTVarId tvar) read
885905
trace <- deschedule Blocked thread simstate
886906
return (Trace time tid tlbl (EventTxBlocked vids) trace)
887907

@@ -930,7 +950,7 @@ schedule thread@Thread{
930950
then do
931951
-- The target thread has async exceptions masked so we add the
932952
-- exception and the source thread id to the pending async exceptions.
933-
let adjustTarget t = t { threadThrowTo = (e, tid) : threadThrowTo t }
953+
let adjustTarget t = t { threadThrowTo = (e, Labelled tid tlbl) : threadThrowTo t }
934954
threads' = Map.adjust adjustTarget tid' threads
935955
trace <- deschedule Blocked thread' simstate { threads = threads' }
936956
return $ Trace time tid tlbl (EventThrowTo e tid')
@@ -1001,7 +1021,7 @@ deschedule Interruptable thread@Thread {
10011021
, threadMasking = MaskedInterruptible
10021022
, threadThrowTo = etids }
10031023
(unblocked,
1004-
simstate') = unblockThreads [tid'] simstate
1024+
simstate') = unblockThreads [l_labelled tid'] simstate
10051025
trace <- schedule thread' simstate'
10061026
return $ Trace time tid tlbl (EventThrowToUnmasked tid')
10071027
$ traceMany [ (time, tid'', tlbl'', EventThrowToWakeup)
@@ -1031,7 +1051,7 @@ deschedule Blocked thread simstate@SimState{threads} =
10311051
deschedule Terminated thread simstate@SimState{ curTime = time, threads } = do
10321052
-- This thread is done. If there are other threads blocked in a
10331053
-- ThrowTo targeted at this thread then we can wake them up now.
1034-
let wakeup = map snd (reverse (threadThrowTo thread))
1054+
let wakeup = map (l_labelled . snd) (reverse (threadThrowTo thread))
10351055
(unblocked,
10361056
simstate') = unblockThreads wakeup simstate
10371057
trace <- reschedule simstate'
@@ -1200,6 +1220,9 @@ data TVar s a = TVar {
12001220
--
12011221
tvarId :: !TVarId,
12021222

1223+
-- | Label.
1224+
tvarLabel :: !(STRef s (Maybe TVarLabel)),
1225+
12031226
-- | The var's current value
12041227
--
12051228
tvarCurrent :: !(STRef s a),
@@ -1345,10 +1368,14 @@ execAtomically =
13451368
let ctl' = OrElseLeftFrame b k written writtenSeq ctl
13461369
go ctl' read Map.empty [] nextVid a
13471370

1348-
NewTVar x k -> do
1349-
v <- execNewTVar nextVid x
1371+
NewTVar !mbLabel x k -> do
1372+
v <- execNewTVar nextVid mbLabel x
13501373
go ctl read written writtenSeq (succ nextVid) (k v)
13511374

1375+
LabelTVar !label tvar k -> do
1376+
writeSTRef (tvarLabel tvar) $! (Just label)
1377+
go ctl read written writtenSeq nextVid k
1378+
13521379
ReadTVar v k
13531380
| tvarId v `Map.member` read -> do
13541381
x <- execReadTVar v
@@ -1400,12 +1427,14 @@ execAtomically' = go Map.empty
14001427
_ -> error "execAtomically': only for special case of reads and writes"
14011428

14021429

1403-
execNewTVar :: TVarId -> a -> ST s (TVar s a)
1404-
execNewTVar nextVid x = do
1430+
execNewTVar :: TVarId -> Maybe String -> a -> ST s (TVar s a)
1431+
execNewTVar nextVid !mbLabel x = do
1432+
tvarLabel <- newSTRef mbLabel
14051433
tvarCurrent <- newSTRef x
14061434
tvarUndo <- newSTRef []
14071435
tvarBlocked <- newSTRef ([], Set.empty)
1408-
return TVar {tvarId = nextVid, tvarCurrent, tvarUndo, tvarBlocked}
1436+
return TVar {tvarId = nextVid, tvarLabel,
1437+
tvarCurrent, tvarUndo, tvarBlocked}
14091438

14101439
execReadTVar :: TVar s a -> ST s a
14111440
execReadTVar TVar{tvarCurrent} = readSTRef tvarCurrent
@@ -1463,10 +1492,10 @@ unblockAllThreadsFromTVar TVar{tvarBlocked} = do
14631492
-- the var writes that woke them.
14641493
--
14651494
threadsUnblockedByWrites :: [SomeTVar s]
1466-
-> ST s ([ThreadId], Map ThreadId (Set TVarId))
1495+
-> ST s ([ThreadId], Map ThreadId (Set (Labelled TVarId)))
14671496
threadsUnblockedByWrites written = do
14681497
tidss <- sequence
1469-
[ (,) (tvarId tvar) <$> readTVarBlockedThreads tvar
1498+
[ (,) <$> labelledTVarId tvar <*> readTVarBlockedThreads tvar
14701499
| SomeTVar tvar <- written ]
14711500
-- Threads to wake up, in wake up order, annotated with the vars written that
14721501
-- caused the unblocking.

0 commit comments

Comments
 (0)