@@ -8,6 +8,7 @@ module Test.Control.Concurrent.Class.MonadMVar where
8
8
import Control.Concurrent.Class.MonadMVar
9
9
import Control.Monad.Class.MonadAsync
10
10
import Control.Monad.Class.MonadFork
11
+ import Control.Monad.Class.MonadTest
11
12
import Control.Monad.Class.MonadTime.SI
12
13
import Control.Monad.Class.MonadTimer.SI
13
14
import Data.Bifoldable (bifoldMap )
@@ -64,6 +65,7 @@ tests =
64
65
[ testCase " empty MVar is empty" unit_isEmptyMVar_empty_sim
65
66
, testCase " full MVar is not empty" unit_isEmptyMVar_full_sim
66
67
]
68
+ , testProperty " takeMVar is exception safe" prop_takeMVar_exception_safe
67
69
]
68
70
69
71
@@ -310,6 +312,29 @@ unit_isEmptyMVar_full_sim =
310
312
assertBool " full mvar must not be empty" $
311
313
runSimOrThrow (prop_isEmptyMVar False )
312
314
315
+ --
316
+ -- takeMVar is exception safe
317
+ --
318
+ prop_takeMVar_exception_safe :: Property
319
+ prop_takeMVar_exception_safe =
320
+ exploreSimTrace id (do
321
+ exploreRaces
322
+ mv <- newMVar (0 :: Int )
323
+ t1 <- async $ void $ withMVar mv (\ v -> pure (v + 1 , () ))
324
+ t2 <- async $ void $ do
325
+ _ <- withMVar mv (\ v -> pure (v + 1 , () ))
326
+ withMVar mv (\ v -> pure (v + 1 , () ))
327
+ t3 <- async $ cancel t1
328
+ wait t3
329
+ wait t2
330
+ wait t1
331
+ ) (\ _ trace ->
332
+ case traceResult False trace of
333
+ Left FailureDeadlock {} ->
334
+ counterexample (ppTrace trace) $ property False
335
+ _ -> property True
336
+ )
337
+
313
338
--
314
339
-- Utils
315
340
--
0 commit comments