Skip to content

Commit 49855e7

Browse files
committed
Make takeMVar exception safe
1 parent b14daa3 commit 49855e7

File tree

1 file changed

+17
-1
lines changed
  • io-sim/src/Control/Monad/IOSim

1 file changed

+17
-1
lines changed

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,23 @@ takeMVarDefault (MVar tv) = mask_ $ do
398398
-- takevar; we need to remove it from 'takeq', otherwise we
399399
-- will have a space leak.
400400
let takeq' = Deque.filter (/= takevar) takeq
401-
writeTVar tv (MVarEmpty takeq' readq)
401+
takevalue <- readTVar takevar
402+
case takevalue of
403+
Nothing ->
404+
writeTVar tv (MVarEmpty takeq' readq)
405+
-- we were given a value before we could read it. Relay it to any
406+
-- new reading threads and possible the next take thread.
407+
Just x -> do
408+
-- notify readers
409+
mapM_ (\readvar -> writeTVar readvar (Just x)) readq
410+
411+
case Deque.uncons takeq' of
412+
Nothing ->
413+
writeTVar tv (MVarFull x mempty)
414+
415+
Just (takevar', takeq'') -> do
416+
writeTVar takevar' (Just x)
417+
writeTVar tv (MVarEmpty takeq'' mempty)
402418

403419
-- This case is unlikely but possible if another thread ran
404420
-- first and modified the mvar. This situation is fine as far as

0 commit comments

Comments
 (0)