Skip to content

Commit 6d84047

Browse files
committed
Implement MonadLabelledMVar
1 parent bbc1e07 commit 6d84047

File tree

5 files changed

+29
-4
lines changed

5 files changed

+29
-4
lines changed

io-classes/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Breaking changes
66

77
* Added `threadLabel` to `MonadThread`
8+
* Added `MonadLabelledMVar` class.
89

910
### 1.7.0.0
1011

io-classes/src/Control/Concurrent/Class/MonadMVar.hs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
module Control.Concurrent.Class.MonadMVar
77
( MonadMVar (..)
8+
-- * non-standard extensions
89
, MonadInspectMVar (..)
10+
, MonadLabelledMVar (..)
911
) where
1012

1113
import Control.Concurrent.MVar qualified as IO
@@ -153,7 +155,6 @@ instance MonadMVar IO where
153155
modifyMVarMasked_ = IO.modifyMVarMasked_
154156
modifyMVarMasked = IO.modifyMVarMasked
155157

156-
157158
--
158159
-- ReaderT instance
159160
--
@@ -204,6 +205,18 @@ instance MonadInspectMVar IO where
204205
type InspectMVarMonad IO = IO
205206
inspectMVar _ = tryReadMVar
206207

208+
-- | Labelled `MVar`s
209+
--
210+
-- The `IO` instances is no-op, the `IOSim` instance enhances simulation trace.
211+
-- This is very useful when analysing low lever concurrency issues (e.g.
212+
-- deadlocks, livelocks etc).
213+
class MonadMVar m
214+
=> MonadLabelledMVar m where
215+
-- | Name an `MVar`
216+
labelMVar :: MVar m a -> String -> m ()
217+
218+
instance MonadLabelledMVar IO where
219+
labelMVar = \_ _ -> pure ()
207220
--
208221
-- Utilities
209222
--

io-sim/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
`TVars`.
88
- `Show` instance for `ScheduleMod` now prints `ThreadId`s in a slightly nicer
99
way, matching the way those steps would be traced in the `SimTrace`.
10+
- Implement `MonadLabelledMVar` instance for `(IOSim s)`
1011

1112
## 1.6.0.0
1213

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,13 +261,17 @@ data MVarState m a = MVarEmpty !(Deque (TVar m (Maybe a))) -- blocked on take
261261
newEmptyMVarDefault :: MonadSTM m => m (MVarDefault m a)
262262
newEmptyMVarDefault = MVar <$> newTVarIO (MVarEmpty mempty mempty)
263263

264+
labelMVarDefault
265+
:: MonadLabelledSTM m
266+
=> MVarDefault m a -> String -> m ()
267+
labelMVarDefault (MVar tvar) = atomically . labelTVar tvar . (<> "-MVar")
264268

265269
newMVarDefault :: MonadSTM m => a -> m (MVarDefault m a)
266270
newMVarDefault a = MVar <$> newTVarIO (MVarFull a mempty)
267271

268272

269273
putMVarDefault :: ( MonadMask m
270-
, MonadSTM m
274+
, MonadLabelledSTM m
271275
, forall x tvar. tvar ~ TVar m x => Eq tvar
272276
)
273277
=> MVarDefault m a -> a -> m ()
@@ -278,6 +282,7 @@ putMVarDefault (MVar tv) x = mask_ $ do
278282
-- It's full, add ourselves to the end of the 'put' blocked queue.
279283
MVarFull x' putq -> do
280284
putvar <- newTVar False
285+
labelTVar putvar "internal-putvar"
281286
writeTVar tv (MVarFull x' (Deque.snoc (x, putvar) putq))
282287
return (Just putvar)
283288

@@ -350,7 +355,7 @@ tryPutMVarDefault (MVar tv) x =
350355

351356

352357
takeMVarDefault :: ( MonadMask m
353-
, MonadSTM m
358+
, MonadLabelledSTM m
354359
, forall x tvar. tvar ~ TVar m x => Eq tvar
355360
)
356361
=> MVarDefault m a
@@ -362,6 +367,7 @@ takeMVarDefault (MVar tv) = mask_ $ do
362367
-- It's empty, add ourselves to the end of the 'take' blocked queue.
363368
MVarEmpty takeq readq -> do
364369
takevar <- newTVar Nothing
370+
labelTVar takevar "internal-takevar"
365371
writeTVar tv (MVarEmpty (Deque.snoc takevar takeq) readq)
366372
return (Left takevar)
367373

@@ -433,7 +439,7 @@ tryTakeMVarDefault (MVar tv) = do
433439
-- 'putMVar' value. It will also not block if the 'MVar' is full, even if there
434440
-- are other threads attempting to 'putMVar'.
435441
--
436-
readMVarDefault :: ( MonadSTM m
442+
readMVarDefault :: ( MonadLabelledSTM m
437443
, MonadMask m
438444
, forall x tvar. tvar ~ TVar m x => Eq tvar
439445
)
@@ -446,6 +452,7 @@ readMVarDefault (MVar tv) = do
446452
-- It's empty, add ourselves to the 'read' blocked queue.
447453
MVarEmpty takeq readq -> do
448454
readvar <- newTVar Nothing
455+
labelTVar readvar "internal-readvar"
449456
writeTVar tv (MVarEmpty takeq (Deque.snoc readvar readq))
450457
return (Left readvar)
451458

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,9 @@ instance MonadInspectMVar (IOSim s) where
606606
MVarEmpty _ _ -> pure Nothing
607607
MVarFull x _ -> pure (Just x)
608608

609+
instance MonadLabelledMVar (IOSim s) where
610+
labelMVar = labelMVarDefault
611+
609612
data Async s a = Async !IOSimThreadId (STM s (Either SomeException a))
610613

611614
instance Eq (Async s a) where

0 commit comments

Comments
 (0)