Strict MVars and TVars with invariant checking for IO and IOSim.
Strict MVar
s and TVar
s with invariant checking
The strict-checked-vars
package provides a strict interface to mutable variables (MVar
) and TVar
s with invariant checking. It builds on top of strict-mvar
, strict-stm
and io-classes
, and thus it provides the interface for MVar
/TVar
implementations for both IO and io-sim.
Checked and unchecked variants
There are currently two variant implementations of StrictTVar
s.
- From
strict-stm
:Control.Concurrent.Class.MonadSTM.Strict.TVar
- From
strict-checked-vars
:Control.Concurrent.Class.MonadSTM.Strict.TVar.Checked
Similarly, there are currently two variant implementations of StrictMVar
s.
- From
strict-mvar
:Control.Concurrent.Class.MonadMVar.Strict
- From
strict-checked-vars
:Control.Concurrent.Class.MonadMVar.Strict.Checked
The unchecked modules provide the simplest implementation of strict variables: a light wrapper around lazy variables that forces values to WHNF before they are put inside the variable. The checked module does the exact same thing, but it has the additional feature that the user can provide an invariant that is checked each time a new value is placed inside the variable. The checked modules are drop-in replacements for the unchecked modules, though invariants will be trivially true in that case. Non-trivial invariants can be set when creating a new variable.
newMVarWithInvariant :: MonadMVar m
=> (a -> Maybe String)
-> a
-> m (StrictMVar m a)
newEmptyMVarWithInvariant :: MonadMVar m
=> (a -> Maybe String)
-> m (StrictMVar m a)
newTVarWithInvariant :: (MonadSTM m, HasCallStack)
=> (a -> Maybe String)
-> a
-> STM m (StrictTVar m a)
newTVarWithInvariantIO :: (MonadSTM m, HasCallStack)
=> (a -> Maybe String)
-> a
-> m (StrictTVar m a)
Note: though the checked modules are drop-in replacements for the unchecked modules, the StrictMVar
/StrictTVar
types are distinct. This means we can't make mixed use of the checked and unchecked modules.
Guarantees for invariant checking on StrictMVar
s
Although all functions that modify a checked StrictMVar
will check the invariant, we do not guarantee that the value inside the StrictMVar
always satisfies the invariant. Instead, we do guarantee that if the StrictMVar
is updated with a value that does not satisfy the invariant, an exception is thrown after the new value is written to the StrictMVar
. The reason for this weaker guarantee is that leaving an MVar
empty can lead to very hard to debug "blocked indefinitely" problems.