Skip to content

Commit c1d12b6

Browse files
authored
Merge pull request #108 from input-output-hk/jdral/factor-out-checked-strict-mvar
Factor out checked `StrictMVar`s
2 parents 7cc199a + 1b2c22b commit c1d12b6

File tree

9 files changed

+9
-367
lines changed

9 files changed

+9
-367
lines changed

.github/workflows/haskell.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,9 @@ jobs:
130130
- name: si-timers [test]
131131
run: cabal run si-timers:test
132132

133-
- name: strict-mvar [test] [unchecked]
134-
run: cabal run --flag="-testchecked" strict-mvar:test
133+
- name: strict-mvar [test]
134+
run: cabal run strict-mvar:test
135135

136-
- name: strict-mvar [test] [checked]
137-
run: cabal run --flag="+testchecked" strict-mvar:test
138136

139137
stylish-haskell:
140138
runs-on: ubuntu-22.04

strict-mvar/CHANGELOG.md

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,13 @@
66

77
* Remove the `asserts` package flag.
88

9-
### Non breaking changes
9+
### Non-breaking changes
1010

11-
* Add a `StrictMVar` with invariant checking in
12-
`Control.Concurrent.Class.MonadMVar.Strict.Checked`.
13-
* Make the checked/unchecked `StrictMVar` modules drop-in replacements of one
14-
another by unifying the interfaces. As a result,
15-
`Control.Concurrent.Class.MonadMVar.Strict` now has `newMVarWithInvariant` and
16-
`newEmptyMVarWithInvariant` functions that ignore the invariant argument.
11+
* Export `LazyMVar`.
1712

1813
### Patch
1914

20-
* Functions that use invariant checking now correctly propagate `HasCallStack`
21-
constraints.
15+
* Update cabal header fields like `author` and `category`.
2216

2317
## 1.1.0.0
2418

