Skip to content

Commit 8293db5

Browse files
authored
Merge pull request #109 from input-output-hk/jdral/factor-out-checked-strict-tvar
Factour out checked `StrictTVar`s
2 parents c1d12b6 + 52ea816 commit 8293db5

File tree

4 files changed

+19
-103
lines changed

4 files changed

+19
-103
lines changed

strict-stm/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## next version
4+
5+
### Breaking changes
6+
7+
* Remove invariants for `StrictTVar`s.
8+
39
## 1.1.0.1
410

511
### Non-breaking changes

strict-stm/src/Control/Concurrent/Class/MonadSTM/Strict/TMVar.hs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,6 @@ import Control.Monad.Class.MonadSTM hiding (traceTMVar, traceTMVarIO)
4040
type LazyTMVar m = Lazy.TMVar m
4141

4242
-- | 'TMVar' that keeps its value in WHNF at all times
43-
--
44-
-- Does not support an invariant: if the invariant would not be satisfied,
45-
-- we would not be able to put a value into an empty TMVar, which would lead
46-
-- to very hard to debug bugs where code is blocked indefinitely.
4743
newtype StrictTMVar m a = StrictTMVar { toLazyTMVar :: LazyTMVar m a }
4844

4945
fromLazyTMVar :: LazyTMVar m a -> StrictTMVar m a
Lines changed: 13 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
{-# LANGUAGE BangPatterns #-}
2-
{-# LANGUAGE CPP #-}
3-
{-# LANGUAGE ExplicitNamespaces #-}
4-
{-# LANGUAGE GADTs #-}
5-
{-# LANGUAGE NamedFieldPuns #-}
6-
{-# LANGUAGE TypeOperators #-}
1+
{-# LANGUAGE BangPatterns #-}
2+
{-# LANGUAGE TypeFamilies #-}
3+
{-# LANGUAGE TypeOperators #-}
74

85
-- | This module corresponds to `Control.Concurrent.STM.TVar` in "stm" package
96
--
@@ -16,17 +13,13 @@ module Control.Concurrent.Class.MonadSTM.Strict.TVar
1613
, castStrictTVar
1714
, newTVar
1815
, newTVarIO
19-
, newTVarWithInvariant
20-
, newTVarWithInvariantIO
2116
, readTVar
2217
, readTVarIO
2318
, writeTVar
2419
, modifyTVar
2520
, stateTVar
2621
, swapTVar
2722
, check
28-
-- ** Low-level API
29-
, checkInvariant
3023
-- * MonadLabelSTM
3124
, labelTVar
3225
, labelTVarIO
@@ -38,22 +31,11 @@ module Control.Concurrent.Class.MonadSTM.Strict.TVar
3831
import qualified Control.Concurrent.Class.MonadSTM.TVar as Lazy
3932
import Control.Monad.Class.MonadSTM hiding (traceTVar, traceTVarIO)
4033

41-
import GHC.Stack
34+
type LazyTVar m = Lazy.TVar m
4235

43-
44-
type LazyTVar m = Lazy.TVar m
45-
46-
#if CHECK_TVAR_INVARIANT
47-
data StrictTVar m a = StrictTVar
48-
{ invariant :: !(a -> Maybe String)
49-
-- ^ Invariant checked whenever updating the 'StrictTVar'.
50-
, tvar :: !(LazyTVar m a)
51-
}
52-
#else
53-
newtype StrictTVar m a = StrictTVar
54-
{ tvar :: LazyTVar m a
55-
}
56-
#endif
36+
newtype StrictTVar m a = StrictTVar {
37+
tvar :: LazyTVar m a
38+
}
5739

5840
labelTVar :: MonadLabelledSTM m => StrictTVar m a -> String -> STM m ()
5941
labelTVar StrictTVar { tvar } = Lazy.labelTVar tvar
@@ -76,8 +58,7 @@ traceTVarIO StrictTVar {tvar} = Lazy.traceTVarIO tvar
7658

7759
castStrictTVar :: LazyTVar m ~ LazyTVar n
7860
=> StrictTVar m a -> StrictTVar n a
79-
castStrictTVar v@StrictTVar {tvar} =
80-
mkStrictTVar (getInvariant v) tvar
61+
castStrictTVar StrictTVar {tvar} = StrictTVar {tvar}
8162

8263
-- | Get the underlying @TVar@
8364
--
@@ -87,50 +68,22 @@ toLazyTVar :: StrictTVar m a -> LazyTVar m a
8768
toLazyTVar StrictTVar { tvar } = tvar
8869

8970
fromLazyTVar :: LazyTVar m a -> StrictTVar m a
90-
fromLazyTVar tvar =
91-
#if CHECK_TVAR_INVARIANT
92-
StrictTVar { invariant = const Nothing
93-
, tvar
94-
}
95-
#else
96-
StrictTVar { tvar }
97-
#endif
71+
fromLazyTVar = StrictTVar
9872

9973
newTVar :: MonadSTM m => a -> STM m (StrictTVar m a)
100-
newTVar !a = (\tvar -> mkStrictTVar (const Nothing) tvar)
101-
<$> Lazy.newTVar a
74+
newTVar !a = StrictTVar <$> Lazy.newTVar a
10275

10376
newTVarIO :: MonadSTM m => a -> m (StrictTVar m a)
104-
newTVarIO = newTVarWithInvariantIO (const Nothing)
105-
106-
newTVarWithInvariant :: (MonadSTM m, HasCallStack)
107-
=> (a -> Maybe String) -- ^ Invariant (expect 'Nothing')
108-
-> a
109-
-> STM m (StrictTVar m a)
110-
newTVarWithInvariant invariant !a =
111-
checkInvariant (invariant a) $
112-
(\tvar -> mkStrictTVar invariant tvar)
113-
<$> Lazy.newTVar a
114-
115-
newTVarWithInvariantIO :: (MonadSTM m, HasCallStack)
116-
=> (a -> Maybe String) -- ^ Invariant (expect 'Nothing')
117-
-> a
118-
-> m (StrictTVar m a)
119-
newTVarWithInvariantIO invariant !a =
120-
checkInvariant (invariant a) $
121-
(\tvar -> mkStrictTVar invariant tvar)
122-
<$> Lazy.newTVarIO a
77+
newTVarIO !a = StrictTVar <$> Lazy.newTVarIO a
12378

12479
readTVar :: MonadSTM m => StrictTVar m a -> STM m a
12580
readTVar StrictTVar { tvar } = Lazy.readTVar tvar
12681

12782
readTVarIO :: MonadSTM m => StrictTVar m a -> m a
12883
readTVarIO StrictTVar { tvar } = Lazy.readTVarIO tvar
12984

130-
writeTVar :: (MonadSTM m, HasCallStack) => StrictTVar m a -> a -> STM m ()
131-
writeTVar v !a =
132-
checkInvariant (getInvariant v a) $
133-
Lazy.writeTVar (tvar v) a
85+
writeTVar :: MonadSTM m => StrictTVar m a -> a -> STM m ()
86+
writeTVar v !a = Lazy.writeTVar (tvar v) a
13487

13588
modifyTVar :: MonadSTM m => StrictTVar m a -> (a -> a) -> STM m ()
13689
modifyTVar v f = readTVar v >>= writeTVar v . f
@@ -147,34 +100,3 @@ swapTVar v a' = do
147100
a <- readTVar v
148101
writeTVar v a'
149102
return a
150-
151-
152-
{-------------------------------------------------------------------------------
153-
Dealing with invariants
154-
-------------------------------------------------------------------------------}
155-
156-
getInvariant :: StrictTVar m a -> a -> Maybe String
157-
mkStrictTVar :: (a -> Maybe String) -> Lazy.TVar m a -> StrictTVar m a
158-
159-
-- | Check invariant (if enabled) before continuing
160-
--
161-
-- @checkInvariant mErr x@ is equal to @x@ if @mErr == Nothing@, and throws
162-
-- an error @err@ if @mErr == Just err@.
163-
--
164-
-- This is exported so that other code that wants to conditionally check
165-
-- invariants can reuse the same logic, rather than having to introduce new
166-
-- per-package flags.
167-
checkInvariant :: HasCallStack => Maybe String -> a -> a
168-
169-
#if CHECK_TVAR_INVARIANT
170-
getInvariant StrictTVar {invariant} = invariant
171-
mkStrictTVar invariant tvar = StrictTVar {invariant, tvar}
172-
173-
checkInvariant Nothing k = k
174-
checkInvariant (Just err) _ = error $ "Invariant violation: " ++ err
175-
#else
176-
getInvariant _ = \_ -> Nothing
177-
mkStrictTVar _invariant tvar = StrictTVar {tvar}
178-
179-
checkInvariant _err k = k
180-
#endif

strict-stm/strict-stm.cabal

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ source-repository head
2323
location: https://github.com/input-output-hk/io-sim
2424
subdir: strict-stm
2525

26-
flag checktvarinvariant
27-
Description: Enable runtime invariant checks on StrictT(M)Var
28-
Manual: True
29-
Default: False
30-
3126
flag asserts
3227
description: Enable assertions
3328
manual: False
@@ -68,6 +63,3 @@ library
6863

6964
if flag(asserts)
7065
ghc-options: -fno-ignore-asserts
71-
72-
if flag(checktvarinvariant)
73-
cpp-options: -DCHECK_TVAR_INVARIANT

0 commit comments

Comments
 (0)