dejafu-1.10.1.0: A library for unit-testing concurrent programs.

Copyright(c) 2016--2018 Michael Walker
LicenseMIT
MaintainerMichael Walker <mike@barrucadu.co.uk>
Stabilityexperimental
PortabilityCPP, FlexibleInstances, GeneralizedNewtypeDeriving, TypeFamilies
Safe HaskellNone
LanguageHaskell2010

Test.DejaFu.Conc

Contents

Description

Deterministic traced execution of concurrent computations.

This works by executing the computation on a single thread, calling out to the supplied scheduler after each step to determine which thread runs next.

Synopsis

The ConcT monad transformer

data ConcT n a Source #

Since: 1.4.0.0

Instances

MonadTrans ConcT Source # 

Methods

lift :: Monad m => m a -> ConcT m a #

Monad (ConcT n) Source # 

Methods

(>>=) :: ConcT n a -> (a -> ConcT n b) -> ConcT n b #

(>>) :: ConcT n a -> ConcT n b -> ConcT n b #

return :: a -> ConcT n a #

fail :: String -> ConcT n a #

Functor (ConcT n) Source # 

Methods

fmap :: (a -> b) -> ConcT n a -> ConcT n b #

(<$) :: a -> ConcT n b -> ConcT n a #

MonadFail (ConcT n) Source # 

Methods

fail :: String -> ConcT n a #

Applicative (ConcT n) Source # 

Methods

pure :: a -> ConcT n a #

(<*>) :: ConcT n (a -> b) -> ConcT n a -> ConcT n b #

liftA2 :: (a -> b -> c) -> ConcT n a -> ConcT n b -> ConcT n c #

(*>) :: ConcT n a -> ConcT n b -> ConcT n b #

(<*) :: ConcT n a -> ConcT n b -> ConcT n a #

MonadIO n => MonadIO (ConcT n) Source #

Since: 1.0.0.0

Methods

liftIO :: IO a -> ConcT n a #

Monad n => MonadConc (ConcT n) Source # 

Associated Types

type STM (ConcT n :: * -> *) :: * -> * #

type MVar (ConcT n :: * -> *) :: * -> * #

type CRef (ConcT n :: * -> *) :: * -> * #

type Ticket (ConcT n :: * -> *) :: * -> * #

type ThreadId (ConcT n :: * -> *) :: * #

Methods

forkWithUnmask :: ((forall a. ConcT n a -> ConcT n a) -> ConcT n ()) -> ConcT n (ThreadId (ConcT n)) #

forkWithUnmaskN :: String -> ((forall a. ConcT n a -> ConcT n a) -> ConcT n ()) -> ConcT n (ThreadId (ConcT n)) #

forkOnWithUnmask :: Int -> ((forall a. ConcT n a -> ConcT n a) -> ConcT n ()) -> ConcT n (ThreadId (ConcT n)) #

forkOnWithUnmaskN :: String -> Int -> ((forall a. ConcT n a -> ConcT n a) -> ConcT n ()) -> ConcT n (ThreadId (ConcT n)) #

forkOSWithUnmask :: ((forall a. ConcT n a -> ConcT n a) -> ConcT n ()) -> ConcT n (ThreadId (ConcT n)) #

forkOSWithUnmaskN :: String -> ((forall a. ConcT n a -> ConcT n a) -> ConcT n ()) -> ConcT n (ThreadId (ConcT n)) #

isCurrentThreadBound :: ConcT n Bool #

getNumCapabilities :: ConcT n Int #

setNumCapabilities :: Int -> ConcT n () #

myThreadId :: ConcT n (ThreadId (ConcT n)) #

yield :: ConcT n () #

threadDelay :: Int -> ConcT n () #

newEmptyMVar :: ConcT n (MVar (ConcT n) a) #

newEmptyMVarN :: String -> ConcT n (MVar (ConcT n) a) #

putMVar :: MVar (ConcT n) a -> a -> ConcT n () #

tryPutMVar :: MVar (ConcT n) a -> a -> ConcT n Bool #

readMVar :: MVar (ConcT n) a -> ConcT n a #

tryReadMVar :: MVar (ConcT n) a -> ConcT n (Maybe a) #

takeMVar :: MVar (ConcT n) a -> ConcT n a #

tryTakeMVar :: MVar (ConcT n) a -> ConcT n (Maybe a) #

newCRef :: a -> ConcT n (CRef (ConcT n) a) #

