Skip to content

Commit 45029aa

Browse files
iohk-bors[bot]coot
andauthored
Merge #2791
2791: Labelled TVars & friends r=coot a=coot This series of patches allows to label TVars, TMVars, TQueues, TBQueues. It also provides an api to consistently name thread & 'TVar' hidden in 'Async'. - io-sim: include threads in 'FailureDeadlock' - io-sim: derive LabelThread instance using Quiet - io-sim-classes: MonadLabeledSTM and MonadLabeledAsync - io-sim: MonadLabeledSTM and MonadLabeledAsync IOSim instances - io-sim: more labeled threads & tvars ids Co-authored-by: Marcin Szamotulski <[email protected]>
2 parents c022dda + 389ebe4 commit 45029aa

File tree

6 files changed

+184
-53
lines changed

6 files changed

+184
-53
lines changed

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

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
{-# LANGUAGE DefaultSignatures #-}
12
{-# LANGUAGE FlexibleContexts #-}
23
{-# LANGUAGE MultiParamTypeClasses #-}
34
{-# LANGUAGE TypeFamilies #-}
45
{-# LANGUAGE TypeFamilyDependencies #-}
56
module Control.Monad.Class.MonadSTM
67
( MonadSTM (..)
78
, MonadSTMTx (..)
9+
, MonadLabelledSTM (..)
10+
, MonadLabelledSTMTx (..)
811
, LazyTVar
912
, LazyTMVar
1013
, TVar
@@ -14,6 +17,7 @@ module Control.Monad.Class.MonadSTM
1417

1518
-- * Default 'TMVar' implementation
1619
, TMVarDefault (..)
20+
, labelTMVarDefault
1721
, newTMVarDefault
1822
, newTMVarIODefault
1923
, newEmptyTMVarDefault
@@ -29,6 +33,7 @@ module Control.Monad.Class.MonadSTM
2933

3034
-- * Default 'TBQueue' implementation
3135
, TQueueDefault (..)
36+
, labelTQueueDefault
3237
, newTQueueDefault
3338
, readTQueueDefault
3439
, tryReadTQueueDefault
@@ -37,6 +42,7 @@ module Control.Monad.Class.MonadSTM
3742

3843
-- * Default 'TBQueue' implementation
3944
, TBQueueDefault (..)
45+
, labelTBQueueDefault
4046
, newTBQueueDefault
4147
, readTBQueueDefault
4248
, tryReadTBQueueDefault
@@ -184,6 +190,37 @@ newEmptyTMVarM :: MonadSTM m => m (TMVar m a)
184190
newEmptyTMVarM = newEmptyTMVarIO
185191
{-# DEPRECATED newEmptyTMVarM "Use newEmptyTMVarIO" #-}
186192

193+
194+
-- | Labelled 'TVar's, 'TMVar's, 'TQueue's and 'TBQueue's.
195+
--
196+
class MonadSTMTx stm => MonadLabelledSTMTx stm where
197+
labelTVar :: TVar_ stm a -> String -> stm ()
198+
labelTMVar :: TMVar_ stm a -> String -> stm ()
199+
labelTQueue :: TQueue_ stm a -> String -> stm ()
200+
labelTBQueue :: TBQueue_ stm a -> String -> stm ()
201+
202+
-- | A convenience class which provides 'MonadSTM' and 'MonadLabelledSTMTx'
203+
-- constraints.
204+
--
205+
class (MonadSTM m, MonadLabelledSTMTx (STM m))
206+
=> MonadLabelledSTM m where
207+
labelTVarIO :: TVar m a -> String -> m ()
208+
labelTMVarIO :: TMVar m a -> String -> m ()
209+
labelTQueueIO :: TQueue m a -> String -> m ()
210+
labelTBQueueIO :: TBQueue m a -> String -> m ()
211+
212+
default labelTVarIO :: TVar m a -> String -> m ()
213+
labelTVarIO = \v l -> atomically (labelTVar v l)
214+
215+
default labelTMVarIO :: TMVar m a -> String -> m ()
216+
labelTMVarIO = \v l -> atomically (labelTMVar v l)
217+
218+
default labelTQueueIO :: TQueue m a -> String -> m ()
219+
labelTQueueIO = \v l -> atomically (labelTQueue v l)
220+
221+
default labelTBQueueIO :: TBQueue m a -> String -> m ()
222+
labelTBQueueIO = \v l -> atomically (labelTBQueue v l)
223+
187224
--
188225
-- Instance for IO uses the existing STM library implementations
189226
--
@@ -237,12 +274,28 @@ instance MonadSTM IO where
237274
newTMVarIO = STM.newTMVarIO
238275
newEmptyTMVarIO = STM.newEmptyTMVarIO
239276

277+
-- | noop instance
278+
--
279+
instance MonadLabelledSTMTx STM.STM where
280+
labelTVar = \_ _ -> return ()
281+
labelTMVar = \_ _ -> return ()
282+
labelTQueue = \_ _ -> return ()
283+
labelTBQueue = \_ _ -> return ()
284+
285+
-- | noop instance
286+
--
287+
instance MonadLabelledSTM IO where
288+
labelTVarIO = \_ _ -> return ()
289+
labelTMVarIO = \_ _ -> return ()
290+
labelTQueueIO = \_ _ -> return ()
291+
labelTBQueueIO = \_ _ -> return ()
292+
240293
-- | Wrapper around 'BlockedIndefinitelyOnSTM' that stores a call stack
241294
data BlockedIndefinitely = BlockedIndefinitely {
242295
blockedIndefinitelyCallStack :: CallStack
243296
, blockedIndefinitelyException :: BlockedIndefinitelyOnSTM
244297
}
245-
deriving (Show)
298+
deriving Show
246299

247300
instance Exception BlockedIndefinitely where
248301
displayException (BlockedIndefinitely cs e) = unlines [
@@ -270,6 +323,11 @@ instance MonadSTM m => MonadSTM (ReaderT r m) where
270323

271324
newtype TMVarDefault m a = TMVar (TVar m (Maybe a))
272325

326+
labelTMVarDefault
327+
:: MonadLabelledSTM m
328+
=> TMVarDefault m a -> String -> STM m ()
329+
labelTMVarDefault (TMVar tvar) = labelTVar tvar
330+
273331
newTMVarDefault :: MonadSTM m => a -> STM m (TMVarDefault m a)
274332
newTMVarDefault a = do
275333
t <- newTVar (Just a)
@@ -291,7 +349,7 @@ newEmptyTMVarDefault = do
291349

292350
newEmptyTMVarIODefault :: MonadSTM m => m (TMVarDefault m a)
293351
newEmptyTMVarIODefault = do
294-
t <- newTVarM Nothing
352+
t <- newTVarIO Nothing
295353
return (TMVar t)
296354

297355
newEmptyTMVarMDefault :: MonadSTM m => m (TMVarDefault m a)
@@ -357,6 +415,13 @@ isEmptyTMVarDefault (TMVar t) = do
357415
data TQueueDefault m a = TQueue !(TVar m [a])
358416
!(TVar m [a])
359417

418+
labelTQueueDefault
419+
:: MonadLabelledSTM m
420+
=> TQueueDefault m a -> String -> STM m ()
421+
labelTQueueDefault (TQueue read write) label = do
422+
labelTVar read (label ++ "-read")
423+
labelTVar write (label ++ "-write")
424+
360425
newTQueueDefault :: MonadSTM m => STM m (TQueueDefault m a)
361426
newTQueueDefault = do
362427
read <- newTVar []
@@ -408,6 +473,15 @@ data TBQueueDefault m a = TBQueue
408473
!(TVar m [a]) -- written elements
409474
!Natural
410475

476+
labelTBQueueDefault
477+
:: MonadLabelledSTM m
478+
=> TBQueueDefault m a -> String -> STM m ()
479+
labelTBQueueDefault (TBQueue rsize read wsize write _size) label = do
480+
labelTVar rsize (label ++ "-rsize")
481+
labelTVar read (label ++ "-read")
482+
labelTVar wsize (label ++ "-wsize")
483+
labelTVar write (label ++ "-write")
484+
411485
newTBQueueDefault :: MonadSTM m => Natural -> STM m (TBQueueDefault m a)
412486
newTBQueueDefault size = do
413487
rsize <- newTVar 0

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{-# LANGUAGE BangPatterns #-}
22
{-# LANGUAGE CPP #-}
33
{-# LANGUAGE DuplicateRecordFields #-}
4+
{-# LANGUAGE FlexibleContexts #-}
45
{-# LANGUAGE NamedFieldPuns #-}
56
{-# LANGUAGE TypeFamilies #-}
67

@@ -13,6 +14,8 @@ module Control.Monad.Class.MonadSTM.Strict
1314
, LazyTMVar
1415
-- * 'StrictTVar'
1516
, StrictTVar
17+
, labelTVar
18+
, labelTVarIO
1619
, castStrictTVar
1720
, toLazyTVar
1821
, newTVar
@@ -24,11 +27,13 @@ module Control.Monad.Class.MonadSTM.Strict
2427
, stateTVar
2528
-- * 'StrictTMVar'
2629
, StrictTMVar
30+
, labelTMVar
31+
, labelTMVarIO
2732
, castStrictTMVar
2833
, newTMVar
2934
, newTMVarIO
30-
, newEmptyTMVarIO
3135
, newEmptyTMVar
36+
, newEmptyTMVarIO
3237
, takeTMVar
3338
, tryTakeTMVar
3439
, putTMVar
@@ -48,7 +53,8 @@ module Control.Monad.Class.MonadSTM.Strict
4853
) where
4954

5055
import Control.Monad.Class.MonadSTM as X hiding (LazyTMVar, LazyTVar,
51-
TMVar, TVar, isEmptyTMVar, modifyTVar, newEmptyTMVar,
56+
TMVar, TVar, isEmptyTMVar, labelTVar, labelTVarIO,
57+
labelTMVar, labelTMVarIO, modifyTVar, newEmptyTMVar,
5258
newEmptyTMVarIO, newEmptyTMVarM, newTMVar, newTMVarIO,
5359
newTMVarM, newTVar, newTVarIO, newTVarM, putTMVar,
5460
readTMVar, readTVar, stateTVar, swapTMVar, takeTMVar,
@@ -73,6 +79,12 @@ data StrictTVar m a = StrictTVar
7379
, tvar :: !(LazyTVar m a)
7480
}
7581

82+
labelTVar :: MonadLabelledSTM m => StrictTVar m a -> String -> STM m ()
83+
labelTVar StrictTVar { tvar } = Lazy.labelTVar tvar
84+
85+
labelTVarIO :: MonadLabelledSTM m => StrictTVar m a -> String -> m ()
86+
labelTVarIO v = atomically . labelTVar v
87+
7688
castStrictTVar :: LazyTVar m ~ LazyTVar n
7789
=> StrictTVar m a -> StrictTVar n a
7890
castStrictTVar StrictTVar{invariant, tvar} = StrictTVar{invariant, tvar}
@@ -86,7 +98,6 @@ toLazyTVar StrictTVar { tvar } = tvar
8698

8799
newTVar :: MonadSTM m => a -> STM m (StrictTVar m a)
88100
newTVar !a = StrictTVar (const Nothing) <$> Lazy.newTVar a
89-
90101
newTVarIO :: MonadSTM m => a -> m (StrictTVar m a)
91102
newTVarIO = newTVarWithInvariantIO (const Nothing)
92103

@@ -142,6 +153,12 @@ updateTVar = stateTVar
142153
-- to very hard to debug bugs where code is blocked indefinitely.
143154
newtype StrictTMVar m a = StrictTMVar (LazyTMVar m a)
144155

156+
labelTMVar :: MonadLabelledSTM m => StrictTMVar m a -> String -> STM m ()
157+
labelTMVar (StrictTMVar tvar) = Lazy.labelTMVar tvar
158+
159+
labelTMVarIO :: MonadLabelledSTM m => StrictTMVar m a -> String -> m ()
160+
labelTMVarIO v = atomically . labelTMVar v
161+
145162
castStrictTMVar :: LazyTMVar m ~ LazyTMVar n
146163
=> StrictTMVar m a -> StrictTMVar n a
147164
castStrictTMVar (StrictTMVar var) = StrictTMVar var

io-sim/io-sim.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ library
4444
exceptions >=0.10,
4545
containers,
4646
psqueues >=0.2 && <0.3,
47-
time >=1.6 && <1.11
47+
time >=1.6 && <1.11,
48+
quiet
4849

4950
ghc-options: -Wall
5051
-Wcompat

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

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module Control.Monad.IOSim (
2121
Trace(..),
2222
TraceEvent(..),
2323
ThreadLabel,
24-
LabeledThread (..),
24+
Labelled (..),
2525
traceEvents,
2626
traceResult,
2727
selectTraceEvents,
@@ -63,9 +63,9 @@ selectTraceEvents fn = go
6363
go (Trace _ _ _ ev trace) = case fn ev of
6464
Just x -> x : go trace
6565
Nothing -> go trace
66-
go (TraceMainException _ e _) = throw (FailureException e)
67-
go (TraceDeadlock _ _) = throw FailureDeadlock
68-
go (TraceMainReturn _ _ _) = []
66+
go (TraceMainException _ e _) = throw (FailureException e)
67+
go (TraceDeadlock _ threads) = throw (FailureDeadlock threads)
68+
go (TraceMainReturn _ _ _) = []
6969

7070
-- | Select all the traced values matching the expected type. This relies on
7171
-- the sim's dynamic trace facility.
@@ -104,20 +104,24 @@ data Failure =
104104
FailureException SomeException
105105

106106
-- | The threads all deadlocked
107-
| FailureDeadlock
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 [LabeledThread]
112+
| FailureSloppyShutdown [Labelled ThreadId]
113113
deriving Show
114114

115115
instance Exception Failure where
116116
displayException (FailureException err) = displayException err
117-
displayException FailureDeadlock = "<<io-sim deadlock>>"
117+
displayException (FailureDeadlock threads) =
118+
concat [ "<<io-sim deadlock: "
119+
, intercalate ", " (show `map` threads)
120+
, ">>"
121+
]
118122
displayException (FailureSloppyShutdown threads) =
119123
concat [ "<<io-sim sloppy shutdown: "
120-
, intercalate "," (show `map` threads)
124+
, intercalate ", " (show `map` threads)
121125
, ">>"
122126
]
123127

@@ -150,7 +154,7 @@ traceResult strict = go
150154
| strict = Left (FailureSloppyShutdown tids)
151155
go (TraceMainReturn _ x _) = Right x
152156
go (TraceMainException _ e _) = Left (FailureException e)
153-
go (TraceDeadlock _ _) = Left FailureDeadlock
157+
go (TraceDeadlock _ threads) = Left (FailureDeadlock threads)
154158

155159
traceEvents :: Trace a -> [(Time, ThreadId, Maybe ThreadLabel, TraceEvent)]
156160
traceEvents (Trace time tid tlbl event t) = (time, tid, tlbl, event)

0 commit comments

Comments
 (0)