strict-mvar/README.md

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,3 @@ The `strict-mvar` package provides a strict interface to mutable variables
55
for `MVar`s implementations from both
66
[base](https://hackage.haskell.org/package/base-4.17.0.0/docs/Control-Concurrent-MVar.html)
77
and [io-sim](https://github.com/input-output-hk/io-sim).
8-
9-
## Checked and unchecked `StrictMVar`s
10-
11-
There are currently two variant implementations of `StrictMVar`s in this package:
12-
* `Control.Concurrent.Class.MonadMVar.Strict`
13-
* `Control.Concurrent.Class.MonadMVar.Strict.Checked`
14-
15-
The _unchecked_ module provides the simplest implementation of a `StrictMVar`: a
16-
light wrapper around lazy MVars that forces values to WHNF before they are put
17-
into the MVar. The _checked_ module does the exact same thing, but it has the
18-
additional feature that the user can provide an invariant that is checked each
19-
time a new value is placed inside the MVar. The two modules are drop-in
20-
replacements for one another: switching from `*.Strict` to `*.Strict.Checked`
21-
will enable invariant checking, while the converse will disable invariant
22-
checking. To facilitate drop-in replacement, both modules share the same
23-
interface, though in case of the `*.Strict` module, everything related to
24-
invariants will be ignored. This will be explicitly mentioned in the Haddock
25-
documentation of said definitions. For example:
26-
27-
```haskell
28-
-- | The given invariant will never be checked. 'newMVarWithInvariant' is a
29-
-- light wrapper around 'newMVar', and is only included here to ensure that the
30-
-- current module and "Control.Concurrent.Class.MonadMVar.Strict.Checked" are
31-
-- drop-in replacements for one another.
32-
newMVarWithInvariant :: MonadMVar m
33-
=> (a -> Maybe String)
34-
-> a
35-
-> m (StrictMVar m a)
36-
```
37-
38-
**Note:** though the two modules are drop-in replacements for one another, the
39-
`StrictMVar` type from `*.Strict` and the `StrictMVar` type from
40-
`*.Strict.Checked` do not share the same internal representation, and so they
41-
are distinct types.
42-
43-
## Guarantees for invariant checking
44-
45-
Although all functions that modify a checked `StrictMVar` will check the
46-
invariant, we do *not* guarantee that the value inside the `StrictMVar` always
47-
satisfies the invariant. Instead, we *do* guarantee that if the `StrictMVar` is
48-
updated with a value that does not satisfy the invariant, an exception is thrown
49-
*after* the new value is written to the `StrictMVar`. The reason for this weaker
50-
guarantee is that leaving an `MVar` empty can lead to very hard to debug
51-
"blocked indefinitely" problems.

strict-mvar/src/Control/Concurrent/Class/MonadMVar/Strict.hs

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
{-# LANGUAGE TypeOperators #-}
44

55
-- | This module corresponds to "Control.Concurrent.MVar" in the @base@ package.
6-
--
7-
-- Use "Control.Concurrent.Class.MonadMVar.Strict.Checked" as a drop-in
8-
-- replacement for the current module in case you want to check invariants on
9-
-- the values inside 'StrictMVar's.
106
module Control.Concurrent.Class.MonadMVar.Strict
117
( -- * StrictMVar
128
StrictMVar
@@ -15,9 +11,7 @@ module Control.Concurrent.Class.MonadMVar.Strict
1511
, toLazyMVar
1612
, fromLazyMVar
1713
, newEmptyMVar
18-
, newEmptyMVarWithInvariant
1914
, newMVar
20-
, newMVarWithInvariant
2115
, takeMVar
2216
, putMVar
2317
, readMVar
@@ -71,28 +65,9 @@ fromLazyMVar = StrictMVar
7165
newEmptyMVar :: MonadMVar m => m (StrictMVar m a)
7266
newEmptyMVar = fromLazyMVar <$> Lazy.newEmptyMVar
7367

74-
-- | The given invariant will never be checked. 'newEmptyMVarWithInvariant' is a
75-
-- light wrapper around 'newEmptyMVar', and is only included here to ensure that
76-
-- the current module and "Control.Concurrent.Class.MonadMVar.Strict.Checked"
77-
-- are drop-in replacements for one another.
78-
newEmptyMVarWithInvariant :: MonadMVar m
79-
=> (a -> Maybe String)
80-
-> m (StrictMVar m a)
81-
newEmptyMVarWithInvariant _inv = StrictMVar <$> Lazy.newEmptyMVar
82-
8368
newMVar :: MonadMVar m => a -> m (StrictMVar m a)
8469
newMVar !a = fromLazyMVar <$> Lazy.newMVar a
8570

86-
-- | The given invariant will never be checked. 'newMVarWithInvariant' is a
87-
-- light wrapper around 'newMVar', and is only included here to ensure that the
88-
-- current module and "Control.Concurrent.Class.MonadMVar.Strict.Checked" are
89-
-- drop-in replacements for one another.
90-
newMVarWithInvariant :: MonadMVar m
91-
=> (a -> Maybe String)
92-
-> a
93-
-> m (StrictMVar m a)
94-
newMVarWithInvariant _inv !a = StrictMVar <$> Lazy.newMVar a
95-
9671
takeMVar :: MonadMVar m => StrictMVar m a -> m a
9772
takeMVar = Lazy.takeMVar . mvar
9873

strict-mvar/src/Control/Concurrent/Class/MonadMVar/Strict/Checked.hs

Lines changed: 0 additions & 200 deletions
This file was deleted.

strict-mvar/strict-mvar.cabal

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ library
2626
hs-source-dirs: src
2727

2828
exposed-modules: Control.Concurrent.Class.MonadMVar.Strict
29-
, Control.Concurrent.Class.MonadMVar.Strict.Checked
3029
default-language: Haskell2010
3130
build-depends: base >= 4.9 && <4.19,
32-
io-classes >= 1.0 && <1.2
31+
io-classes ^>= 1.1,
3332
ghc-options: -Wall
3433
-Wno-unticked-promoted-constructors
3534
-Wcompat
@@ -38,18 +37,12 @@ library
3837
-Wpartial-fields
3938
-Widentities
4039

41-
flag testchecked
42-
description: Run tests for checked Strict MVars.
43-
Default: False
44-
Manual: True
45-
4640
test-suite test
4741
type: exitcode-stdio-1.0
4842
hs-source-dirs: test
4943
main-is: Main.hs
5044

51-
other-modules: Test.Control.Concurrent.Class.MonadMVar.Strict.Checked
52-
Test.Control.Concurrent.Class.MonadMVar.Strict.WHNF
45+
other-modules: Test.Control.Concurrent.Class.MonadMVar.Strict.WHNF
5346
Test.Utils
5447
default-language: Haskell2010
5548
build-depends: base >=4.9 && <4.19,
@@ -68,6 +61,3 @@ test-suite test
6861
-Wpartial-fields
6962
-Widentities
7063
-fno-ignore-asserts
71-
72-
if flag(testchecked)
73-
CPP-Options: -DTEST_CHECKED

strict-mvar/test/Main.hs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
module Main where
22

3-
import qualified Test.Control.Concurrent.Class.MonadMVar.Strict.Checked as Checked
43
import qualified Test.Control.Concurrent.Class.MonadMVar.Strict.WHNF as WHNF
54
import Test.Tasty
65

76
main :: IO ()
87
main = defaultMain $ testGroup "strict-mvar" [
9-
Checked.tests
10-
, WHNF.tests
8+
WHNF.tests
119
]

0 commit comments

Comments
 (0)