newCRefN :: String -> a -> ConcT n (CRef (ConcT n) a) #

readCRef :: CRef (ConcT n) a -> ConcT n a #

atomicModifyCRef :: CRef (ConcT n) a -> (a -> (a, b)) -> ConcT n b #

writeCRef :: CRef (ConcT n) a -> a -> ConcT n () #

atomicWriteCRef :: CRef (ConcT n) a -> a -> ConcT n () #

readForCAS :: CRef (ConcT n) a -> ConcT n (Ticket (ConcT n) a) #

peekTicket' :: Proxy (* -> *) (ConcT n) -> Ticket (ConcT n) a -> a #

casCRef :: CRef (ConcT n) a -> Ticket (ConcT n) a -> a -> ConcT n (Bool, Ticket (ConcT n) a) #

modifyCRefCAS :: CRef (ConcT n) a -> (a -> (a, b)) -> ConcT n b #

modifyCRefCAS_ :: CRef (ConcT n) a -> (a -> a) -> ConcT n () #

atomically :: STM (ConcT n) a -> ConcT n a #

readTVarConc :: TVar (STM (ConcT n)) a -> ConcT n a #

throwTo :: Exception e => ThreadId (ConcT n) -> e -> ConcT n () #

MonadThrow (ConcT n) Source # 

Methods

throwM :: Exception e => e -> ConcT n a #

MonadCatch (ConcT n) Source # 

Methods

catch :: Exception e => ConcT n a -> (e -> ConcT n a) -> ConcT n a #

MonadMask (ConcT n) Source # 

Methods

mask :: ((forall a. ConcT n a -> ConcT n a) -> ConcT n b) -> ConcT n b #

uninterruptibleMask :: ((forall a. ConcT n a -> ConcT n a) -> ConcT n b) -> ConcT n b #

generalBracket :: ConcT n a -> (a -> ExitCase b -> ConcT n c) -> (a -> ConcT n b) -> ConcT n (b, c) #

type ThreadId (ConcT n) Source # 
type Ticket (ConcT n) Source # 
type CRef (ConcT n) Source # 
type CRef (ConcT n) = ModelCRef n
type MVar (ConcT n) Source # 
type MVar (ConcT n) = ModelMVar n
type STM (ConcT n) Source # 
type STM (ConcT n) = ModelSTM n

type ConcIO = ConcT IO Source #

A MonadConc implementation using IO.

Since: 0.4.0.0

Executing computations

data Failure Source #

An indication of how a concurrent computation failed.

The Eq, Ord, and NFData instances compare/evaluate the exception with show in the UncaughtException case.

Since: 1.1.0.0

Constructors

InternalError

Will be raised if the scheduler does something bad. This should never arise unless you write your own, faulty, scheduler! If it does, please file a bug report.

Abort

The scheduler chose to abort execution. This will be produced if, for example, all possible decisions exceed the specified bounds (there have been too many pre-emptions, the computation has executed for too long, or there have been too many yields).

Deadlock

Every thread is blocked, and the main thread is not blocked in an STM transaction.

STMDeadlock

Every thread is blocked, and the main thread is blocked in an STM transaction.

UncaughtException SomeException

An uncaught exception bubbled to the top of the computation.

IllegalSubconcurrency

Calls to subconcurrency were nested, or attempted when multiple threads existed.

IllegalDontCheck

A call to dontCheck was attempted after the first action of the initial thread.

Instances

Eq Failure Source # 

Methods

(==) :: Failure -> Failure -> Bool #

(/=) :: Failure -> Failure -> Bool #

Ord Failure Source # 
Show Failure Source # 
Generic Failure Source #

Since: 1.3.1.0

Associated Types

type Rep Failure :: * -> * #

Methods

from :: Failure -> Rep Failure x #

to :: Rep Failure x -> Failure #

NFData Failure Source # 

Methods

rnf :: Failure -> () #

type Rep Failure Source # 
type Rep Failure = D1 * (MetaData "Failure" "Test.DejaFu.Types" "dejafu-1.10.1.0-Jnz8UmvHazc5uVK0snz6XW" False) ((:+:) * ((:+:) * (C1 * (MetaCons "InternalError" PrefixI False) (U1 *)) ((:+:) * (C1 * (MetaCons "Abort" PrefixI False) (U1 *)) (C1 * (MetaCons "Deadlock" PrefixI False) (U1 *)))) ((:+:) * ((:+:) * (C1 * (MetaCons "STMDeadlock" PrefixI False) (U1 *)) (C1 * (MetaCons "UncaughtException" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * SomeException)))) ((:+:) * (C1 * (MetaCons "IllegalSubconcurrency" PrefixI False) (U1 *)) (C1 * (MetaCons "IllegalDontCheck" PrefixI False) (U1 *)))))

