Skip to content

Commit 238d845

Browse files
author
Yogesh Sajanikar
committed
Add catch semantics to STM
Add catch handler as branch to support catch
1 parent 2126b8b commit 238d845

File tree

4 files changed

+75
-7
lines changed

4 files changed

+75
-7
lines changed

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

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -896,10 +896,33 @@ execAtomically !time !tid !tlbl !nextVid0 action0 k0 =
896896
go ctl' read written' writtenSeq' createdOuterSeq nextVid (k x)
897897

898898
ThrowStm e ->
899+
{-# SCC "execAtomically.go.ThrowStm" #-}
900+
case ctl of
901+
AtomicallyFrame -> do
902+
-- Revert all the TVar writes
903+
!_ <- traverse_ (\(SomeTVar tvar) -> revertTVar tvar) written
904+
k0 $ StmTxAborted [] (toException e)
905+
906+
BranchFrame (CatchStmA h) k writtenOuter writtenOuterSeq createdOuterSeq ctl' ->
907+
{-# SCC "execAtomically.go.branchFrame" #-} do
908+
-- Revert all the TVar writes within this orElse
909+
!_ <- traverse_ (\(SomeTVar tvar) -> revertTVar tvar) written
910+
-- Execute the catch handler with an empty written set
911+
let ctl'' = BranchFrame EmptyStmA k writtenOuter writtenOuterSeq createdOuterSeq ctl'
912+
go ctl'' read Map.empty [] [] nextVid (h e)
913+
--
914+
BranchFrame _ _k writtenOuter writtenOuterSeq createdOuterSeq ctl' ->
915+
{-# SCC "execAtomically.go.branchFrame" #-} do
916+
-- Revert all the TVar writes within this orElse
917+
!_ <- traverse_ (\(SomeTVar tvar) -> revertTVar tvar) written
918+
go ctl' read writtenOuter writtenOuterSeq createdOuterSeq nextVid (ThrowStm e)
919+
920+
CatchStm a h k ->
899921
{-# SCC "execAtomically.go.ThrowStm" #-} do
900-
-- Revert all the TVar writes
901-
!_ <- traverse_ (\(SomeTVar tvar) -> revertTVar tvar) written
902-
k0 $ StmTxAborted [] (toException e)
922+
-- Execute the left side in a new frame with an empty written set
923+
let ctl' = BranchFrame (CatchStmA h) k written writtenSeq createdSeq ctl
924+
go ctl' read Map.empty [] [] nextVid a
925+
903926

904927
Retry ->
905928
{-# SCC "execAtomically.go.Retry" #-}

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ runSTM (STM k) = k ReturnStm
176176
data StmA s a where
177177
ReturnStm :: a -> StmA s a
178178
ThrowStm :: SomeException -> StmA s a
179+
CatchStm :: StmA s a -> (SomeException -> StmA s a) -> (a -> StmA s b) -> StmA s b
179180

180181
NewTVar :: Maybe String -> x -> (TVar s x -> StmA s b) -> StmA s b
181182
LabelTVar :: String -> TVar s a -> StmA s b -> StmA s b
@@ -314,6 +315,25 @@ instance MonadThrow (STM s) where
314315
instance Exceptions.MonadThrow (STM s) where
315316
throwM = MonadThrow.throwIO
316317

318+
instance MonadCatch (STM s) where
319+
320+
catch action handler = STM $ oneShot $ \k -> CatchStm (runSTM action) (runSTM . handler') k
321+
where
322+
handler' e = case fromException e of
323+
Nothing -> throwIO e -- Rethrow the exception if handler does not handle it.
324+
Just e' -> handler e'
325+
326+
generalBracket acquire release use = do
327+
resource <- acquire
328+
b <- use resource `catch` \e -> do
329+
_ <- release resource (ExitCaseException e)
330+
throwIO e
331+
c <- release resource (ExitCaseSuccess b)
332+
return (b, c)
333+
334+
instance Exceptions.MonadCatch (STM s) where
335+
catch = MonadThrow.catch
336+
317337
instance MonadCatch (IOSim s) where
318338
catch action handler =
319339
IOSim $ oneShot $ \k -> Catch (runIOSim action) (runIOSim . handler) k
@@ -836,7 +856,9 @@ data StmTxResult s a =
836856

837857
-- | OrElse/Catch give rise to an alternate branch. A branch of a branch is an
838858
-- empty one.
839-
data BranchStmA s a = OrElseStmA (StmA s a) | EmptyStmA
859+
data BranchStmA s a = OrElseStmA (StmA s a)
860+
| CatchStmA (SomeException -> StmA s a)
861+
| EmptyStmA
840862

841863
data StmStack s b a where
842864
-- | Executing in the context of a top level 'atomically'.

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,10 +1107,32 @@ execAtomically time tid tlbl nextVid0 action0 k0 =
11071107
go ctl' read written' writtenSeq' createdOuterSeq nextVid (k x)
11081108

11091109
ThrowStm e ->
1110+
{-# SCC "execAtomically.go.ThrowStm" #-}
1111+
case ctl of
1112+
AtomicallyFrame -> do
1113+
-- Revert all the TVar writes
1114+
!_ <- traverse_ (\(SomeTVar tvar) -> revertTVar tvar) written
1115+
k0 $ StmTxAborted [] (toException e)
1116+
1117+
BranchFrame (CatchStmA h) k writtenOuter writtenOuterSeq createdOuterSeq ctl' ->
1118+
{-# SCC "execAtomically.go.branchFrame" #-} do
1119+
-- Revert all the TVar writes within this orElse
1120+
!_ <- traverse_ (\(SomeTVar tvar) -> revertTVar tvar) written
1121+
-- Execute the catch handler with an empty written set
1122+
let ctl'' = BranchFrame EmptyStmA k writtenOuter writtenOuterSeq createdOuterSeq ctl'
1123+
go ctl'' read Map.empty [] [] nextVid (h e)
1124+
--
1125+
BranchFrame _ _k writtenOuter writtenOuterSeq createdOuterSeq ctl' ->
1126+
{-# SCC "execAtomically.go.branchFrame" #-} do
1127+
-- Revert all the TVar writes within this orElse
1128+
!_ <- traverse_ (\(SomeTVar tvar) -> revertTVar tvar) written
1129+
go ctl' read writtenOuter writtenOuterSeq createdOuterSeq nextVid (ThrowStm e)
1130+
1131+
CatchStm a h k ->
11101132
{-# SCC "execAtomically.go.ThrowStm" #-} do
1111-
-- Revert all the TVar writes
1112-
!_ <- traverse_ (\(SomeTVar tvar) -> revertTVar tvar) written
1113-
k0 $ StmTxAborted (Map.elems read) (toException e)
1133+
-- Execute the left side in a new frame with an empty written set
1134+
let ctl' = BranchFrame (CatchStmA h) k written writtenSeq createdSeq ctl
1135+
go ctl' read Map.empty [] [] nextVid a
11141136

11151137
Retry ->
11161138
{-# SCC "execAtomically.go.Retry" #-}

io-sim/test/Test/STM.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ data Term (t :: Type) where
6767

6868
Return :: Expr t -> Term t
6969
Throw :: Expr a -> Term t
70+
Catch :: Term t -> Expr a -> Term t -> Term t
7071
Retry :: Term t
7172

7273
ReadTVar :: Name (TyVar t) -> Term t

0 commit comments

Comments
 (0)