dejafu-0.9.0.0: Systematic testing for Haskell concurrency.

Copyright (c) 2016 Michael Walker MIT Michael Walker experimental CPP, ExistentialQuantification, RankNTypes None Haskell2010

Test.DejaFu.Conc.Internal.Common

Description

Common types and utility functions for deterministic execution of MonadConc implementations. This module is NOT considered to form

Synopsis

# The Conc Monad

newtype M n r a Source #

The underlying monad is based on continuations over Actions.

One might wonder why the return type isn't reflected in Action, and a free monad formulation used. This would remove the need for a AStop actions having their parameter. However, this makes the current expression of threads and exception handlers very difficult (perhaps even not possible without significant reworking), so I abandoned the attempt.

Constructors

 M FieldsrunM :: (a -> Action n r) -> Action n r

Instances

 Monad (M n r) Source # Methods(>>=) :: M n r a -> (a -> M n r b) -> M n r b #(>>) :: M n r a -> M n r b -> M n r b #return :: a -> M n r a #fail :: String -> M n r a # Functor (M n r) Source # Methodsfmap :: (a -> b) -> M n r a -> M n r b #(<\$) :: a -> M n r b -> M n r a # MonadFail (M n r) Source # Since: 0.7.1.2 Methodsfail :: String -> M n r a # Applicative (M n r) Source # Methodspure :: a -> M n r a #(<*>) :: M n r (a -> b) -> M n r a -> M n r b #(*>) :: M n r a -> M n r b -> M n r b #(<*) :: M n r a -> M n r b -> M n r a #

data MVar r a Source #

The concurrent variable type used with the Conc monad. One notable difference between these and MVars is that MVars are single-wakeup, and wake up in a FIFO order. Writing to a MVar wakes up all threads blocked on reading it, and it is up to the scheduler which one runs next. Taking from a MVar behaves analogously.

Constructors

 MVar Fields_cvarId :: MVarId _cvarVal :: r (Maybe a)

data CRef r a Source #

The mutable non-blocking reference type. These are like IORefs.

CRefs are represented as a unique numeric identifier and a reference containing (a) any thread-local non-synchronised writes (so each thread sees its latest write), (b) a commit count (used in compare-and-swaps), and (c) the current value visible to all threads.

Constructors

 CRef Fields_crefId :: CRefId _crefVal :: r (Map ThreadId a, Integer, a)

Instances

 MonadRef (CRef r) (ConcT r n) # MethodsnewRef :: a -> ConcT r n (CRef r a) #readRef :: CRef r a -> ConcT r n a #writeRef :: CRef r a -> a -> ConcT r n () #modifyRef :: CRef r a -> (a -> a) -> ConcT r n () #modifyRef' :: CRef r a -> (a -> a) -> ConcT r n () # MonadAtomicRef (CRef r) (ConcT r n) # MethodsatomicModifyRef :: CRef r a -> (a -> (a, b)) -> ConcT r n b #atomicModifyRef' :: CRef r a -> (a -> (a, b)) -> ConcT r n b #

data Ticket a Source #

The compare-and-swap proof type.

Tickets are represented as just a wrapper around the identifier of the CRef it came from, the commit count at the time it was produced, and an a value. This doesn't work in the source package (atomic-primops) because of the need to use pointer equality. Here we can just pack extra information into CRef to avoid that need.

Constructors

 Ticket Fields_ticketCRef :: CRefId _ticketWrites :: Integer _ticketVal :: a

cont :: ((a -> Action n r) -> Action n r) -> M n r a Source #

Construct a continuation-passing operation from a function.

runCont :: M n r a -> (a -> Action n r) -> Action n r Source #

Run a CPS computation with the given final computation.

# Primitive Actions

data Action n r Source #

Scheduling is done in terms of a trace of Actions. Blocking can only occur as a result of an action, and they cover (most of) the primitives of the concurrency. spawn is absent as it is implemented in terms of newEmptyMVar, fork, and putMVar.

Constructors