data MemType Source #

The memory model to use for non-synchronised CRef operations.

Since: 0.4.0.0

Constructors

SequentialConsistency

The most intuitive model: a program behaves as a simple interleaving of the actions in different threads. When a CRef is written to, that write is immediately visible to all threads.

TotalStoreOrder

Each thread has a write buffer. A thread sees its writes immediately, but other threads will only see writes when they are committed, which may happen later. Writes are committed in the same order that they are created.

PartialStoreOrder

Each CRef has a write buffer. A thread sees its writes immediately, but other threads will only see writes when they are committed, which may happen later. Writes to different CRefs are not necessarily committed in the same order that they are created.

Instances

Bounded MemType Source # 
Enum MemType Source # 
Eq MemType Source # 

Methods

(==) :: MemType -> MemType -> Bool #

(/=) :: MemType -> MemType -> Bool #

Ord MemType Source # 
Read MemType Source # 
Show MemType Source # 
Generic MemType Source #

Since: 1.3.1.0

Associated Types

type Rep MemType :: * -> * #

Methods

from :: MemType -> Rep MemType x #

to :: Rep MemType x -> MemType #

NFData MemType Source #

Since: 0.5.1.0

Methods

rnf :: MemType -> () #

type Rep MemType Source # 
type Rep MemType = D1 * (MetaData "MemType" "Test.DejaFu.Types" "dejafu-1.10.1.0-Jnz8UmvHazc5uVK0snz6XW" False) ((:+:) * (C1 * (MetaCons "SequentialConsistency" PrefixI False) (U1 *)) ((:+:) * (C1 * (MetaCons "TotalStoreOrder" PrefixI False) (U1 *)) (C1 * (MetaCons "PartialStoreOrder" PrefixI False) (U1 *))))

runConcurrent :: MonadConc n => Scheduler s -> MemType -> s -> ConcT n a -> n (Either Failure a, s, Trace) Source #

Run a concurrent computation with a given Scheduler and initial state, returning a failure reason on error. Also returned is the final state of the scheduler, and an execution trace.

If the RTS supports bound threads (ghc -threaded when linking) then the main thread of the concurrent computation will be bound, and forkOS / forkOSN will work during execution. If not, then the main thread will not be found, and attempting to fork a bound thread will raise an error.

Warning: Blocking on the action of another thread in liftIO cannot be detected! So if you perform some potentially blocking action in a liftIO the entire collection of threads may deadlock! You should therefore keep IO blocks small, and only perform blocking operations with the supplied primitives, insofar as possible.

Note: In order to prevent computation from hanging, the runtime will assume that a deadlock situation has arisen if the scheduler attempts to (a) schedule a blocked thread, or (b) schedule a nonexistent thread. In either of those cases, the computation will be halted.

Since: 1.0.0.0

subconcurrency :: ConcT n a -> ConcT n (Either Failure a) Source #

Run a concurrent computation and return its result.

This can only be called in the main thread, when no other threads exist. Calls to subconcurrency cannot be nested, or placed inside a call to dontCheck. Violating either of these conditions will result in the computation failing with IllegalSubconcurrency. The overall test-case can still succeed if the predicate allows for a failing computation.

Since: 0.6.0.0

dontCheck Source #

Arguments

:: Maybe Int

An optional length bound.

-> ConcT n a

The action to execute.

-> ConcT n a 

Run an arbitrary action which gets some special treatment:

  • For systematic testing, dontCheck is not dependent with anything, even if the action has dependencies.
  • For pre-emption bounding, dontCheck counts for zero pre-emptions, even if the action performs pre-emptive context switches.
  • For fair bounding, dontCheck counts for zero yields/delays, even if the action performs yields or delays.
  • For length bounding, dontCheck counts for one step, even if the action has many.
  • All SCT functions use runForDCSnapshot / runWithDCSnapshot to ensure that the action is only executed once, although you should be careful with IO (see note on snapshotting IO).

