packages feed

dejafu 2.0.0.1 → 2.1.0.0

raw patch · 13 files changed

+395/−223 lines, 13 filesdep ~concurrencyPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: concurrency

API changes (from Hackage documentation)

- Test.DejaFu.Conc.Internal.Threading: BoundThread :: MVar n (n (Action n)) -> MVar n (Action n) -> ThreadId n -> BoundThread n
- Test.DejaFu.Conc.Internal.Threading: [_boundTId] :: BoundThread n -> ThreadId n
- Test.DejaFu.Conc.Internal.Threading: [_getboundIO] :: BoundThread n -> MVar n (Action n)
- Test.DejaFu.Conc.Internal.Threading: [_runboundIO] :: BoundThread n -> MVar n (n (Action n))
- Test.DejaFu.Conc.Internal.Threading: data BoundThread n
+ Test.DejaFu.Conc: SupportsBoundThreads :: Bool -> ThreadAction
+ Test.DejaFu.Conc: WillSupportsBoundThreads :: Lookahead
+ Test.DejaFu.Conc.Internal.Common: ASupportsBoundThreads :: (Bool -> Action n) -> Action n
+ Test.DejaFu.Types: --
+ Test.DejaFu.Types: -- (for example, if it's not based on <tt>IO</tt>), then this should be
+ Test.DejaFu.Types: -- These references are always used from the same Haskell thread, so it's
+ Test.DejaFu.Types: -- does).
+ Test.DejaFu.Types: -- relaxed-memory behaviours (like <tt>IORef</tt>s).
+ Test.DejaFu.Types: -- safe to implement these using unsynchronised primitives with
+ Test.DejaFu.Types: -- some type which can't be constructed, like <a>V1</a>.
+ Test.DejaFu.Types: -- value, and so don't need to handle emptiness (like <tt>MVar</tt>
+ Test.DejaFu.Types: -- | A handle to a bound thread. If the monad doesn't support bound threads
+ Test.DejaFu.Types: IOBoundThread :: (IO a -> IO a) -> IO () -> IOBoundThread a
+ Test.DejaFu.Types: SupportsBoundThreads :: Bool -> ThreadAction
+ Test.DejaFu.Types: WillSupportsBoundThreads :: Lookahead
+ Test.DejaFu.Types: [iobtKillBoundThread] :: IOBoundThread a -> IO ()
+ Test.DejaFu.Types: [iobtRunInBoundThread] :: IOBoundThread a -> IO a -> IO a
+ Test.DejaFu.Types: class MonadThrow m => MonadDejaFu m where {
+ Test.DejaFu.Types: data IOBoundThread a
+ Test.DejaFu.Types: forkBoundThread :: MonadDejaFu m => Maybe (m (BoundThread m a))
+ Test.DejaFu.Types: instance Test.DejaFu.Types.MonadDejaFu (Control.Monad.Catch.Pure.CatchT (GHC.ST.ST t))
+ Test.DejaFu.Types: instance Test.DejaFu.Types.MonadDejaFu GHC.Types.IO
+ Test.DejaFu.Types: killBoundThread :: MonadDejaFu m => BoundThread m a -> m ()
+ Test.DejaFu.Types: newRef :: MonadDejaFu m => a -> m (Ref m a)
+ Test.DejaFu.Types: readRef :: MonadDejaFu m => Ref m a -> m a
+ Test.DejaFu.Types: runInBoundThread :: MonadDejaFu m => BoundThread m a -> m a -> m a
+ Test.DejaFu.Types: type family BoundThread m :: * -> *;
+ Test.DejaFu.Types: writeRef :: MonadDejaFu m => Ref m a -> a -> m ()
+ Test.DejaFu.Types: }
- Test.DejaFu: autocheck :: (MonadConc n, MonadIO n, Eq a, Show a) => Program pty n a -> n Bool
+ Test.DejaFu: autocheck :: (MonadDejaFu n, MonadIO n, Eq a, Show a) => Program pty n a -> n Bool
- Test.DejaFu: autocheckWay :: (MonadConc n, MonadIO n, Eq a, Show a) => Way -> MemType -> Program pty n a -> n Bool
+ Test.DejaFu: autocheckWay :: (MonadDejaFu n, MonadIO n, Eq a, Show a) => Way -> MemType -> Program pty n a -> n Bool
- Test.DejaFu: autocheckWithSettings :: (MonadConc n, MonadIO n, Eq a, Show a) => Settings n a -> Program pty n a -> n Bool
+ Test.DejaFu: autocheckWithSettings :: (MonadDejaFu n, MonadIO n, Eq a, Show a) => Settings n a -> Program pty n a -> n Bool
- Test.DejaFu: dejafu :: (MonadConc n, MonadIO n, Show b) => String -> ProPredicate a b -> Program pty n a -> n Bool
+ Test.DejaFu: dejafu :: (MonadDejaFu n, MonadIO n, Show b) => String -> ProPredicate a b -> Program pty n a -> n Bool
- Test.DejaFu: dejafuWay :: (MonadConc n, MonadIO n, Show b) => Way -> MemType -> String -> ProPredicate a b -> Program pty n a -> n Bool
+ Test.DejaFu: dejafuWay :: (MonadDejaFu n, MonadIO n, Show b) => Way -> MemType -> String -> ProPredicate a b -> Program pty n a -> n Bool
- Test.DejaFu: dejafuWithSettings :: (MonadConc n, MonadIO n, Show b) => Settings n a -> String -> ProPredicate a b -> Program pty n a -> n Bool
+ Test.DejaFu: dejafuWithSettings :: (MonadDejaFu n, MonadIO n, Show b) => Settings n a -> String -> ProPredicate a b -> Program pty n a -> n Bool
- Test.DejaFu: dejafus :: (MonadConc n, MonadIO n, Show b) => [(String, ProPredicate a b)] -> Program pty n a -> n Bool
+ Test.DejaFu: dejafus :: (MonadDejaFu n, MonadIO n, Show b) => [(String, ProPredicate a b)] -> Program pty n a -> n Bool
- Test.DejaFu: dejafusWay :: (MonadConc n, MonadIO n, Show b) => Way -> MemType -> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
+ Test.DejaFu: dejafusWay :: (MonadDejaFu n, MonadIO n, Show b) => Way -> MemType -> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
- Test.DejaFu: dejafusWithSettings :: (MonadConc n, MonadIO n, Show b) => Settings n a -> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
+ Test.DejaFu: dejafusWithSettings :: (MonadDejaFu n, MonadIO n, Show b) => Settings n a -> [(String, ProPredicate a b)] -> Program pty n a -> n Bool
- Test.DejaFu: runTest :: MonadConc n => ProPredicate a b -> Program pty n a -> n (Result b)
+ Test.DejaFu: runTest :: MonadDejaFu n => ProPredicate a b -> Program pty n a -> n (Result b)
- Test.DejaFu: runTestWay :: MonadConc n => Way -> MemType -> ProPredicate a b -> Program pty n a -> n (Result b)
+ Test.DejaFu: runTestWay :: MonadDejaFu n => Way -> MemType -> ProPredicate a b -> Program pty n a -> n (Result b)
- Test.DejaFu: runTestWithSettings :: MonadConc n => Settings n a -> ProPredicate a b -> Program pty n a -> n (Result b)
+ Test.DejaFu: runTestWithSettings :: MonadDejaFu n => Settings n a -> ProPredicate a b -> Program pty n a -> n (Result b)
- Test.DejaFu.Conc: recordSnapshot :: MonadConc n => Program pty n a -> n (Maybe (Either Condition (Snapshot pty n a), Trace))
+ Test.DejaFu.Conc: recordSnapshot :: MonadDejaFu n => Program pty n a -> n (Maybe (Either Condition (Snapshot pty n a), Trace))
- Test.DejaFu.Conc: runConcurrent :: MonadConc n => Scheduler s -> MemType -> s -> Program pty n a -> n (Either Condition a, s, Trace)
+ Test.DejaFu.Conc: runConcurrent :: MonadDejaFu n => Scheduler s -> MemType -> s -> Program pty n a -> n (Either Condition a, s, Trace)
- Test.DejaFu.Conc: runSnapshot :: MonadConc n => Scheduler s -> MemType -> s -> Snapshot pty n a -> n (Either Condition a, s, Trace)
+ Test.DejaFu.Conc: runSnapshot :: MonadDejaFu n => Scheduler s -> MemType -> s -> Snapshot pty n a -> n (Either Condition a, s, Trace)
- Test.DejaFu.Conc.Internal: CResult :: Context n g -> IORef n (Maybe (Either Condition a)) -> (Threads n -> n ()) -> SeqTrace -> Maybe (ThreadId, ThreadAction) -> CResult n g a
+ Test.DejaFu.Conc.Internal: CResult :: Context n g -> Ref n (Maybe (Either Condition a)) -> (Threads n -> n ()) -> SeqTrace -> Maybe (ThreadId, ThreadAction) -> CResult n g a
- Test.DejaFu.Conc.Internal: [finalRef] :: CResult n g a -> IORef n (Maybe (Either Condition a))
+ Test.DejaFu.Conc.Internal: [finalRef] :: CResult n g a -> Ref n (Maybe (Either Condition a))
- Test.DejaFu.Conc.Internal: checkInvariant :: MonadConc n => Invariant n a -> n (Either SomeException ([IORefId], [MVarId], [TVarId]))
+ Test.DejaFu.Conc.Internal: checkInvariant :: MonadDejaFu n => Invariant n a -> n (Either SomeException ([IORefId], [MVarId], [TVarId]))
- Test.DejaFu.Conc.Internal: checkInvariants :: MonadConc n => InvariantContext n -> n (Either SomeException (InvariantContext n))
+ Test.DejaFu.Conc.Internal: checkInvariants :: MonadDejaFu n => InvariantContext n -> n (Either SomeException (InvariantContext n))
- Test.DejaFu.Conc.Internal: doInvariant :: MonadConc n => Invariant n a -> n (Either SomeException a, [IORefId], [MVarId], [TVarId])
+ Test.DejaFu.Conc.Internal: doInvariant :: MonadDejaFu n => Invariant n a -> n (Either SomeException a, [IORefId], [MVarId], [TVarId])
- Test.DejaFu.Conc.Internal: killAllThreads :: (MonadConc n, HasCallStack) => Context n g -> n ()
+ Test.DejaFu.Conc.Internal: killAllThreads :: (MonadDejaFu n, HasCallStack) => Context n g -> n ()
- Test.DejaFu.Conc.Internal: runConcurrency :: (MonadConc n, HasCallStack) => [Invariant n ()] -> Bool -> Scheduler g -> MemType -> g -> IdSource -> Int -> ModelConc n a -> n (CResult n g a)
+ Test.DejaFu.Conc.Internal: runConcurrency :: (MonadDejaFu n, HasCallStack) => [Invariant n ()] -> Bool -> Scheduler g -> MemType -> g -> IdSource -> Int -> ModelConc n a -> n (CResult n g a)
- Test.DejaFu.Conc.Internal: runConcurrencyWithSnapshot :: (MonadConc n, HasCallStack) => Scheduler g -> MemType -> Context n g -> (Threads n -> n ()) -> ModelConc n a -> n (CResult n g a)
+ Test.DejaFu.Conc.Internal: runConcurrencyWithSnapshot :: (MonadDejaFu n, HasCallStack) => Scheduler g -> MemType -> Context n g -> (Threads n -> n ()) -> ModelConc n a -> n (CResult n g a)
- Test.DejaFu.Conc.Internal: runThreads :: (MonadConc n, HasCallStack) => Bool -> Scheduler g -> MemType -> IORef n (Maybe (Either Condition a)) -> Context n g -> n (CResult n g a)
+ Test.DejaFu.Conc.Internal: runThreads :: (MonadDejaFu n, HasCallStack) => Bool -> Scheduler g -> MemType -> Ref n (Maybe (Either Condition a)) -> Context n g -> n (CResult n g a)
- Test.DejaFu.Conc.Internal: stepInvariant :: MonadConc n => IAction n -> n (Either SomeException (Maybe (IAction n)), [IORefId], [MVarId], [TVarId])
+ Test.DejaFu.Conc.Internal: stepInvariant :: MonadDejaFu n => IAction n -> n (Either SomeException (Maybe (IAction n)), [IORefId], [MVarId], [TVarId])
- Test.DejaFu.Conc.Internal: stepThread :: (MonadConc n, HasCallStack) => Bool -> Bool -> Scheduler g -> MemType -> ThreadId -> Action n -> Context n g -> n (What n g, ThreadAction, Threads n -> n ())
+ Test.DejaFu.Conc.Internal: stepThread :: forall n g. (MonadDejaFu n, HasCallStack) => Bool -> Bool -> Scheduler g -> MemType -> ThreadId -> Action n -> Context n g -> n (What n g, ThreadAction, Threads n -> n ())
- Test.DejaFu.Conc.Internal: stepThrow :: (MonadConc n, Exception e) => (Bool -> ThreadAction) -> ThreadId -> e -> Context n g -> n (What n g, ThreadAction, Threads n -> n ())
+ Test.DejaFu.Conc.Internal: stepThrow :: (MonadDejaFu n, Exception e) => (Bool -> ThreadAction) -> ThreadId -> e -> Context n g -> n (What n g, ThreadAction, Threads n -> n ())
- Test.DejaFu.Conc.Internal: synchronised :: MonadConc n => (Context n g -> n x) -> Context n g -> n x
+ Test.DejaFu.Conc.Internal: synchronised :: MonadDejaFu n => (Context n g -> n x) -> Context n g -> n x
- Test.DejaFu.Conc.Internal.Common: ModelIORef :: IORefId -> IORef n (Map ThreadId a, Integer, a) -> ModelIORef n a
+ Test.DejaFu.Conc.Internal.Common: ModelIORef :: IORefId -> Ref n (Map ThreadId a, Integer, a) -> ModelIORef n a
- Test.DejaFu.Conc.Internal.Common: ModelMVar :: MVarId -> IORef n (Maybe a) -> ModelMVar n a
+ Test.DejaFu.Conc.Internal.Common: ModelMVar :: MVarId -> Ref n (Maybe a) -> ModelMVar n a
- Test.DejaFu.Conc.Internal.Common: [iorefRef] :: ModelIORef n a -> IORef n (Map ThreadId a, Integer, a)
+ Test.DejaFu.Conc.Internal.Common: [iorefRef] :: ModelIORef n a -> Ref n (Map ThreadId a, Integer, a)
- Test.DejaFu.Conc.Internal.Common: [mvarRef] :: ModelMVar n a -> IORef n (Maybe a)
+ Test.DejaFu.Conc.Internal.Common: [mvarRef] :: ModelMVar n a -> Ref n (Maybe a)
- Test.DejaFu.Conc.Internal.Memory: bufferWrite :: MonadConc n => WriteBuffer n -> (ThreadId, Maybe IORefId) -> ModelIORef n a -> a -> n (WriteBuffer n)
+ Test.DejaFu.Conc.Internal.Memory: bufferWrite :: MonadDejaFu n => WriteBuffer n -> (ThreadId, Maybe IORefId) -> ModelIORef n a -> a -> n (WriteBuffer n)
- Test.DejaFu.Conc.Internal.Memory: casIORef :: MonadConc n => ModelIORef n a -> ThreadId -> ModelTicket a -> a -> n (Bool, ModelTicket a, n ())
+ Test.DejaFu.Conc.Internal.Memory: casIORef :: MonadDejaFu n => ModelIORef n a -> ThreadId -> ModelTicket a -> a -> n (Bool, ModelTicket a, n ())
- Test.DejaFu.Conc.Internal.Memory: commitWrite :: MonadConc n => WriteBuffer n -> (ThreadId, Maybe IORefId) -> n (WriteBuffer n)
+ Test.DejaFu.Conc.Internal.Memory: commitWrite :: MonadDejaFu n => WriteBuffer n -> (ThreadId, Maybe IORefId) -> n (WriteBuffer n)
- Test.DejaFu.Conc.Internal.Memory: mutMVar :: MonadConc n => Blocking -> ModelMVar n a -> a -> (Bool -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
+ Test.DejaFu.Conc.Internal.Memory: mutMVar :: MonadDejaFu n => Blocking -> ModelMVar n a -> a -> (Bool -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- Test.DejaFu.Conc.Internal.Memory: putIntoMVar :: MonadConc n => ModelMVar n a -> a -> Action n -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
+ Test.DejaFu.Conc.Internal.Memory: putIntoMVar :: MonadDejaFu n => ModelMVar n a -> a -> Action n -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- Test.DejaFu.Conc.Internal.Memory: readForTicket :: MonadConc n => ModelIORef n a -> ThreadId -> n (ModelTicket a)
+ Test.DejaFu.Conc.Internal.Memory: readForTicket :: MonadDejaFu n => ModelIORef n a -> ThreadId -> n (ModelTicket a)
- Test.DejaFu.Conc.Internal.Memory: readFromMVar :: (MonadConc n, HasCallStack) => ModelMVar n a -> (a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
+ Test.DejaFu.Conc.Internal.Memory: readFromMVar :: (MonadDejaFu n, HasCallStack) => ModelMVar n a -> (a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- Test.DejaFu.Conc.Internal.Memory: readIORef :: MonadConc n => ModelIORef n a -> ThreadId -> n a
+ Test.DejaFu.Conc.Internal.Memory: readIORef :: MonadDejaFu n => ModelIORef n a -> ThreadId -> n a
- Test.DejaFu.Conc.Internal.Memory: readIORefGlobal :: MonadConc n => ModelIORef n a -> n a
+ Test.DejaFu.Conc.Internal.Memory: readIORefGlobal :: MonadDejaFu n => ModelIORef n a -> n a
- Test.DejaFu.Conc.Internal.Memory: readIORefPrim :: MonadConc n => ModelIORef n a -> ThreadId -> n (a, Integer)
+ Test.DejaFu.Conc.Internal.Memory: readIORefPrim :: MonadDejaFu n => ModelIORef n a -> ThreadId -> n (a, Integer)
- Test.DejaFu.Conc.Internal.Memory: seeMVar :: MonadConc n => Emptying -> Blocking -> ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
+ Test.DejaFu.Conc.Internal.Memory: seeMVar :: MonadDejaFu n => Emptying -> Blocking -> ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- Test.DejaFu.Conc.Internal.Memory: takeFromMVar :: (MonadConc n, HasCallStack) => ModelMVar n a -> (a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
+ Test.DejaFu.Conc.Internal.Memory: takeFromMVar :: (MonadDejaFu n, HasCallStack) => ModelMVar n a -> (a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- Test.DejaFu.Conc.Internal.Memory: tryPutIntoMVar :: MonadConc n => ModelMVar n a -> a -> (Bool -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
+ Test.DejaFu.Conc.Internal.Memory: tryPutIntoMVar :: MonadDejaFu n => ModelMVar n a -> a -> (Bool -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- Test.DejaFu.Conc.Internal.Memory: tryReadFromMVar :: MonadConc n => ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
+ Test.DejaFu.Conc.Internal.Memory: tryReadFromMVar :: MonadDejaFu n => ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- Test.DejaFu.Conc.Internal.Memory: tryTakeFromMVar :: MonadConc n => ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
+ Test.DejaFu.Conc.Internal.Memory: tryTakeFromMVar :: MonadDejaFu n => ModelMVar n a -> (Maybe a -> Action n) -> ThreadId -> Threads n -> n (Bool, Threads n, [ThreadId], n ())
- Test.DejaFu.Conc.Internal.Memory: writeBarrier :: MonadConc n => WriteBuffer n -> n ()
+ Test.DejaFu.Conc.Internal.Memory: writeBarrier :: MonadDejaFu n => WriteBuffer n -> n ()
- Test.DejaFu.Conc.Internal.Memory: writeImmediate :: MonadConc n => ModelIORef n a -> a -> n (n ())
+ Test.DejaFu.Conc.Internal.Memory: writeImmediate :: MonadDejaFu n => ModelIORef n a -> a -> n (n ())
- Test.DejaFu.Conc.Internal.Program: defaultRecordSnapshot :: MonadConc n => (SimpleSnapshot n a -> x -> snap) -> ModelConc n x -> (x -> ModelConc n a) -> n (Maybe (Either Condition snap, Trace))
+ Test.DejaFu.Conc.Internal.Program: defaultRecordSnapshot :: MonadDejaFu n => (SimpleSnapshot n a -> x -> snap) -> ModelConc n x -> (x -> ModelConc n a) -> n (Maybe (Either Condition snap, Trace))
- Test.DejaFu.Conc.Internal.Program: recordSnapshot :: MonadConc n => Program pty n a -> n (Maybe (Either Condition (Snapshot pty n a), Trace))
+ Test.DejaFu.Conc.Internal.Program: recordSnapshot :: MonadDejaFu n => Program pty n a -> n (Maybe (Either Condition (Snapshot pty n a), Trace))
- Test.DejaFu.Conc.Internal.Program: runConcurrent :: MonadConc n => Scheduler s -> MemType -> s -> Program pty n a -> n (Either Condition a, s, Trace)
+ Test.DejaFu.Conc.Internal.Program: runConcurrent :: MonadDejaFu n => Scheduler s -> MemType -> s -> Program pty n a -> n (Either Condition a, s, Trace)
- Test.DejaFu.Conc.Internal.Program: runSnapshot :: MonadConc n => Scheduler s -> MemType -> s -> Snapshot pty n a -> n (Either Condition a, s, Trace)
+ Test.DejaFu.Conc.Internal.Program: runSnapshot :: MonadDejaFu n => Scheduler s -> MemType -> s -> Snapshot pty n a -> n (Either Condition a, s, Trace)
- Test.DejaFu.Conc.Internal.Program: simpleRunConcurrency :: (MonadConc n, HasCallStack) => Bool -> IdSource -> ModelConc n a -> n (CResult n () a)
+ Test.DejaFu.Conc.Internal.Program: simpleRunConcurrency :: (MonadDejaFu n, HasCallStack) => Bool -> IdSource -> ModelConc n a -> n (CResult n () a)
- Test.DejaFu.Conc.Internal.STM: ModelTVar :: TVarId -> IORef n a -> ModelTVar n a
+ Test.DejaFu.Conc.Internal.STM: ModelTVar :: TVarId -> Ref n a -> ModelTVar n a
- Test.DejaFu.Conc.Internal.STM: [tvarRef] :: ModelTVar n a -> IORef n a
+ Test.DejaFu.Conc.Internal.STM: [tvarRef] :: ModelTVar n a -> Ref n a
- Test.DejaFu.Conc.Internal.STM: doTransaction :: MonadConc n => ModelSTM n a -> IdSource -> n (Result a, n (), IdSource, [TAction])
+ Test.DejaFu.Conc.Internal.STM: doTransaction :: MonadDejaFu n => ModelSTM n a -> IdSource -> n (Result a, n (), IdSource, [TAction])
- Test.DejaFu.Conc.Internal.STM: runTransaction :: MonadConc n => ModelSTM n a -> IdSource -> n (Result a, IdSource, [TAction])
+ Test.DejaFu.Conc.Internal.STM: runTransaction :: MonadDejaFu n => ModelSTM n a -> IdSource -> n (Result a, IdSource, [TAction])
- Test.DejaFu.Conc.Internal.STM: stepTrans :: MonadConc n => STMAction n -> IdSource -> n (STMAction n, n (), IdSource, [TVarId], [TVarId], TAction)
+ Test.DejaFu.Conc.Internal.STM: stepTrans :: MonadDejaFu n => STMAction n -> IdSource -> n (STMAction n, n (), IdSource, [TVarId], [TVarId], TAction)
- Test.DejaFu.Conc.Internal.Threading: Thread :: Action n -> Maybe BlockedOn -> [Handler n] -> MaskingState -> Maybe (BoundThread n) -> Thread n
+ Test.DejaFu.Conc.Internal.Threading: Thread :: Action n -> Maybe BlockedOn -> [Handler n] -> MaskingState -> Maybe (BoundThread n (Action n)) -> Thread n
- Test.DejaFu.Conc.Internal.Threading: [_bound] :: Thread n -> Maybe (BoundThread n)
+ Test.DejaFu.Conc.Internal.Threading: [_bound] :: Thread n -> Maybe (BoundThread n (Action n))
- Test.DejaFu.Conc.Internal.Threading: kill :: (MonadConc n, HasCallStack) => ThreadId -> Threads n -> n (Threads n)
+ Test.DejaFu.Conc.Internal.Threading: kill :: (MonadDejaFu n, HasCallStack) => ThreadId -> Threads n -> n (Threads n)
- Test.DejaFu.Conc.Internal.Threading: makeBound :: (MonadConc n, HasCallStack) => ThreadId -> Threads n -> n (Threads n)
+ Test.DejaFu.Conc.Internal.Threading: makeBound :: (MonadDejaFu n, HasCallStack) => n (BoundThread n (Action n)) -> ThreadId -> Threads n -> n (Threads n)
- Test.DejaFu.Conc.Internal.Threading: runLiftedAct :: MonadConc n => ThreadId -> Threads n -> n (Action n) -> n (Action n)
+ Test.DejaFu.Conc.Internal.Threading: runLiftedAct :: MonadDejaFu n => ThreadId -> Threads n -> n (Action n) -> n (Action n)
- Test.DejaFu.Internal: runRefCont :: MonadConc n => (n () -> x) -> (a -> Maybe b) -> ((a -> x) -> x) -> n (x, IORef n (Maybe b))
+ Test.DejaFu.Internal: runRefCont :: MonadDejaFu n => (n () -> x) -> (a -> Maybe b) -> ((a -> x) -> x) -> n (x, Ref n (Maybe b))
- Test.DejaFu.SCT: resultsSet :: (MonadConc n, Ord a) => Way -> MemType -> Program pty n a -> n (Set (Either Condition a))
+ Test.DejaFu.SCT: resultsSet :: (MonadDejaFu n, Ord a) => Way -> MemType -> Program pty n a -> n (Set (Either Condition a))
- Test.DejaFu.SCT: resultsSet' :: (MonadConc n, Ord a, NFData a) => Way -> MemType -> Program pty n a -> n (Set (Either Condition a))
+ Test.DejaFu.SCT: resultsSet' :: (MonadDejaFu n, Ord a, NFData a) => Way -> MemType -> Program pty n a -> n (Set (Either Condition a))
- Test.DejaFu.SCT: resultsSetWithSettings :: (MonadConc n, Ord a) => Settings n a -> Program pty n a -> n (Set (Either Condition a))
+ Test.DejaFu.SCT: resultsSetWithSettings :: (MonadDejaFu n, Ord a) => Settings n a -> Program pty n a -> n (Set (Either Condition a))
- Test.DejaFu.SCT: resultsSetWithSettings' :: (MonadConc n, Ord a, NFData a) => Settings n a -> Program pty n a -> n (Set (Either Condition a))
+ Test.DejaFu.SCT: resultsSetWithSettings' :: (MonadDejaFu n, Ord a, NFData a) => Settings n a -> Program pty n a -> n (Set (Either Condition a))
- Test.DejaFu.SCT: runSCT :: MonadConc n => Way -> MemType -> Program pty n a -> n [(Either Condition a, Trace)]
+ Test.DejaFu.SCT: runSCT :: MonadDejaFu n => Way -> MemType -> Program pty n a -> n [(Either Condition a, Trace)]
- Test.DejaFu.SCT: runSCT' :: (MonadConc n, NFData a) => Way -> MemType -> Program pty n a -> n [(Either Condition a, Trace)]
+ Test.DejaFu.SCT: runSCT' :: (MonadDejaFu n, NFData a) => Way -> MemType -> Program pty n a -> n [(Either Condition a, Trace)]
- Test.DejaFu.SCT: runSCTWithSettings :: MonadConc n => Settings n a -> Program pty n a -> n [(Either Condition a, Trace)]
+ Test.DejaFu.SCT: runSCTWithSettings :: MonadDejaFu n => Settings n a -> Program pty n a -> n [(Either Condition a, Trace)]
- Test.DejaFu.SCT: runSCTWithSettings' :: (MonadConc n, NFData a) => Settings n a -> Program pty n a -> n [(Either Condition a, Trace)]
+ Test.DejaFu.SCT: runSCTWithSettings' :: (MonadDejaFu n, NFData a) => Settings n a -> Program pty n a -> n [(Either Condition a, Trace)]
- Test.DejaFu.SCT.Internal: replay :: MonadConc n => (forall x. Scheduler x -> x -> n (Either Condition a, x, Trace)) -> [(ThreadId, ThreadAction)] -> n (Either Condition a, [(ThreadId, ThreadAction)], Trace)
+ Test.DejaFu.SCT.Internal: replay :: MonadDejaFu n => (forall x. Scheduler x -> x -> n (Either Condition a, x, Trace)) -> [(ThreadId, ThreadAction)] -> n (Either Condition a, [(ThreadId, ThreadAction)], Trace)
- Test.DejaFu.SCT.Internal: sct :: (MonadConc n, HasCallStack) => Settings n a -> ([ThreadId] -> s) -> (s -> Maybe t) -> (ConcurrencyState -> (Scheduler g -> g -> n (Either Condition a, g, Trace)) -> s -> t -> n (s, Maybe (Either Condition a, Trace))) -> Program pty n a -> n [(Either Condition a, Trace)]
+ Test.DejaFu.SCT.Internal: sct :: (MonadDejaFu n, HasCallStack) => Settings n a -> ([ThreadId] -> s) -> (s -> Maybe t) -> (ConcurrencyState -> (Scheduler g -> g -> n (Either Condition a, g, Trace)) -> s -> t -> n (s, Maybe (Either Condition a, Trace))) -> Program pty n a -> n [(Either Condition a, Trace)]
- Test.DejaFu.SCT.Internal: sct' :: (MonadConc n, HasCallStack) => Settings n a -> ConcurrencyState -> s -> (s -> Maybe t) -> (s -> t -> n (s, Maybe (Either Condition a, Trace))) -> (forall x. Scheduler x -> x -> n (Either Condition a, x, Trace)) -> ThreadId -> IORefId -> n [(Either Condition a, Trace)]
+ Test.DejaFu.SCT.Internal: sct' :: (MonadDejaFu n, HasCallStack) => Settings n a -> ConcurrencyState -> s -> (s -> Maybe t) -> (s -> t -> n (s, Maybe (Either Condition a, Trace))) -> (forall x. Scheduler x -> x -> n (Either Condition a, x, Trace)) -> ThreadId -> IORefId -> n [(Either Condition a, Trace)]
- Test.DejaFu.SCT.Internal: simplifyExecution :: (MonadConc n, HasCallStack) => Settings n a -> ConcurrencyState -> (forall x. Scheduler x -> x -> n (Either Condition a, x, Trace)) -> ThreadId -> IORefId -> Either Condition a -> Trace -> n (Either Condition a, Trace)
+ Test.DejaFu.SCT.Internal: simplifyExecution :: (MonadDejaFu n, HasCallStack) => Settings n a -> ConcurrencyState -> (forall x. Scheduler x -> x -> n (Either Condition a, x, Trace)) -> ThreadId -> IORefId -> Either Condition a -> Trace -> n (Either Condition a, Trace)

Files

CHANGELOG.rst view
@@ -6,6 +6,67 @@  .. _PVP: https://pvp.haskell.org/ ++2.1.0.0 (2019-03-24)+--------------------++* Git: :tag:`dejafu-2.1.0.0`+* Hackage: :hackage:`dejafu-2.1.0.0`++Added+~~~~~++* The ``Test.DejaFu.Types.MonadDejaFu`` typeclass, containing the+  primitives needed to run a concurrent program.  There are instances+  for:+    * ``IO``, which is probably the ``MonadConc`` instance people used+      previously, so there is no breaking change there.+    * ``CatchT (ST t)``, meaning that concurrent programs can be run+      without ``IO`` once more.++* Thread action constructors for ``MonadConc``+  ``supportsBoundThreads`` function:+    * ``Test.DejaFu.Types.ThreadAction``, ``SupportsBoundThreads``+    * ``Test.DejaFu.Types.Lookahead``, ``WillSupportsBoundThreads``++Changed+~~~~~~~++* Many functions which had a ``MonadConc`` constraint now have a+  ``MonadDejaFu`` constraint:+    * In ``Test.DejaFu``+        * ``autocheck``+        * ``autocheckWay``+        * ``autocheckWithSettings``+        * ``dejafu``+        * ``dejafuWay``+        * ``dejafuWithSettings``+        * ``dejafus``+        * ``dejafusWay``+        * ``dejafusWithSettings``+        * ``runTest``+        * ``runTestWay``+        * ``runTestWithSettings``+    * In ``Test.DejaFu.Conc``+        * ``runConcurrent``+        * ``recordSnapshot``+        * ``runSnapshot``+    * In ``Test.DejaFu.SCT``+        * ``runSCT``+        * ``resultsSet``+        * ``runSCT'``+        * ``resultsSet'``+        * ``runSCTWithSettings``+        * ``resultsSetWithSettings``+        * ``runSCTWithSettings'``+        * ``resultsSetWithSettings'``++Miscellaneous+~~~~~~~~~~~~~++* The version bound on :hackage:`concurrency` is >=1.7 and <1.8.++ 2.0.0.1 (2019-03-14) -------------------- 
Test/DejaFu.hs view
@@ -313,18 +313,16 @@   , inspectTVar ) where -import           Control.Arrow            (first)-import           Control.DeepSeq          (NFData(..))-import           Control.Monad            (unless, when)-import           Control.Monad.Conc.Class (MonadConc)-import           Control.Monad.IO.Class   (MonadIO(..))-import           Data.Either              (isLeft)-import           Data.Function            (on)-import           Data.List                (intercalate, intersperse, partition)-import           Data.Maybe               (catMaybes, isJust, isNothing,-                                           mapMaybe)-import           Data.Profunctor          (Profunctor(..))-import           System.Environment       (lookupEnv)+import           Control.Arrow          (first)+import           Control.DeepSeq        (NFData(..))+import           Control.Monad          (unless, when)+import           Control.Monad.IO.Class (MonadIO(..))+import           Data.Either            (isLeft)+import           Data.Function          (on)+import           Data.List              (intercalate, intersperse, partition)+import           Data.Maybe             (catMaybes, isJust, isNothing, mapMaybe)+import           Data.Profunctor        (Profunctor(..))+import           System.Environment     (lookupEnv)  import           Test.DejaFu.Conc import           Test.DejaFu.Internal@@ -373,8 +371,8 @@ --     "world" S0----S2--S0-- -- False ----- @since 2.0.0.0-autocheck :: (MonadConc n, MonadIO n, Eq a, Show a)+-- @since 2.1.0.0+autocheck :: (MonadDejaFu n, MonadIO n, Eq a, Show a)   => Program pty n a   -- ^ The computation to test.   -> n Bool@@ -405,8 +403,8 @@ --     (True,False) S0---------S2----S1----S0--- -- False ----- @since 2.0.0.0-autocheckWay :: (MonadConc n, MonadIO n, Eq a, Show a)+-- @since 2.1.0.0+autocheckWay :: (MonadDejaFu n, MonadIO n, Eq a, Show a)   => Way   -- ^ How to run the concurrent program.   -> MemType@@ -440,8 +438,8 @@ --     (True,False) S0---------S2----S1----S0--- -- False ----- @since 2.0.0.0-autocheckWithSettings :: (MonadConc n, MonadIO n, Eq a, Show a)+-- @since 2.1.0.0+autocheckWithSettings :: (MonadDejaFu n, MonadIO n, Eq a, Show a)   => Settings n a   -- ^ The SCT settings.   -> Program pty n a@@ -466,8 +464,8 @@ --     "world" S0----S2--S0-- -- False ----- @since 2.0.0.0-dejafu :: (MonadConc n, MonadIO n, Show b)+-- @since 2.1.0.0+dejafu :: (MonadDejaFu n, MonadIO n, Show b)   => String   -- ^ The name of the test.   -> ProPredicate a b@@ -496,8 +494,8 @@ --     "world" S0----S2--S1-S0-- -- False ----- @since 2.0.0.0-dejafuWay :: (MonadConc n, MonadIO n, Show b)+-- @since 2.1.0.0+dejafuWay :: (MonadDejaFu n, MonadIO n, Show b)   => Way   -- ^ How to run the concurrent program.   -> MemType@@ -522,8 +520,8 @@ --     "world" S0----S2--S1-S0-- -- False ----- @since 2.0.0.0-dejafuWithSettings :: (MonadConc n, MonadIO n, Show b)+-- @since 2.1.0.0+dejafuWithSettings :: (MonadDejaFu n, MonadIO n, Show b)   => Settings n a   -- ^ The SCT settings.   -> String@@ -547,8 +545,8 @@ -- [pass] B -- False ----- @since 2.0.0.0-dejafus :: (MonadConc n, MonadIO n, Show b)+-- @since 2.1.0.0+dejafus :: (MonadDejaFu n, MonadIO n, Show b)   => [(String, ProPredicate a b)]   -- ^ The list of predicates (with names) to check.   -> Program pty n a@@ -569,8 +567,8 @@ -- [pass] B -- False ----- @since 2.0.0.0-dejafusWay :: (MonadConc n, MonadIO n, Show b)+-- @since 2.1.0.0+dejafusWay :: (MonadDejaFu n, MonadIO n, Show b)   => Way   -- ^ How to run the concurrent program.   -> MemType@@ -594,8 +592,8 @@ -- [pass] B -- False ----- @since 2.0.0.0-dejafusWithSettings :: (MonadConc n, MonadIO n, Show b)+-- @since 2.1.0.0+dejafusWithSettings :: (MonadDejaFu n, MonadIO n, Show b)   => Settings n a   -- ^ The SCT settings.   -> [(String, ProPredicate a b)]@@ -670,8 +668,8 @@ -- found, is unspecified and may change between releases.  This may -- affect which failing traces are reported, when there is a failure. ----- @since 2.0.0.0-runTest :: MonadConc n+-- @since 2.1.0.0+runTest :: MonadDejaFu n   => ProPredicate a b   -- ^ The predicate to check   -> Program pty n a@@ -686,8 +684,8 @@ -- found, is unspecified and may change between releases.  This may -- affect which failing traces are reported, when there is a failure. ----- @since 2.0.0.0-runTestWay :: MonadConc n+-- @since 2.1.0.0+runTestWay :: MonadDejaFu n   => Way   -- ^ How to run the concurrent program.   -> MemType@@ -705,8 +703,8 @@ -- found, is unspecified and may change between releases.  This may -- affect which failing traces are reported, when there is a failure. ----- @since 2.0.0.0-runTestWithSettings :: MonadConc n+-- @since 2.1.0.0+runTestWithSettings :: MonadDejaFu n   => Settings n a   -- ^ The SCT settings.   -> ProPredicate a b
Test/DejaFu/Conc/Internal.hs view
@@ -3,14 +3,15 @@ {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}  -- | -- Module      : Test.DejaFu.Conc.Internal--- Copyright   : (c) 2016--2018 Michael Walker+-- Copyright   : (c) 2016--2019 Michael Walker -- License     : MIT -- Maintainer  : Michael Walker <mike@barrucadu.co.uk> -- Stability   : experimental--- Portability : FlexibleContexts, LambdaCase, MultiWayIf, RankNTypes, RecordWildCards+-- Portability : FlexibleContexts, LambdaCase, MultiWayIf, RankNTypes, RecordWildCards, ScopedTypeVariables -- -- Concurrent monads with a fixed scheduler: internal types and -- functions. This module is NOT considered to form part of the public@@ -21,7 +22,6 @@                                                       MaskingState(..),                                                       toException) import qualified Control.Monad.Catch                 as E-import qualified Control.Monad.Conc.Class            as C import           Data.Foldable                       (foldrM) import           Data.Functor                        (void) import           Data.List                           (nub, partition, sortOn)@@ -50,7 +50,7 @@ -- | The result of running a concurrent program. data CResult n g a = CResult   { finalContext :: Context n g-  , finalRef :: C.IORef n (Maybe (Either Condition a))+  , finalRef :: Ref n (Maybe (Either Condition a))   , finalRestore :: Threads n -> n ()   -- ^ Meaningless if this result doesn't come from a snapshotting   -- execution.@@ -61,7 +61,7 @@ -- | Run a concurrent computation with a given 'Scheduler' and initial -- state, returning a Condition reason on error. Also returned is the -- final state of the scheduler, and an execution trace.-runConcurrency :: (C.MonadConc n, HasCallStack)+runConcurrency :: (MonadDejaFu n, HasCallStack)   => [Invariant n ()]   -> Bool   -> Scheduler g@@ -83,13 +83,15 @@                     }   (c, ref) <- runRefCont AStop (Just . Right) (runModelConc ma)   let threads0 = launch' Unmasked initialThread (const c) (cThreads ctx)-  threads <- (if C.rtsSupportsBoundThreads then makeBound initialThread else pure) threads0+  threads <- case forkBoundThread of+    Just fbt -> makeBound fbt initialThread threads0+    Nothing  -> pure threads0   res <- runThreads forSnapshot sched memtype ref ctx { cThreads = threads }   killAllThreads (finalContext res)   pure res  -- | Like 'runConcurrency' but starts from a snapshot.-runConcurrencyWithSnapshot :: (C.MonadConc n, HasCallStack)+runConcurrencyWithSnapshot :: (MonadDejaFu n, HasCallStack)   => Scheduler g   -> MemType   -> Context n g@@ -100,16 +102,19 @@   (c, ref) <- runRefCont AStop (Just . Right) (runModelConc ma)   let threads0 = M.delete initialThread (cThreads ctx)   let threads1 = launch' Unmasked initialThread (const c) threads0-  let boundThreads = M.filter (isJust . _bound) threads1-  threads2 <- (if C.rtsSupportsBoundThreads then makeBound initialThread else pure) threads1-  threads3 <- foldrM makeBound threads2 (M.keys boundThreads)-  restore threads3-  res <- runThreads False sched memtype ref ctx { cThreads = threads3 }+  threads <- case forkBoundThread of+    Just fbt -> do+      let boundThreads = M.filter (isJust . _bound) threads1+      threads' <- makeBound fbt initialThread threads1+      foldrM (makeBound fbt) threads' (M.keys boundThreads)+    Nothing -> pure threads1+  restore threads+  res <- runThreads False sched memtype ref ctx { cThreads = threads }   killAllThreads (finalContext res)   pure res  -- | Kill the remaining threads-killAllThreads :: (C.MonadConc n, HasCallStack) => Context n g -> n ()+killAllThreads :: (MonadDejaFu n, HasCallStack) => Context n g -> n () killAllThreads ctx =   let finalThreads = cThreads ctx   in mapM_ (`kill` finalThreads) (M.keys finalThreads)@@ -130,17 +135,17 @@   }  -- | Run a collection of threads, until there are no threads left.-runThreads :: (C.MonadConc n, HasCallStack)+runThreads :: (MonadDejaFu n, HasCallStack)   => Bool   -> Scheduler g   -> MemType-  -> C.IORef n (Maybe (Either Condition a))+  -> Ref n (Maybe (Either Condition a))   -> Context n g   -> n (CResult n g a) runThreads forSnapshot sched memtype ref = schedule (const $ pure ()) Seq.empty Nothing where   -- signal failure & terminate   die reason finalR finalT finalD finalC = do-    C.writeIORef ref (Just $ Left reason)+    writeRef ref (Just $ Left reason)     stop finalR finalT finalD finalC    -- just terminate; 'ref' must have been written to before calling@@ -256,7 +261,7 @@ -- -- Note: the returned snapshot action will definitely not do the right -- thing with relaxed memory.-stepThread :: (C.MonadConc n, HasCallStack)+stepThread :: forall n g. (MonadDejaFu n, HasCallStack)   => Bool   -- ^ Should we record a snapshot?   -> Bool@@ -282,12 +287,23 @@      )  -- start a new bound thread, assigning it the next 'ThreadId'-stepThread _ _ _ _ tid (AForkOS n a b) = \ctx@Context{..} -> do-  let (idSource', newtid) = nextTId n cIdSource-  let threads' = launch tid newtid a cThreads-  threads'' <- makeBound newtid threads'-  pure ( Succeeded ctx { cThreads = goto (b newtid) tid threads'', cIdSource = idSource' }-       , ForkOS newtid+stepThread _ _ _ _ tid (AForkOS n a b) = \ctx@Context{..} -> case forkBoundThread of+  Just fbt -> do+    let (idSource', newtid) = nextTId n cIdSource+    let threads' = launch tid newtid a cThreads+    threads'' <- makeBound fbt newtid threads'+    pure ( Succeeded ctx { cThreads = goto (b newtid) tid threads'', cIdSource = idSource' }+         , ForkOS newtid+         , const (pure ())+         )+  Nothing ->+    stepThrow Throw tid (MonadFailException "dejafu is running with bound threads disabled - do not use forkOS") ctx++-- check if we support bound threads+stepThread _ _ _ _ tid (ASupportsBoundThreads c) = \ctx@Context{..} -> do+  let sbt = isJust (forkBoundThread :: Maybe (n (BoundThread n ())))+  pure ( Succeeded ctx { cThreads = goto (c sbt) tid cThreads }+       , SupportsBoundThreads sbt        , const (pure ())        ) @@ -337,11 +353,11 @@ -- create a new @MVar@, using the next 'MVarId'. stepThread _ _ _ _ tid (ANewMVar n c) = \ctx@Context{..} -> do   let (idSource', newmvid) = nextMVId n cIdSource-  ref <- C.newIORef Nothing+  ref <- newRef Nothing   let mvar = ModelMVar newmvid ref   pure ( Succeeded ctx { cThreads = goto (c mvar) tid cThreads, cIdSource = idSource' }        , NewMVar newmvid-       , const (C.writeIORef ref Nothing)+       , const (writeRef ref Nothing)        )  -- put a value into a @MVar@, blocking the thread until it's empty.@@ -398,11 +414,11 @@ stepThread _ _ _ _  tid (ANewIORef n a c) = \ctx@Context{..} -> do   let (idSource', newiorid) = nextIORId n cIdSource   let val = (M.empty, 0, a)-  ioref <- C.newIORef val+  ioref <- newRef val   let ref = ModelIORef newiorid ioref   pure ( Succeeded ctx { cThreads = goto (c ref) tid cThreads, cIdSource = idSource' }        , NewIORef newiorid-       , const (C.writeIORef ioref val)+       , const (writeRef ioref val)        )  -- read from a @IORef@.@@ -609,7 +625,7 @@  -- | Handle an exception being thrown from an @AAtom@, @AThrow@, or -- @AThrowTo@.-stepThrow :: (C.MonadConc n, Exception e)+stepThrow :: (MonadDejaFu n, Exception e)   => (Bool -> ThreadAction)   -- ^ Action to include in the trace.   -> ThreadId@@ -641,7 +657,7 @@     some = toException e  -- | Helper for actions impose a write barrier.-synchronised :: C.MonadConc n+synchronised :: MonadDejaFu n   => (Context n g -> n x)   -- ^ Action to run after the write barrier.   -> Context n g@@ -674,7 +690,7 @@  -- | Check all active invariants, returning an arbitrary failure if -- multiple ones fail.-checkInvariants :: C.MonadConc n+checkInvariants :: MonadDejaFu n   => InvariantContext n   -> n (Either E.SomeException (InvariantContext n)) checkInvariants ic = go (icActive ic) >>= \case@@ -687,7 +703,7 @@     go [] = pure (Right [])  -- | Check an invariant.-checkInvariant :: C.MonadConc n+checkInvariant :: MonadDejaFu n   => Invariant n a   -> n (Either E.SomeException ([IORefId], [MVarId], [TVarId])) checkInvariant inv = doInvariant inv >>= \case@@ -695,13 +711,13 @@   (Left exc, _, _, _) -> pure (Left exc)  -- | Run an invariant (more primitive)-doInvariant :: C.MonadConc n+doInvariant :: MonadDejaFu n   => Invariant n a   -> n (Either E.SomeException a, [IORefId], [MVarId], [TVarId]) doInvariant inv = do     (c, ref) <- runRefCont IStop (Just . Right) (runInvariant inv)     (iorefs, mvars, tvars) <- go ref c [] [] []-    val <- C.readIORef ref+    val <- readRef ref     pure (efromJust val, nub iorefs, nub mvars, nub tvars)   where     go ref act iorefs mvars tvars = do@@ -715,21 +731,21 @@         Right Nothing ->           pure (newIORefs, newMVars, newTVars)         Left exc -> do-          C.writeIORef ref (Just (Left exc))+          writeRef ref (Just (Left exc))           pure (newIORefs, newMVars, newTVars)  -- | Run an invariant for one step-stepInvariant :: C.MonadConc n+stepInvariant :: MonadDejaFu n   => IAction n   -> n (Either E.SomeException (Maybe (IAction n)), [IORefId], [MVarId], [TVarId]) stepInvariant (IInspectIORef ioref@ModelIORef{..} k) = do   a <- readIORefGlobal ioref   pure (Right (Just (k a)), [iorefId], [], []) stepInvariant (IInspectMVar ModelMVar{..} k) = do-  a <- C.readIORef mvarRef+  a <- readRef mvarRef   pure (Right (Just (k a)), [], [mvarId], []) stepInvariant (IInspectTVar ModelTVar{..} k) = do-  a <- C.readIORef tvarRef+  a <- readRef tvarRef   pure (Right (Just (k a)), [], [], [tvarId]) stepInvariant (ICatch h nx k) = doInvariant nx >>= \case   (Right a, iorefs, mvars, tvars) ->
Test/DejaFu/Conc/Internal/Common.hs view
@@ -17,7 +17,6 @@  import           Control.Exception             (Exception, MaskingState(..)) import           Control.Monad.Catch           (MonadCatch(..), MonadThrow(..))-import qualified Control.Monad.Conc.Class      as C import qualified Control.Monad.Fail            as Fail import           Data.Map.Strict               (Map) @@ -106,7 +105,7 @@ -- @Maybe@ value. data ModelMVar n a = ModelMVar   { mvarId  :: MVarId-  , mvarRef :: C.IORef n (Maybe a)+  , mvarRef :: Ref n (Maybe a)   }  -- | A @IORef@ is modelled as a unique ID and a reference holding@@ -114,7 +113,7 @@ -- committed value. data ModelIORef n a = ModelIORef   { iorefId  :: IORefId-  , iorefRef :: C.IORef n (Map ThreadId a, Integer, a)+  , iorefRef :: Ref n (Map ThreadId a, Integer, a)   }  -- | A @Ticket@ is modelled as the ID of the @ModelIORef@ it came from,@@ -136,6 +135,8 @@ data Action n =     AFork   String ((forall b. ModelConc n b -> ModelConc n b) -> Action n) (ThreadId -> Action n)   | AForkOS String ((forall b. ModelConc n b -> ModelConc n b) -> Action n) (ThreadId -> Action n)++  | ASupportsBoundThreads (Bool -> Action n)   | AIsBound (Bool -> Action n)   | AMyTId (ThreadId -> Action n) @@ -182,6 +183,7 @@ lookahead :: Action n -> Lookahead lookahead (AFork _ _ _) = WillFork lookahead (AForkOS _ _ _) = WillForkOS+lookahead (ASupportsBoundThreads _) = WillSupportsBoundThreads lookahead (AIsBound _) = WillIsCurrentThreadBound lookahead (AMyTId _) = WillMyThreadId lookahead (AGetNumCapabilities _) = WillGetNumCapabilities
Test/DejaFu/Conc/Internal/Memory.hs view
@@ -6,7 +6,7 @@  -- | -- Module      : Test.DejaFu.Conc.Internal.Memory--- Copyright   : (c) 2016--2018 Michael Walker+-- Copyright   : (c) 2016--2019 Michael Walker -- License     : MIT -- Maintainer  : Michael Walker <mike@barrucadu.co.uk> -- Stability   : experimental@@ -25,7 +25,6 @@ -- Memory Models/, N. Zhang, M. Kusano, and C. Wang (2015). module Test.DejaFu.Conc.Internal.Memory where -import qualified Control.Monad.Conc.Class            as C import           Data.Map.Strict                     (Map) import qualified Data.Map.Strict                     as M import           Data.Maybe                          (maybeToList)@@ -61,20 +60,20 @@ emptyBuffer = WriteBuffer M.empty  -- | Add a new write to the end of a buffer.-bufferWrite :: C.MonadConc n => WriteBuffer n -> (ThreadId, Maybe IORefId) -> ModelIORef n a -> a -> n (WriteBuffer n)+bufferWrite :: MonadDejaFu n => WriteBuffer n -> (ThreadId, Maybe IORefId) -> ModelIORef n a -> a -> n (WriteBuffer n) bufferWrite (WriteBuffer wb) k@(tid, _) ref@ModelIORef{..} new = do   -- Construct the new write buffer   let write = singleton $ BufferedWrite tid ref new   let buffer' = M.insertWith (flip (><)) k write wb    -- Write the thread-local value to the @IORef@'s update map.-  (locals, count, def) <- C.readIORef iorefRef-  C.writeIORef iorefRef (M.insert tid new locals, count, def)+  (locals, count, def) <- readRef iorefRef+  writeRef iorefRef (M.insert tid new locals, count, def)    pure (WriteBuffer buffer')  -- | Commit the write at the head of a buffer.-commitWrite :: C.MonadConc n => WriteBuffer n -> (ThreadId, Maybe IORefId) -> n (WriteBuffer n)+commitWrite :: MonadDejaFu n => WriteBuffer n -> (ThreadId, Maybe IORefId) -> n (WriteBuffer n) commitWrite w@(WriteBuffer wb) k = case maybe EmptyL viewl $ M.lookup k wb of   BufferedWrite _ ref a :< rest -> do     _ <- writeImmediate ref a@@ -83,21 +82,21 @@  -- | Read from a @IORef@, returning a newer thread-local non-committed -- write if there is one.-readIORef :: C.MonadConc n => ModelIORef n a -> ThreadId -> n a+readIORef :: MonadDejaFu n => ModelIORef n a -> ThreadId -> n a readIORef ref tid = do   (val, _) <- readIORefPrim ref tid   pure val  -- | Read from a @IORef@, returning a @Ticket@ representing the current -- view of the thread.-readForTicket :: C.MonadConc n => ModelIORef n a -> ThreadId -> n (ModelTicket a)+readForTicket :: MonadDejaFu n => ModelIORef n a -> ThreadId -> n (ModelTicket a) readForTicket ref@ModelIORef{..} tid = do   (val, count) <- readIORefPrim ref tid   pure (ModelTicket iorefId count val)  -- | Perform a compare-and-swap on a @IORef@ if the ticket is still -- valid. This is strict in the \"new\" value argument.-casIORef :: C.MonadConc n => ModelIORef n a -> ThreadId -> ModelTicket a -> a -> n (Bool, ModelTicket a, n ())+casIORef :: MonadDejaFu n => ModelIORef n a -> ThreadId -> ModelTicket a -> a -> n (Bool, ModelTicket a, n ()) casIORef ref tid (ModelTicket _ cc _) !new = do   tick'@(ModelTicket _ cc' _) <- readForTicket ref tid @@ -109,28 +108,28 @@   else pure (False, tick', pure ())  -- | Read the local state of a @IORef@.-readIORefPrim :: C.MonadConc n => ModelIORef n a -> ThreadId -> n (a, Integer)+readIORefPrim :: MonadDejaFu n => ModelIORef n a -> ThreadId -> n (a, Integer) readIORefPrim ModelIORef{..} tid = do-  (vals, count, def) <- C.readIORef iorefRef+  (vals, count, def) <- readRef iorefRef   pure (M.findWithDefault def tid vals, count)  -- | Read the global state of a @IORef@.-readIORefGlobal :: C.MonadConc n => ModelIORef n a -> n a+readIORefGlobal :: MonadDejaFu n => ModelIORef n a -> n a readIORefGlobal ModelIORef{..} = do-  (_, _, def) <- C.readIORef iorefRef+  (_, _, def) <- readRef iorefRef   pure def  -- | Write and commit to a @IORef@ immediately, clearing the update map -- and incrementing the write count.-writeImmediate :: C.MonadConc n => ModelIORef n a -> a -> n (n ())+writeImmediate :: MonadDejaFu n => ModelIORef n a -> a -> n (n ()) writeImmediate ModelIORef{..} a = do-  (_, count, _) <- C.readIORef iorefRef-  let effect = C.writeIORef iorefRef (M.empty, count + 1, a)+  (_, count, _) <- readRef iorefRef+  let effect = writeRef iorefRef (M.empty, count + 1, a)   effect   pure effect  -- | Flush all writes in the buffer.-writeBarrier :: C.MonadConc n => WriteBuffer n -> n ()+writeBarrier :: MonadDejaFu n => WriteBuffer n -> n () writeBarrier (WriteBuffer wb) = mapM_ flush $ M.elems wb where   flush = mapM_ $ \(BufferedWrite _ ref a) -> writeImmediate ref a @@ -162,7 +161,7 @@ data Emptying = Emptying | NonEmptying  -- | Put into a @MVar@, blocking if full.-putIntoMVar :: C.MonadConc n+putIntoMVar :: MonadDejaFu n   => ModelMVar n a   -> a   -> Action n@@ -172,7 +171,7 @@ putIntoMVar cvar a c = mutMVar Blocking cvar a (const c)  -- | Try to put into a @MVar@, not blocking if full.-tryPutIntoMVar :: C.MonadConc n+tryPutIntoMVar :: MonadDejaFu n   => ModelMVar n a   -> a   -> (Bool -> Action n)@@ -182,7 +181,7 @@ tryPutIntoMVar = mutMVar NonBlocking  -- | Read from a @MVar@, blocking if empty.-readFromMVar :: (C.MonadConc n, HasCallStack)+readFromMVar :: (MonadDejaFu n, HasCallStack)   => ModelMVar n a   -> (a -> Action n)   -> ThreadId@@ -191,7 +190,7 @@ readFromMVar cvar c = seeMVar NonEmptying Blocking cvar (c . efromJust)  -- | Try to read from a @MVar@, not blocking if empty.-tryReadFromMVar :: C.MonadConc n+tryReadFromMVar :: MonadDejaFu n   => ModelMVar n a   -> (Maybe a -> Action n)   -> ThreadId@@ -200,7 +199,7 @@ tryReadFromMVar = seeMVar NonEmptying NonBlocking  -- | Take from a @MVar@, blocking if empty.-takeFromMVar :: (C.MonadConc n, HasCallStack)+takeFromMVar :: (MonadDejaFu n, HasCallStack)   => ModelMVar n a   -> (a -> Action n)   -> ThreadId@@ -209,7 +208,7 @@ takeFromMVar cvar c = seeMVar Emptying Blocking cvar (c . efromJust)  -- | Try to take from a @MVar@, not blocking if empty.-tryTakeFromMVar :: C.MonadConc n+tryTakeFromMVar :: MonadDejaFu n   => ModelMVar n a   -> (Maybe a -> Action n)   -> ThreadId@@ -218,7 +217,7 @@ tryTakeFromMVar = seeMVar Emptying NonBlocking  -- | Mutate a @MVar@, in either a blocking or nonblocking way.-mutMVar :: C.MonadConc n+mutMVar :: MonadDejaFu n   => Blocking   -> ModelMVar n a   -> a@@ -226,7 +225,7 @@   -> ThreadId   -> Threads n   -> n (Bool, Threads n, [ThreadId], n ())-mutMVar blocking ModelMVar{..} a c threadid threads = C.readIORef mvarRef >>= \case+mutMVar blocking ModelMVar{..} a c threadid threads = readRef mvarRef >>= \case   Just _ -> case blocking of     Blocking ->       let threads' = block (OnMVarEmpty mvarId) threadid threads@@ -234,14 +233,14 @@     NonBlocking ->       pure (False, goto (c False) threadid threads, [], pure ())   Nothing -> do-    let effect = C.writeIORef mvarRef $ Just a+    let effect = writeRef mvarRef $ Just a     let (threads', woken) = wake (OnMVarFull mvarId) threads     effect     pure (True, goto (c True) threadid threads', woken, effect)  -- | Read a @MVar@, in either a blocking or nonblocking -- way.-seeMVar :: C.MonadConc n+seeMVar :: MonadDejaFu n   => Emptying   -> Blocking   -> ModelMVar n a@@ -249,10 +248,10 @@   -> ThreadId   -> Threads n   -> n (Bool, Threads n, [ThreadId], n ())-seeMVar emptying blocking ModelMVar{..} c threadid threads = C.readIORef mvarRef >>= \case+seeMVar emptying blocking ModelMVar{..} c threadid threads = readRef mvarRef >>= \case   val@(Just _) -> do     let effect = case emptying of-          Emptying -> C.writeIORef mvarRef Nothing+          Emptying -> writeRef mvarRef Nothing           NonEmptying -> pure ()     let (threads', woken) = wake (OnMVarEmpty mvarId) threads     effect
Test/DejaFu/Conc/Internal/Program.hs view
@@ -92,11 +92,9 @@    forkWithUnmaskN   n ma = ModelConc (AFork n (\umask -> runModelConc (ma umask) (\_ -> AStop (pure ()))))   forkOnWithUnmaskN n _  = C.forkWithUnmaskN n-  forkOSWithUnmaskN n ma-    | C.rtsSupportsBoundThreads =-      ModelConc (AForkOS n (\umask -> runModelConc (ma umask) (\_ -> AStop (pure ()))))-    | otherwise = fail "RTS doesn't support multiple OS threads (use ghc -threaded when linking)"+  forkOSWithUnmaskN n ma = ModelConc (AForkOS n (\umask -> runModelConc (ma umask) (\_ -> AStop (pure ())))) +  supportsBoundThreads = ModelConc ASupportsBoundThreads   isCurrentThreadBound = ModelConc AIsBound    -- This implementation lies and returns 2 until a value is set. This@@ -172,8 +170,8 @@ -- nonexistent thread. In either of those cases, the computation will -- be halted. ----- @since 2.0.0.0-runConcurrent :: C.MonadConc n+-- @since 2.1.0.0+runConcurrent :: MonadDejaFu n   => Scheduler s   -> MemType   -> s@@ -181,7 +179,7 @@   -> n (Either Condition a, s, Trace) runConcurrent sched memtype s ma@(ModelConc _) = do   res <- runConcurrency [] False sched memtype s initialIdSource 2 ma-  out <- efromJust <$> C.readIORef (finalRef res)+  out <- efromJust <$> readRef (finalRef res)   pure ( out        , cSchedState (finalContext res)        , F.toList (finalTrace res)@@ -252,9 +250,9 @@ --   (liftIO . readIORef) -- @ ----- @since 2.0.0.0+-- @since 2.1.0.0 recordSnapshot-  :: C.MonadConc n+  :: MonadDejaFu n   => Program pty n a   -> n (Maybe (Either Condition (Snapshot pty n a), Trace)) recordSnapshot ModelConc{..} = pure Nothing@@ -267,9 +265,9 @@  -- | Runs a program with snapshotted setup to completion. ----- @since 2.0.0.0+-- @since 2.1.0.0 runSnapshot-  :: C.MonadConc n+  :: MonadDejaFu n   => Scheduler s   -> MemType   -> s@@ -278,7 +276,7 @@ runSnapshot sched memtype s (WS SimpleSnapshot{..}) = do   let context = fromSnapContext s snapContext   CResult{..} <- runConcurrencyWithSnapshot sched memtype context snapRestore snapNext-  out <- efromJust <$> C.readIORef finalRef+  out <- efromJust <$> readRef finalRef   pure ( out        , cSchedState finalContext        , F.toList finalTrace@@ -287,9 +285,9 @@   let context = fromSnapContext s snapContext   intermediateResult <- runConcurrencyWithSnapshot sched memtype context snapRestore snapNext   let idsrc = cIdSource (finalContext intermediateResult)-  out1 <- efromJust <$> C.readIORef (finalRef intermediateResult)+  out1 <- efromJust <$> readRef (finalRef intermediateResult)   teardownResult <- simpleRunConcurrency False idsrc (teardown out1)-  out2 <- efromJust <$> C.readIORef (finalRef teardownResult)+  out2 <- efromJust <$> readRef (finalRef teardownResult)   pure ( out2        , cSchedState (finalContext intermediateResult)        , F.toList (finalTrace intermediateResult)@@ -328,7 +326,7 @@ -- | 'recordSnapshot' implemented generically. -- -- Throws an error if the snapshot could not be produced.-defaultRecordSnapshot :: C.MonadConc n+defaultRecordSnapshot :: MonadDejaFu n   => (SimpleSnapshot n a -> x -> snap)   -> ModelConc n x   -> (x -> ModelConc n a)@@ -336,7 +334,7 @@ defaultRecordSnapshot mkSnapshot setup program = do   CResult{..} <- simpleRunConcurrency True initialIdSource setup   let trc = F.toList finalTrace-  out <- C.readIORef finalRef+  out <- readRef finalRef   pure . Just $ case out of     Just (Right a) ->       let snap = mkSnapshot (SimpleSnapshot finalContext finalRestore (program a)) a@@ -351,7 +349,7 @@  -- | Run a concurrent program with a deterministic scheduler in -- snapshotting or non-snapshotting mode.-simpleRunConcurrency ::(C.MonadConc n, HasCallStack)+simpleRunConcurrency ::(MonadDejaFu n, HasCallStack)   => Bool   -> IdSource   -> ModelConc n a
Test/DejaFu/Conc/Internal/STM.hs view
@@ -7,7 +7,7 @@  -- | -- Module      : Test.DejaFu.Conc.Internal.STM--- Copyright   : (c) 2017--2018 Michael Walker+-- Copyright   : (c) 2017--2019 Michael Walker -- License     : MIT -- Maintainer  : Michael Walker <mike@barrucadu.co.uk> -- Stability   : experimental@@ -18,15 +18,14 @@ -- of this library. module Test.DejaFu.Conc.Internal.STM where -import           Control.Applicative      (Alternative(..))-import           Control.Exception        (Exception, SomeException,-                                           fromException, toException)-import           Control.Monad            (MonadPlus(..))-import           Control.Monad.Catch      (MonadCatch(..), MonadThrow(..))-import qualified Control.Monad.Conc.Class as C-import qualified Control.Monad.Fail       as Fail-import qualified Control.Monad.STM.Class  as S-import           Data.List                (nub)+import           Control.Applicative     (Alternative(..))+import           Control.Exception       (Exception, SomeException,+                                          fromException, toException)+import           Control.Monad           (MonadPlus(..))+import           Control.Monad.Catch     (MonadCatch(..), MonadThrow(..))+import qualified Control.Monad.Fail      as Fail+import qualified Control.Monad.STM.Class as S+import           Data.List               (nub)  import           Test.DejaFu.Internal import           Test.DejaFu.Types@@ -100,7 +99,7 @@ -- value. data ModelTVar n a = ModelTVar   { tvarId  :: TVarId-  , tvarRef :: C.IORef n a+  , tvarRef :: Ref n a   }  --------------------------------------------------------------------------------@@ -126,7 +125,7 @@  -- | Run a transaction, returning the result and new initial 'TVarId'. -- If the transaction failed, any effects are undone.-runTransaction :: C.MonadConc n+runTransaction :: MonadDejaFu n   => ModelSTM n a   -> IdSource   -> n (Result a, IdSource, [TAction])@@ -138,14 +137,14 @@ -- -- If the transaction fails, its effects will automatically be undone, -- so the undo action returned will be @pure ()@.-doTransaction :: C.MonadConc n+doTransaction :: MonadDejaFu n   => ModelSTM n a   -> IdSource   -> n (Result a, n (), IdSource, [TAction]) doTransaction ma idsource = do   (c, ref) <- runRefCont SStop (Just . Right) (runModelSTM ma)   (idsource', undo, readen, written, trace) <- go ref c (pure ()) idsource [] [] []-  res <- C.readIORef ref+  res <- readRef ref    case res of     Just (Right val) -> pure (Success (nub readen) (nub written) val, undo, idsource', reverse trace)@@ -166,15 +165,15 @@       case tact of         TStop  -> pure (newIDSource, newUndo, newReaden, newWritten, TStop:newSofar)         TRetry -> do-          C.writeIORef ref Nothing+          writeRef ref Nothing           pure (newIDSource, newUndo, newReaden, newWritten, TRetry:newSofar)         TThrow -> do-          C.writeIORef ref (Just . Left $ case act of SThrow e -> toException e; _ -> undefined)+          writeRef ref (Just . Left $ case act of SThrow e -> toException e; _ -> undefined)           pure (newIDSource, newUndo, newReaden, newWritten, TThrow:newSofar)         _ -> go ref newAct newUndo newIDSource newReaden newWritten newSofar  -- | Run a transaction for one step.-stepTrans :: C.MonadConc n+stepTrans :: MonadDejaFu n   => STMAction n   -> IdSource   -> n (STMAction n, n (), IdSource, [TVarId], [TVarId], TAction)@@ -199,17 +198,17 @@         Nothing   -> pure (SThrow exc, nothing, idsource, [], [], TCatch trace Nothing))      stepRead ModelTVar{..} c = do-      val <- C.readIORef tvarRef+      val <- readRef tvarRef       pure (c val, nothing, idsource, [tvarId], [], TRead tvarId)      stepWrite ModelTVar{..} a c = do-      old <- C.readIORef tvarRef-      C.writeIORef tvarRef a-      pure (c, C.writeIORef tvarRef old, idsource, [], [tvarId], TWrite tvarId)+      old <- readRef tvarRef+      writeRef tvarRef a+      pure (c, writeRef tvarRef old, idsource, [], [tvarId], TWrite tvarId)      stepNew n a c = do       let (idsource', tvid) = nextTVId n idsource-      ref <- C.newIORef a+      ref <- newRef a       let tvar = ModelTVar tvid ref       pure (c tvar, nothing, idsource', [], [tvid], TNew tvid) 
Test/DejaFu/Conc/Internal/Threading.hs view
@@ -4,7 +4,7 @@  -- | -- Module      : Test.DejaFu.Conc.Internal.Threading--- Copyright   : (c) 2016--2018 Michael Walker+-- Copyright   : (c) 2016--2019 Michael Walker -- License     : MIT -- Maintainer  : Michael Walker <mike@barrucadu.co.uk> -- Stability   : experimental@@ -16,8 +16,6 @@  import           Control.Exception                (Exception, MaskingState(..),                                                    SomeException, fromException)-import           Control.Monad                    (forever)-import qualified Control.Monad.Conc.Class         as C import           Data.List                        (intersect) import           Data.Map.Strict                  (Map) import qualified Data.Map.Strict                  as M@@ -44,20 +42,10 @@   -- ^ Stack of exception handlers   , _masking      :: MaskingState   -- ^ The exception masking state.-  , _bound        :: Maybe (BoundThread n)+  , _bound        :: Maybe (BoundThread n (Action n))   -- ^ State for the associated bound thread, if it exists.   } --- | The state of a bound thread.-data BoundThread n = BoundThread-  { _runboundIO :: C.MVar n (n (Action n))-  -- ^ Run an @IO@ action in the bound thread by writing to this.-  , _getboundIO :: C.MVar n (Action n)-  -- ^ Get the result of the above by reading from this.-  , _boundTId   :: C.ThreadId n-  -- ^ Thread ID-  }- -- | Construct a thread with just one action mkthread :: Action n -> Thread n mkthread c = Thread c Nothing [] Unmasked Nothing@@ -167,33 +155,24 @@ -- ** Bound threads  -- | Turn a thread into a bound thread.-makeBound :: (C.MonadConc n, HasCallStack) => ThreadId -> Threads n -> n (Threads n)-makeBound tid threads = do-    runboundIO <- C.newEmptyMVar-    getboundIO <- C.newEmptyMVar-    btid <- C.forkOSN ("bound worker for '" ++ show tid ++ "'") (go runboundIO getboundIO)-    let bt = BoundThread runboundIO getboundIO btid-    pure (eadjust (\t -> t { _bound = Just bt }) tid threads)-  where-    go runboundIO getboundIO = forever $ do-      na <- C.takeMVar runboundIO-      C.putMVar getboundIO =<< na+makeBound :: (MonadDejaFu n, HasCallStack)+  => n (BoundThread n (Action n)) -> ThreadId -> Threads n -> n (Threads n)+makeBound fbt tid threads = do+  bt <- fbt+  pure (eadjust (\t -> t { _bound = Just bt }) tid threads)  -- | Kill a thread and remove it from the thread map. -- -- If the thread is bound, the worker thread is cleaned up.-kill :: (C.MonadConc n, HasCallStack) => ThreadId -> Threads n -> n (Threads n)+kill :: (MonadDejaFu n, HasCallStack) => ThreadId -> Threads n -> n (Threads n) kill tid threads = do   let thread = elookup tid threads-  maybe (pure ()) (C.killThread . _boundTId) (_bound thread)+  maybe (pure ()) killBoundThread (_bound thread)   pure (M.delete tid threads)- -- | Run an action. -- -- If the thread is bound, the action is run in the worker thread.-runLiftedAct :: C.MonadConc n => ThreadId -> Threads n -> n (Action n) -> n (Action n)+runLiftedAct :: MonadDejaFu n => ThreadId -> Threads n -> n (Action n) -> n (Action n) runLiftedAct tid threads ma = case _bound =<< M.lookup tid threads of-  Just bt -> do-    C.putMVar (_runboundIO bt) ma-    C.takeMVar (_getboundIO bt)+  Just bt -> runInBoundThread bt ma   Nothing -> ma
Test/DejaFu/Internal.hs view
@@ -17,18 +17,17 @@ -- library. module Test.DejaFu.Internal where -import           Control.DeepSeq          (NFData(..))-import           Control.Exception        (MaskingState(..))-import qualified Control.Monad.Conc.Class as C-import           Data.List.NonEmpty       (NonEmpty(..))-import           Data.Map.Strict          (Map)-import qualified Data.Map.Strict          as M-import           Data.Maybe               (fromMaybe)-import           Data.Set                 (Set)-import qualified Data.Set                 as S-import           GHC.Generics             (Generic)-import           GHC.Stack                (HasCallStack, withFrozenCallStack)-import           System.Random            (RandomGen)+import           Control.DeepSeq    (NFData(..))+import           Control.Exception  (MaskingState(..))+import           Data.List.NonEmpty (NonEmpty(..))+import           Data.Map.Strict    (Map)+import qualified Data.Map.Strict    as M+import           Data.Maybe         (fromMaybe)+import           Data.Set           (Set)+import qualified Data.Set           as S+import           GHC.Generics       (Generic)+import           GHC.Stack          (HasCallStack, withFrozenCallStack)+import           System.Random      (RandomGen)  import           Test.DejaFu.Types @@ -165,6 +164,7 @@ rewind :: ThreadAction -> Lookahead rewind (Fork _) = WillFork rewind (ForkOS _) = WillForkOS+rewind (SupportsBoundThreads _) = WillSupportsBoundThreads rewind (IsCurrentThreadBound _) = WillIsCurrentThreadBound rewind MyThreadId = WillMyThreadId rewind (GetNumCapabilities _) = WillGetNumCapabilities@@ -449,12 +449,12 @@ -- | Run with a continuation that writes its value into a reference, -- returning the computation and the reference.  Using the reference -- is non-blocking, it is up to you to ensure you wait sufficiently.-runRefCont :: C.MonadConc n+runRefCont :: MonadDejaFu n   => (n () -> x)   -> (a -> Maybe b)   -> ((a -> x) -> x)-  -> n (x, C.IORef n (Maybe b))+  -> n (x, Ref n (Maybe b)) runRefCont act f k = do-  ref <- C.newIORef Nothing-  let c = k (act . C.writeIORef ref . f)+  ref <- newRef Nothing+  let c = k (act . writeRef ref . f)   pure (c, ref)
Test/DejaFu/SCT.hs view
@@ -1,5 +1,3 @@-{-# OPTIONS_GHC -Wno-deprecations #-}- -- | -- Module      : Test.DejaFu.SCT -- Copyright   : (c) 2015--2019 Michael Walker@@ -26,7 +24,6 @@  import           Control.Applicative               ((<|>)) import           Control.DeepSeq                   (NFData(..), force)-import           Control.Monad.Conc.Class          (MonadConc) import           Data.List                         (foldl') import qualified Data.Map.Strict                   as M import           Data.Maybe                        (fromMaybe)@@ -51,8 +48,8 @@ -- The exact executions tried, and the order in which results are -- found, is unspecified and may change between releases. ----- @since 2.0.0.0-runSCT :: MonadConc n+-- @since 2.1.0.0+runSCT :: MonadDejaFu n   => Way   -- ^ How to run the concurrent program.   -> MemType@@ -64,8 +61,8 @@  -- | Return the set of results of a concurrent program. ----- @since 2.0.0.0-resultsSet :: (MonadConc n, Ord a)+-- @since 2.1.0.0+resultsSet :: (MonadDejaFu n, Ord a)   => Way   -- ^ How to run the concurrent program.   -> MemType@@ -83,8 +80,8 @@ -- The exact executions tried, and the order in which results are -- found, is unspecified and may change between releases. ----- @since 2.0.0.0-runSCT' :: (MonadConc n, NFData a)+-- @since 2.1.0.0+runSCT' :: (MonadDejaFu n, NFData a)   => Way   -- ^ How to run the concurrent program.   -> MemType@@ -99,8 +96,8 @@ -- Demanding the result of this will force it to normal form, which -- may be more efficient in some situations. ----- @since 2.0.0.0-resultsSet' :: (MonadConc n, Ord a, NFData a)+-- @since 2.1.0.0+resultsSet' :: (MonadDejaFu n, Ord a, NFData a)   => Way   -- ^ How to run the concurrent program.   -> MemType@@ -118,8 +115,8 @@ -- The exact executions tried, and the order in which results are -- found, is unspecified and may change between releases. ----- @since 2.0.0.0-runSCTWithSettings :: MonadConc n+-- @since 2.1.0.0+runSCTWithSettings :: MonadDejaFu n   => Settings n a   -- ^ The SCT settings.   -> Program pty n a@@ -159,8 +156,8 @@  -- | A variant of 'resultsSet' which takes a 'Settings' record. ----- @since 2.0.0.0-resultsSetWithSettings :: (MonadConc n, Ord a)+-- @since 2.1.0.0+resultsSetWithSettings :: (MonadDejaFu n, Ord a)   => Settings n a   -- ^ The SCT settings.   -> Program pty n a@@ -178,8 +175,8 @@ -- The exact executions tried, and the order in which results are -- found, is unspecified and may change between releases. ----- @since 2.0.0.0-runSCTWithSettings' :: (MonadConc n, NFData a)+-- @since 2.1.0.0+runSCTWithSettings' :: (MonadDejaFu n, NFData a)   => Settings n a   -- ^ The SCT settings.   -> Program pty n a@@ -194,8 +191,8 @@ -- Demanding the result of this will force it to normal form, which -- may be more efficient in some situations. ----- @since 2.0.0.0-resultsSetWithSettings' :: (MonadConc n, Ord a, NFData a)+-- @since 2.1.0.0+resultsSetWithSettings' :: (MonadDejaFu n, Ord a, NFData a)   => Settings n a   -- ^ The SCT settings.   -> Program pty n a
Test/DejaFu/SCT/Internal.hs view
@@ -5,7 +5,7 @@  -- | -- Module      : Test.DejaFu.SCT.Internal--- Copyright   : (c) 2018 Michael Walker+-- Copyright   : (c) 2018--2019 Michael Walker -- License     : MIT -- Maintainer  : Michael Walker <mike@barrucadu.co.uk> -- Stability   : experimental@@ -15,7 +15,6 @@ -- considered to form part of the public interface of this library. module Test.DejaFu.SCT.Internal where -import           Control.Monad.Conc.Class          (MonadConc) import           Data.Coerce                       (Coercible, coerce) import qualified Data.IntMap.Strict                as I import           Data.List                         (find, mapAccumL)@@ -36,7 +35,7 @@ -- * Exploration  -- | General-purpose SCT function.-sct :: (MonadConc n, HasCallStack)+sct :: (MonadDejaFu n, HasCallStack)   => Settings n a   -- ^ The SCT settings ('Way' is ignored)   -> ([ThreadId] -> s)@@ -79,7 +78,7 @@     runSnap snap sched s = runSnapshot sched (_memtype settings) s snap  -- | Like 'sct' but given a function to run the computation.-sct' :: (MonadConc n, HasCallStack)+sct' :: (MonadDejaFu n, HasCallStack)   => Settings n a   -- ^ The SCT settings ('Way' is ignored)   -> ConcurrencyState@@ -150,7 +149,7 @@ -- Unlike shrinking in randomised property-testing tools like -- QuickCheck or Hedgehog, we only run the test case /once/, at the -- end, rather than after every simplification step.-simplifyExecution :: (MonadConc n, HasCallStack)+simplifyExecution :: (MonadDejaFu n, HasCallStack)   => Settings n a   -- ^ The SCT settings ('Way' is ignored)   -> ConcurrencyState@@ -190,7 +189,7 @@     p = either show debugShow  -- | Replay an execution.-replay :: MonadConc n+replay :: MonadDejaFu n   => (forall x. Scheduler x -> x -> n (Either Condition a, x, Trace))   -- ^ Run the computation   -> [(ThreadId, ThreadAction)]
Test/DejaFu/Types.hs view
@@ -1,7 +1,10 @@ {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}  -- | -- Module      : Test.DejaFu.Types@@ -9,26 +12,141 @@ -- License     : MIT -- Maintainer  : Michael Walker <mike@barrucadu.co.uk> -- Stability   : experimental--- Portability : DeriveGeneric, GeneralizedNewtypeDeriving, LambdaCase, StandaloneDeriving+-- Portability : DeriveGeneric, FlexibleInstances, GeneralizedNewtypeDeriving, LambdaCase, RankNTypes, StandaloneDeriving, TypeFamilies -- -- Common types and functions used throughout DejaFu. module Test.DejaFu.Types where +import qualified Control.Concurrent                   as IO import           Control.DeepSeq                      (NFData(..)) import           Control.Exception                    (Exception(..),                                                        MaskingState(..),                                                        SomeException)+import           Control.Monad                        (forever)+import           Control.Monad.Catch                  (MonadThrow)+import           Control.Monad.Catch.Pure             (CatchT)+import qualified Control.Monad.ST                     as ST+import           Control.Monad.Trans.Class            (lift) import           Data.Function                        (on) import           Data.Functor.Contravariant           (Contravariant(..)) import           Data.Functor.Contravariant.Divisible (Divisible(..))+import qualified Data.IORef                           as IO import           Data.Map.Strict                      (Map) import qualified Data.Map.Strict                      as M import           Data.Semigroup                       (Semigroup(..)) import           Data.Set                             (Set) import qualified Data.Set                             as S-import           GHC.Generics                         (Generic)+import qualified Data.STRef                           as ST+import           GHC.Generics                         (Generic, V1)  -------------------------------------------------------------------------------+-- * The @MonadDejaFu@ typeclass++-- | The @MonadDejaFu@ class captures the two things needed to run a+-- concurrent program which we can't implement in normal Haskell:+-- mutable references, and the ability to create a bound thread in+-- @IO@.+--+-- In addition to needing the operations in this class, dejafu also+-- needs the ability to throw exceptions, as these are used to+-- communicate 'Error's, so there is a 'MonadThrow' constraint.+--+-- @since 2.1.0.0+class MonadThrow m => MonadDejaFu m where+  -- | The type of mutable references.  These references will always+  -- contain a value, and so don't need to handle emptiness (like+  -- @MVar@ does).+  --+  -- These references are always used from the same Haskell thread, so+  -- it's safe to implement these using unsynchronised primitives with+  -- relaxed-memory behaviours (like @IORef@s).+  type Ref m :: * -> *++  -- | Create a new reference holding a given initial value.+  newRef :: a -> m (Ref m a)++  -- | Read the current value in the reference.+  readRef :: Ref m a -> m a++  -- | Replace the value in the reference.+  writeRef :: Ref m a -> a -> m ()++  -- | A handle to a bound thread.  If the monad doesn't support bound+  -- threads (for example, if it's not based on @IO@), then this+  -- should be some type which can't be constructed, like 'V1'.+  type BoundThread m :: * -> *++  -- | Fork a new bound thread, if the monad supports them.+  forkBoundThread :: Maybe (m (BoundThread m a))++  -- | Run an action in a previously created bound thread.+  runInBoundThread :: BoundThread m a -> m a -> m a++  -- | Terminate a previously created bound thread.+  --+  -- After termination, 'runInBoundThread' and 'killBoundThread' will+  -- never be called on this @BoundThread m a@ value again.+  killBoundThread :: BoundThread m a -> m ()++-- | A bound thread in @IO@.+--+-- @since 2.1.0.0+data IOBoundThread a = IOBoundThread+  { iobtRunInBoundThread :: IO a -> IO a+    -- ^ Pass an action to the bound thread, run it, and return the+    -- result to this thread.+  , iobtKillBoundThread  :: IO ()+    -- ^ Terminate the bound thread.+  }++-- | @since 2.1.0.0+instance MonadDejaFu IO where+  type Ref IO = IO.IORef++  newRef   = IO.newIORef+  readRef  = IO.readIORef+  writeRef = IO.writeIORef++  type BoundThread IO = IOBoundThread++  forkBoundThread = Just $ do+      runboundIO <- IO.newEmptyMVar+      getboundIO <- IO.newEmptyMVar+      tid <- IO.forkOS (go runboundIO getboundIO)+      pure IOBoundThread+        { iobtRunInBoundThread = run runboundIO getboundIO+        , iobtKillBoundThread  = IO.killThread tid+        }+    where+      go runboundIO getboundIO = forever $ do+        na <- IO.takeMVar runboundIO+        IO.putMVar getboundIO =<< na++      run runboundIO getboundIO ma = do+        IO.putMVar runboundIO ma+        IO.takeMVar getboundIO++  runInBoundThread = iobtRunInBoundThread+  killBoundThread  = iobtKillBoundThread++-- | This instance does not support bound threads.+--+-- @since 2.1.0.0+instance MonadDejaFu (CatchT (ST.ST t)) where+  type Ref (CatchT (ST.ST t)) = ST.STRef t++  newRef     = lift . ST.newSTRef+  readRef    = lift . ST.readSTRef+  writeRef r = lift . ST.writeSTRef r++  -- V1 has no constructors+  type BoundThread (CatchT (ST.ST t)) = V1++  forkBoundThread  = Nothing+  runInBoundThread = undefined+  killBoundThread  = undefined++------------------------------------------------------------------------------- -- * Identifiers  -- | Every thread has a unique identitifer.@@ -116,6 +234,8 @@   -- ^ Start a new thread.   | ForkOS ThreadId   -- ^ Start a new bound thread.+  | SupportsBoundThreads Bool+  -- ^ Check if bound threads are supported.   | IsCurrentThreadBound Bool   -- ^ Check if the current thread is bound.   | MyThreadId@@ -206,6 +326,7 @@ instance NFData ThreadAction where   rnf (Fork t) = rnf t   rnf (ForkOS t) = rnf t+  rnf (SupportsBoundThreads b) = rnf b   rnf (IsCurrentThreadBound b) = rnf b   rnf MyThreadId = ()   rnf (GetNumCapabilities i) = rnf i@@ -252,6 +373,8 @@   -- ^ Will start a new thread.   | WillForkOS   -- ^ Will start a new bound thread.+  | WillSupportsBoundThreads+  -- ^ Will check if bound threads are supported.   | WillIsCurrentThreadBound   -- ^ Will check if the current thread is bound.   | WillMyThreadId@@ -331,6 +454,7 @@ instance NFData Lookahead where   rnf WillFork = ()   rnf WillForkOS = ()+  rnf WillSupportsBoundThreads = ()   rnf WillIsCurrentThreadBound = ()   rnf WillMyThreadId = ()   rnf WillGetNumCapabilities = ()
dejafu.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                dejafu-version:             2.0.0.1+version:             2.1.0.0 synopsis:            A library for unit-testing concurrent programs.  description:@@ -20,7 +20,7 @@ license-file:        LICENSE author:              Michael Walker maintainer:          mike@barrucadu.co.uk-copyright:           (c) 2015--2018 Michael Walker+copyright:           (c) 2015--2019 Michael Walker category:            Concurrency build-type:          Simple extra-source-files:  README.markdown CHANGELOG.rst@@ -33,7 +33,7 @@ source-repository this   type:     git   location: https://github.com/barrucadu/dejafu.git-  tag:      dejafu-2.0.0.1+  tag:      dejafu-2.1.0.0  library   exposed-modules:     Test.DejaFu@@ -59,7 +59,7 @@   -- other-modules:          -- other-extensions:       build-depends:       base              >=4.9 && <5-                     , concurrency       >=1.6 && <1.7+                     , concurrency       >=1.7 && <1.8                      , containers        >=0.5 && <0.7                      , contravariant     >=1.2 && <1.6                      , deepseq           >=1.1 && <2