Skip to content

Commit b2a0986

Browse files
committed
Add an assertOnce check, useful for debugging
1 parent 206e7c2 commit b2a0986

File tree

1 file changed

+23
-1
lines changed
  • src/Development/Shake/Internal/Core

1 file changed

+23
-1
lines changed

src/Development/Shake/Internal/Core/Monad.hs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{-# LANGUAGE CPP #-}
2-
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
2+
{-# LANGUAGE GADTs, ScopedTypeVariables, TupleSections #-}
33

44
module Development.Shake.Internal.Core.Monad(
55
RAW, Capture, runRAW,
@@ -11,6 +11,8 @@ module Development.Shake.Internal.Core.Monad(
1111
import Control.Exception.Extra
1212
import Control.Monad.IO.Class
1313
import Data.IORef
14+
import Control.Monad
15+
import System.IO
1416
import Data.Semigroup
1517
import Prelude
1618

@@ -65,9 +67,26 @@ instance (Semigroup a, Monoid a) => Monoid (RAW ro rw a) where
6567
type Capture a = (a -> IO ()) -> IO ()
6668

6769

70+
-- Useful for checking that all continuations are run only once
71+
-- Cannot be enabled for performance reasons and because some of
72+
-- "monad test" deliberately breaks the invariant to check it doesn't go wrong
73+
assertOnceCheck = False
74+
75+
assertOnce :: MonadIO m => String -> (a -> m b) -> IO (a -> m b)
76+
assertOnce msg k
77+
| not assertOnceCheck = return k
78+
| otherwise = do
79+
ref <- liftIO $ newIORef False
80+
return $ \v -> do
81+
liftIO $ join $ atomicModifyIORef ref $ \old -> (True,) $ when old $ do
82+
hPutStrLn stderr "FATAL ERROR: assertOnce failed"
83+
Prelude.fail $ "assertOnce failed: " ++ msg
84+
k v
85+
6886
-- | Run and then call a continuation.
6987
runRAW :: ro -> rw -> RAW ro rw a -> Capture (Either SomeException a)
7088
runRAW ro rw m k = do
89+
k <- assertOnce "runRAW" k
7190
rw <- newIORef rw
7291
handler <- newIORef throwIO
7392
writeIORef handler $ \e -> do
@@ -79,6 +98,7 @@ runRAW ro rw m k = do
7998
goRAW handler ro rw m (\v -> do writeIORef handler throwIO; k $ Right v)
8099
`catch_` \e -> ($ e) =<< readIORef handler
81100

101+
82102
goRAW :: forall ro rw a . IORef (SomeException -> IO ()) -> ro -> IORef rw -> RAW ro rw a -> Capture a
83103
goRAW handler ro rw = go
84104
where
@@ -97,6 +117,7 @@ goRAW handler ro rw = go
97117
ModifyRW f -> modifyIORef' rw f >> k ()
98118

99119
CatchRAW m hdl -> do
120+
hdl <- assertOnce "CatchRAW" hdl
100121
old <- readIORef handler
101122
writeIORef handler $ \e -> do
102123
writeIORef handler old
@@ -105,6 +126,7 @@ goRAW handler ro rw = go
105126
go m $ \x -> writeIORef handler old >> k x
106127

107128
CaptureRAW f -> do
129+
f <- assertOnce "CaptureRAW" f
108130
old <- readIORef handler
109131
writeIORef handler throwIO
110132
f $ \x -> case x of

0 commit comments

Comments
 (0)