The action is executed atomically with a deterministic scheduler under sequential consistency. Any threads created inside the action continue to exist in the main computation.

This must be the first thing done in the main thread. Violating this condition will result in the computation failing with IllegalDontCheck. The overall test-case can still succeed if the predicate allows for a failing computation.

If the action fails (deadlock, length bound exceeded, etc), the whole computation fails.

Since: 1.1.0.0

Snapshotting

Snapshotting IO: A snapshot captures entire state of your concurrent program: the state of every thread, the number of capabilities, the values of any CRefs, MVars, and TVars, and records any IO that you performed.

When restoring a snapshot this IO is replayed, in order. But the whole snapshotted computation is not. So the effects of the IO take place again, but any return values are ignored. For example, this program will not do what you want:

bad_snapshot = do
  r <- dontCheck Nothing $ do
    r <- liftIO (newIORef 0)
    liftIO (modifyIORef r (+1))
    pure r
  liftIO (readIORef r)

When the snapshot is taken, the value in the IORef will be 1. When the snapshot is restored for the first time, those IO actions will be run again, but their return values will be discarded. The value in the IORef will be 2. When the snapshot is restored for the second time, the value in the IORef will be 3. And so on.

To safely use IO in a snapshotted computation, the combined effect must be idempotent. You should either use actions which set the state to the final value directly, rather than modifying it (eg, using a combination of liftIO . readCRef and liftIO . writeIORef here), or reset the state to a known value. Both of these approaches will work:

good_snapshot1 = do
  r <- dontCheck Nothing $ do
    let modify r f = liftIO (readIORef r) >>= liftIO . writeIORef r . f
    r <- liftIO (newIORef 0)
    modify r (+1)
    pure r
  liftIO (readIORef r)

good_snapshot2 = do
  r <- dontCheck Nothing $ do
    r <- liftIO (newIORef 0)
    liftIO (writeIORef r 0)
    liftIO (modifyIORef r (+1))
    pure r
  liftIO (readIORef r)

data DCSnapshot n a Source #

A snapshot of the concurrency state immediately after dontCheck finishes.

Since: 1.4.0.0

runForDCSnapshot :: MonadConc n => ConcT n a -> n (Maybe (Either Failure (DCSnapshot n a), Trace)) Source #

Like runConcurrent, but terminates immediately after running the dontCheck action with a DCSnapshot which can be used in runWithDCSnapshot to avoid doing that work again.

If this program does not contain a legal use of dontCheck, then the result will be Nothing.

If you are using the SCT functions on an action which contains a dontCheck, snapshotting will be handled for you, without you needing to call this function yourself.

Since: 1.1.0.0

runWithDCSnapshot :: MonadConc n => Scheduler s -> MemType -> s -> DCSnapshot n a -> n (Either Failure a, s, Trace) Source #

Like runConcurrent, but uses a DCSnapshot produced by runForDCSnapshot to skip the dontCheck work.

If you are using the SCT functions on an action which contains a dontCheck, snapshotting will be handled for you, without you needing to call this function yourself.

Since: 1.1.0.0

canDCSnapshot :: ConcT n a -> Bool Source #

Check if a DCSnapshot can be taken from this computation.

Since: 1.1.0.0

threadsFromDCSnapshot :: DCSnapshot n a -> ([ThreadId], [ThreadId]) Source #

Get the threads which exist in a snapshot, partitioned into runnable and not runnable.

Since: 1.1.0.0

Execution traces

type Trace = [(Decision, [(ThreadId, Lookahead)], ThreadAction)] Source #

One of the outputs of the runner is a Trace, which is a log of decisions made, all the alternative unblocked threads and what they would do, and the action a thread took in its step.

Since: 0.8.0.0

data Decision Source #

Scheduling decisions are based on the state of the running program, and so we can capture some of that state in recording what specific decision we made.

Since: 0.5.0.0

Constructors

Start ThreadId

Start a new thread, because the last was blocked (or it's the start of computation).

Continue

Continue running the last thread for another step.

SwitchTo ThreadId

Pre-empt the running thread, and switch to another.

Instances

Eq Decision Source # 
Show Decision Source # 
Generic Decision Source #

Since: 1.3.1.0

Associated Types

type Rep Decision :: * -> * #

Methods

from :: Decision -> Rep Decision x #

to :: Rep Decision x -> Decision #

NFData Decision Source #

Since: 0.5.1.0

Methods

rnf :: Decision -> () #

type Rep Decision Source # 
type Rep Decision = D1 * (MetaData "Decision" "Test.DejaFu.Types" "dejafu-1.10.1.0-Jnz8UmvHazc5uVK0snz6XW" False) ((:+:) * (C1 * (MetaCons "Start" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * ThreadId))) ((:+:) * (C1 * (MetaCons "Continue" PrefixI False) (U1 *)) (C1 * (MetaCons "SwitchTo" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * ThreadId)))))

newtype ThreadId Source #

Every thread has a unique identitifer.

Since: 1.0.0.0

Constructors

ThreadId Id 

Instances

Eq ThreadId Source # 
Ord ThreadId Source # 
Show ThreadId Source # 
Generic ThreadId Source #

Since: 1.3.1.0

Associated Types

type Rep ThreadId :: * -> * #

Methods

from :: ThreadId -> Rep ThreadId x #

to :: Rep ThreadId x -> ThreadId #

NFData ThreadId Source # 

Methods

rnf :: ThreadId -> () #

type Rep ThreadId Source # 
type Rep ThreadId = D1 * (MetaData "ThreadId" "Test.DejaFu.Types" "dejafu-1.10.1.0-Jnz8UmvHazc5uVK0snz6XW" True) (C1 * (MetaCons "ThreadId" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Id)))

data ThreadAction Source #

All the actions that a thread can perform.

Since: 1.9.0.0

Constructors

Fork ThreadId

Start a new thread.

ForkOS ThreadId

Start a new bound thread.

IsCurrentThreadBound Bool

Check if the current thread is bound.

MyThreadId

Get the ThreadId of the current thread.

GetNumCapabilities Int

Get the number of Haskell threads that can run simultaneously.

SetNumCapabilities Int

Set the number of Haskell threads that can run simultaneously.

Yield

Yield the current thread.

ThreadDelay Int

Yield/delay the current thread.

NewMVar MVarId

Create a new MVar.

PutMVar MVarId [ThreadId]

Put into a MVar, possibly waking up some threads.

BlockedPutMVar MVarId

Get blocked on a put.

TryPutMVar MVarId Bool [ThreadId]

Try to put into a MVar, possibly waking up some threads.

ReadMVar MVarId

Read from a MVar.

TryReadMVar MVarId Bool

Try to read from a MVar.

BlockedReadMVar MVarId

Get blocked on a read.

TakeMVar MVarId [ThreadId]

Take from a MVar, possibly waking up some threads.

BlockedTakeMVar MVarId

Get blocked on a take.

TryTakeMVar MVarId Bool [ThreadId]

Try to take from a MVar, possibly waking up some threads.

NewCRef CRefId

Create a new CRef.

ReadCRef CRefId

Read from a CRef.

ReadCRefCas CRefId

Read from a CRef for a future compare-and-swap.

ModCRef CRefId

Modify a CRef.

ModCRefCas CRefId

Modify a CRef using a compare-and-swap.

WriteCRef CRefId

Write to a CRef without synchronising.

CasCRef CRefId Bool

Attempt to to a CRef using a compare-and-swap, synchronising it.

CommitCRef ThreadId CRefId

Commit the last write to the given CRef by the given thread, so that all threads can see the updated value.

STM [TAction] [ThreadId]

An STM transaction was executed, possibly waking up some threads.

BlockedSTM [TAction]

Got blocked in an STM transaction.

Catching

Register a new exception handler

PopCatching

Pop the innermost exception handler from the stack.

Throw Bool

Throw an exception. If the Bool is True, then this killed the thread.

ThrowTo ThreadId Bool

Throw an exception to a thread. If the Bool is True, then this killed the thread.

BlockedThrowTo ThreadId

Get blocked on a throwTo.

SetMasking Bool MaskingState

Set the masking state. If True, this is being used to set the masking state to the original state in the argument passed to a masked function.

ResetMasking Bool MaskingState

Return to an earlier masking state. If True, this is being used to return to the state of the masked block in the argument passed to a masked function.

LiftIO

Lift an IO action. Note that this can only happen with ConcIO.

Return

A return or pure action was executed.

Stop

Cease execution and terminate.

Subconcurrency

Start executing an action with subconcurrency.

StopSubconcurrency

Stop executing an action with subconcurrency.

DontCheck Trace

Execute an action with dontCheck.

Instances

Eq ThreadAction Source # 
Show ThreadAction Source # 
Generic ThreadAction Source #

Since: 1.3.1.0

Associated Types

type Rep ThreadAction :: * -> * #

NFData ThreadAction Source # 

Methods

rnf :: ThreadAction -> () #

type Rep ThreadAction Source # 
type Rep ThreadAction = D1 * (MetaData "ThreadAction" "Test.DejaFu.Types" "dejafu-1.10.1.0-Jnz8UmvHazc5uVK0snz6XW" False) ((:+:) * ((:+:) * ((:+:) * ((:+:) * ((:+:) * (C1 * (MetaCons "Fork" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * ThreadId))) (C1 * (MetaCons "ForkOS" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * ThreadId)))) ((:+:) * (C1 * (MetaCons "IsCurrentThreadBound" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool))) ((:+:) * (C1 * (MetaCons "MyThreadId" PrefixI False) (U1 *)) (C1 * (MetaCons "GetNumCapabilities" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Int)))))) ((:+:) * ((:+:) * (C1 * (MetaCons "SetNumCapabilities" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Int))) (C1 * (MetaCons "Yield" PrefixI False) (U1 *))) ((:+:) * (C1 * (MetaCons "ThreadDelay" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Int))) ((:+:) * (C1 * (MetaCons "NewMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId))) (C1 * (MetaCons "PutMVar" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * [ThreadId])))))))) ((:+:) * ((:+:) * ((:+:) * (C1 * (MetaCons "BlockedPutMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId))) (C1 * (MetaCons "TryPutMVar" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId)) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * [ThreadId])))))) ((:+:) * (C1 * (MetaCons "ReadMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId))) ((:+:) * (C1 * (MetaCons "TryReadMVar" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool)))) (C1 * (MetaCons "BlockedReadMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId)))))) ((:+:) * ((:+:) * (C1 * (MetaCons "TakeMVar" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * [ThreadId])))) (C1 * (MetaCons "BlockedTakeMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId)))) ((:+:) * (C1 * (MetaCons "TryTakeMVar" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId)) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * [ThreadId]))))) ((:+:) * (C1 * (MetaCons "NewCRef" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId))) (C1 * (MetaCons "ReadCRef" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId)))))))) ((:+:) * ((:+:) * ((:+:) * ((:+:) * (C1 * (MetaCons "ReadCRefCas" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId))) (C1 * (MetaCons "ModCRef" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId)))) ((:+:) * (C1 * (MetaCons "ModCRefCas" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId))) ((:+:) * (C1 * (MetaCons "WriteCRef" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId))) (C1 * (MetaCons "CasCRef" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool))))))) ((:+:) * ((:+:) * (C1 * (MetaCons "CommitCRef" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * ThreadId)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId)))) (C1 * (MetaCons "STM" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * [TAction])) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * [ThreadId]))))) ((:+:) * (C1 * (MetaCons "BlockedSTM" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * [TAction]))) ((:+:) * (C1 * (MetaCons "Catching" PrefixI False) (U1 *)) (C1 * (MetaCons "PopCatching" PrefixI False) (U1 *)))))) ((:+:) * ((:+:) * ((:+:) * (C1 * (MetaCons "Throw" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool))) (C1 * (MetaCons "ThrowTo" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * ThreadId)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool))))) ((:+:) * (C1 * (MetaCons "BlockedThrowTo" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * ThreadId))) ((:+:) * (C1 * (MetaCons "SetMasking" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MaskingState)))) (C1 * (MetaCons "ResetMasking" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MaskingState))))))) ((:+:) * ((:+:) * (C1 * (MetaCons "LiftIO" PrefixI False) (U1 *)) ((:+:) * (C1 * (MetaCons "Return" PrefixI False) (U1 *)) (C1 * (MetaCons "Stop" PrefixI False) (U1 *)))) ((:+:) * (C1 * (MetaCons "Subconcurrency" PrefixI False) (U1 *)) ((:+:) * (C1 * (MetaCons "StopSubconcurrency" PrefixI False) (U1 *)) (C1 * (MetaCons "DontCheck" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Trace)))))))))

data Lookahead Source #

A one-step look-ahead at what a thread will do next.

Since: 1.1.0.0

Constructors

WillFork

Will start a new thread.

WillForkOS

Will start a new bound thread.

WillIsCurrentThreadBound

Will check if the current thread is bound.

WillMyThreadId

Will get the ThreadId.

WillGetNumCapabilities

Will get the number of Haskell threads that can run simultaneously.

WillSetNumCapabilities Int

Will set the number of Haskell threads that can run simultaneously.

WillYield

Will yield the current thread.

WillThreadDelay Int

Will yield/delay the current thread.

WillNewMVar

Will create a new MVar.

WillPutMVar MVarId

Will put into a MVar, possibly waking up some threads.

WillTryPutMVar MVarId

Will try to put into a MVar, possibly waking up some threads.

WillReadMVar MVarId

Will read from a MVar.

WillTryReadMVar MVarId

Will try to read from a MVar.

WillTakeMVar MVarId

Will take from a MVar, possibly waking up some threads.

WillTryTakeMVar MVarId

Will try to take from a MVar, possibly waking up some threads.

WillNewCRef

Will create a new CRef.

WillReadCRef CRefId

Will read from a CRef.

WillReadCRefCas CRefId

Will read from a CRef for a future compare-and-swap.

WillModCRef CRefId

Will modify a CRef.

WillModCRefCas CRefId

Will modify a CRef using a compare-and-swap.

WillWriteCRef CRefId

Will write to a CRef without synchronising.

WillCasCRef CRefId

Will attempt to to a CRef using a compare-and-swap, synchronising it.

WillCommitCRef ThreadId CRefId

Will commit the last write by the given thread to the CRef.

WillSTM

Will execute an STM transaction, possibly waking up some threads.

WillCatching

Will register a new exception handler

WillPopCatching

Will pop the innermost exception handler from the stack.

WillThrow

Will throw an exception.

WillThrowTo ThreadId

Will throw an exception to a thread.

WillSetMasking Bool MaskingState

Will set the masking state. If True, this is being used to set the masking state to the original state in the argument passed to a masked function.

WillResetMasking Bool MaskingState

Will return to an earlier masking state. If True, this is being used to return to the state of the masked block in the argument passed to a masked function.

WillLiftIO

Will lift an IO action. Note that this can only happen with ConcIO.

WillReturn

Will execute a return or pure action.

WillStop

Will cease execution and terminate.

WillSubconcurrency

Will execute an action with subconcurrency.

WillStopSubconcurrency

Will stop executing an extion with subconcurrency.

WillDontCheck

Will execute an action with dontCheck.

Instances

Eq Lookahead Source # 
Show Lookahead Source # 
Generic Lookahead Source #

Since: 1.3.1.0

Associated Types

type Rep Lookahead :: * -> * #

NFData Lookahead Source # 

Methods

rnf :: Lookahead -> () #

type Rep Lookahead Source # 
type Rep Lookahead = D1 * (MetaData "Lookahead" "Test.DejaFu.Types" "dejafu-1.10.1.0-Jnz8UmvHazc5uVK0snz6XW" False) ((:+:) * ((:+:) * ((:+:) * ((:+:) * ((:+:) * (C1 * (MetaCons "WillFork" PrefixI False) (U1 *)) (C1 * (MetaCons "WillForkOS" PrefixI False) (U1 *))) ((:+:) * (C1 * (MetaCons "WillIsCurrentThreadBound" PrefixI False) (U1 *)) (C1 * (MetaCons "WillMyThreadId" PrefixI False) (U1 *)))) ((:+:) * ((:+:) * (C1 * (MetaCons "WillGetNumCapabilities" PrefixI False) (U1 *)) (C1 * (MetaCons "WillSetNumCapabilities" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Int)))) ((:+:) * (C1 * (MetaCons "WillYield" PrefixI False) (U1 *)) ((:+:) * (C1 * (MetaCons "WillThreadDelay" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Int))) (C1 * (MetaCons "WillNewMVar" PrefixI False) (U1 *)))))) ((:+:) * ((:+:) * ((:+:) * (C1 * (MetaCons "WillPutMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId))) (C1 * (MetaCons "WillTryPutMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId)))) ((:+:) * (C1 * (MetaCons "WillReadMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId))) (C1 * (MetaCons "WillTryReadMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId))))) ((:+:) * ((:+:) * (C1 * (MetaCons "WillTakeMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId))) (C1 * (MetaCons "WillTryTakeMVar" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MVarId)))) ((:+:) * (C1 * (MetaCons "WillNewCRef" PrefixI False) (U1 *)) ((:+:) * (C1 * (MetaCons "WillReadCRef" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId))) (C1 * (MetaCons "WillReadCRefCas" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId)))))))) ((:+:) * ((:+:) * ((:+:) * ((:+:) * (C1 * (MetaCons "WillModCRef" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId))) (C1 * (MetaCons "WillModCRefCas" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId)))) ((:+:) * (C1 * (MetaCons "WillWriteCRef" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId))) (C1 * (MetaCons "WillCasCRef" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId))))) ((:+:) * ((:+:) * (C1 * (MetaCons "WillCommitCRef" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * ThreadId)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * CRefId)))) (C1 * (MetaCons "WillSTM" PrefixI False) (U1 *))) ((:+:) * (C1 * (MetaCons "WillCatching" PrefixI False) (U1 *)) ((:+:) * (C1 * (MetaCons "WillPopCatching" PrefixI False) (U1 *)) (C1 * (MetaCons "WillThrow" PrefixI False) (U1 *)))))) ((:+:) * ((:+:) * ((:+:) * (C1 * (MetaCons "WillThrowTo" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * ThreadId))) (C1 * (MetaCons "WillSetMasking" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MaskingState))))) ((:+:) * (C1 * (MetaCons "WillResetMasking" PrefixI False) ((:*:) * (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Bool)) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * MaskingState)))) (C1 * (MetaCons "WillLiftIO" PrefixI False) (U1 *)))) ((:+:) * ((:+:) * (C1 * (MetaCons "WillReturn" PrefixI False) (U1 *)) (C1 * (MetaCons "WillStop" PrefixI False) (U1 *))) ((:+:) * (C1 * (MetaCons "WillSubconcurrency" PrefixI False) (U1 *)) ((:+:) * (C1 * (MetaCons "WillStopSubconcurrency" PrefixI False) (U1 *)) (C1 * (MetaCons "WillDontCheck" PrefixI False) (U1 *))))))))

data MVarId Source #

Every MVar has a unique identifier.

Since: 1.0.0.0

Instances

Eq MVarId Source # 

Methods

(==) :: MVarId -> MVarId -> Bool #

(/=) :: MVarId -> MVarId -> Bool #

Ord MVarId Source # 
Show MVarId Source # 
Generic MVarId Source #

Since: 1.3.1.0

Associated Types

type Rep MVarId :: * -> * #

Methods

from :: MVarId -> Rep MVarId x #

to :: Rep MVarId x -> MVarId #

NFData MVarId Source # 

Methods

rnf :: MVarId -> () #

type Rep MVarId Source # 
type Rep MVarId = D1 * (MetaData "MVarId" "Test.DejaFu.Types" "dejafu-1.10.1.0-Jnz8UmvHazc5uVK0snz6XW" True) (C1 * (MetaCons "MVarId" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Id)))

data CRefId Source #

Every CRef has a unique identifier.

Since: 1.0.0.0

Instances

Eq CRefId Source # 

Methods

(==) :: CRefId -> CRefId -> Bool #

(/=) :: CRefId -> CRefId -> Bool #

Ord CRefId Source # 
Show CRefId Source # 
Generic CRefId Source #

Since: 1.3.1.0

Associated Types

type Rep CRefId :: * -> * #

Methods

from :: CRefId -> Rep CRefId x #

to :: Rep CRefId x -> CRefId #

NFData CRefId Source # 

Methods

rnf :: CRefId -> () #

type Rep CRefId Source # 
type Rep CRefId = D1 * (MetaData "CRefId" "Test.DejaFu.Types" "dejafu-1.10.1.0-Jnz8UmvHazc5uVK0snz6XW" True) (C1 * (MetaCons "CRefId" PrefixI False) (S1 * (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Id)))

data MaskingState :: * #

Describes the behaviour of a thread when an asynchronous exception is received.

Constructors

Unmasked

asynchronous exceptions are unmasked (the normal state)

MaskedInterruptible

the state during mask: asynchronous exceptions are masked, but blocking operations may still be interrupted

MaskedUninterruptible

the state during uninterruptibleMask: asynchronous exceptions are masked, and blocking operations may not be interrupted

showTrace :: Trace -> String Source #

Pretty-print a trace, including a key of the thread IDs (not including thread 0). Each line of the key is indented by two spaces.

Since: 0.5.0.0

showFail :: Failure -> String Source #

Pretty-print a failure

Since: 0.4.0.0

Scheduling