{-# OPTIONS_GHC -Wno-orphans #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
module Test.DejaFu.Conc.Internal.Program where
import Control.Applicative (Applicative(..))
import Control.Exception (MaskingState(..))
import qualified Control.Monad.Catch as Ca
import qualified Control.Monad.IO.Class as IO
import Control.Monad.Trans.Class (MonadTrans(..))
import qualified Data.Foldable as F
import Data.List (partition)
import qualified Data.Map.Strict as M
import Data.Maybe (isNothing)
import GHC.Stack (HasCallStack)
import qualified Control.Monad.Conc.Class as C
import Test.DejaFu.Conc.Internal
import Test.DejaFu.Conc.Internal.Common
import Test.DejaFu.Conc.Internal.STM (ModelSTM)
import Test.DejaFu.Conc.Internal.Threading (Threads, _blocking)
import Test.DejaFu.Internal
import Test.DejaFu.Schedule
import Test.DejaFu.Types
instance (pty ~ Basic, IO.MonadIO n) => IO.MonadIO (Program pty n) where
liftIO :: forall a. IO a -> Program pty n a
liftIO IO a
ma = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\a -> Action n
c -> forall (n :: * -> *). n (Action n) -> Action n
ALift (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Action n
c (forall (m :: * -> *) a. MonadIO m => IO a -> m a
IO.liftIO IO a
ma)))
instance (pty ~ Basic) => MonadTrans (Program pty) where
lift :: forall (m :: * -> *) a. Monad m => m a -> Program pty m a
lift m a
ma = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\a -> Action m
c -> forall (n :: * -> *). n (Action n) -> Action n
ALift (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Action m
c m a
ma))
instance (pty ~ Basic) => Ca.MonadCatch (Program pty n) where
catch :: forall e a.
Exception e =>
Program pty n a -> (e -> Program pty n a) -> Program pty n a
catch Program pty n a
ma e -> Program pty n a
h = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a e.
Exception e =>
(e -> ModelConc n a)
-> ModelConc n a -> (a -> Action n) -> Action n
ACatching e -> Program pty n a
h Program pty n a
ma)
instance (pty ~ Basic) => Ca.MonadThrow (Program pty n) where
throwM :: forall e a. Exception e => e -> Program pty n a
throwM e
e = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\a -> Action n
_ -> forall (n :: * -> *) e. Exception e => e -> Action n
AThrow e
e)
instance (pty ~ Basic) => Ca.MonadMask (Program pty n) where
mask :: forall b.
((forall a. Program pty n a -> Program pty n a) -> Program pty n b)
-> Program pty n b
mask (forall a. Program pty n a -> Program pty n a) -> Program pty n b
mb = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
MaskingState
-> ((forall b. ModelConc n b -> ModelConc n b) -> ModelConc n a)
-> (a -> Action n)
-> Action n
AMasking MaskingState
MaskedInterruptible (\forall b. ModelConc n b -> ModelConc n b
f -> (forall a. Program pty n a -> Program pty n a) -> Program pty n b
mb forall b. ModelConc n b -> ModelConc n b
f))
uninterruptibleMask :: forall b.
((forall a. Program pty n a -> Program pty n a) -> Program pty n b)
-> Program pty n b
uninterruptibleMask (forall a. Program pty n a -> Program pty n a) -> Program pty n b
mb = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
MaskingState
-> ((forall b. ModelConc n b -> ModelConc n b) -> ModelConc n a)
-> (a -> Action n)
-> Action n
AMasking MaskingState
MaskedUninterruptible (\forall b. ModelConc n b -> ModelConc n b
f -> (forall a. Program pty n a -> Program pty n a) -> Program pty n b
mb forall b. ModelConc n b -> ModelConc n b
f))
#if MIN_VERSION_exceptions(0,10,0)
generalBracket :: forall a b c.
Program pty n a
-> (a -> ExitCase b -> Program pty n c)
-> (a -> Program pty n b)
-> Program pty n (b, c)
generalBracket Program pty n a
acquire a -> ExitCase b -> Program pty n c
release a -> Program pty n b
use = forall (m :: * -> *) b.
MonadMask m =>
((forall a. m a -> m a) -> m b) -> m b
Ca.mask forall a b. (a -> b) -> a -> b
$ \forall a. Program pty n a -> Program pty n a
unmasked -> do
a
resource <- Program pty n a
acquire
b
b <- forall a. Program pty n a -> Program pty n a
unmasked (a -> Program pty n b
use a
resource) forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`Ca.catch` (\SomeException
e -> a -> ExitCase b -> Program pty n c
release a
resource (forall a. SomeException -> ExitCase a
Ca.ExitCaseException SomeException
e) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
Ca.throwM SomeException
e)
c
c <- a -> ExitCase b -> Program pty n c
release a
resource (forall a. a -> ExitCase a
Ca.ExitCaseSuccess b
b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (b
b, c
c)
#elif MIN_VERSION_exceptions(0,9,0)
generalBracket acquire release cleanup use = Ca.mask $ \unmasked -> do
resource <- acquire
result <- unmasked (use resource) `Ca.catch` (\e -> cleanup resource e >> Ca.throwM e)
_ <- release resource
pure result
#endif
instance (pty ~ Basic, Monad n) => C.MonadConc (Program pty n) where
type MVar (Program pty n) = ModelMVar n
type IORef (Program pty n) = ModelIORef n
type Ticket (Program pty n) = ModelTicket
type STM (Program pty n) = ModelSTM n
type ThreadId (Program pty n) = ThreadId
forkWithUnmaskN :: String
-> ((forall a. Program pty n a -> Program pty n a)
-> Program pty n ())
-> Program pty n (ThreadId (Program pty n))
forkWithUnmaskN String
n (forall a. Program pty n a -> Program pty n a) -> Program pty n ()
ma = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *).
String
-> ((forall b. ModelConc n b -> ModelConc n b) -> Action n)
-> (ThreadId -> Action n)
-> Action n
AFork String
n (\forall b. ModelConc n b -> ModelConc n b
umask -> forall a (n :: * -> *).
Program Basic n a -> (a -> Action n) -> Action n
runModelConc ((forall a. Program pty n a -> Program pty n a) -> Program pty n ()
ma forall b. ModelConc n b -> ModelConc n b
umask) (\()
_ -> forall (n :: * -> *). n () -> Action n
AStop (forall (f :: * -> *) a. Applicative f => a -> f a
pure ()))))
forkOnWithUnmaskN :: String
-> Int
-> ((forall a. Program pty n a -> Program pty n a)
-> Program pty n ())
-> Program pty n (ThreadId (Program pty n))
forkOnWithUnmaskN String
n Int
_ = forall (m :: * -> *).
MonadConc m =>
String -> ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)
C.forkWithUnmaskN String
n
forkOSWithUnmaskN :: String
-> ((forall a. Program pty n a -> Program pty n a)
-> Program pty n ())
-> Program pty n (ThreadId (Program pty n))
forkOSWithUnmaskN String
n (forall a. Program pty n a -> Program pty n a) -> Program pty n ()
ma = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *).
String
-> ((forall b. ModelConc n b -> ModelConc n b) -> Action n)
-> (ThreadId -> Action n)
-> Action n
AForkOS String
n (\forall b. ModelConc n b -> ModelConc n b
umask -> forall a (n :: * -> *).
Program Basic n a -> (a -> Action n) -> Action n
runModelConc ((forall a. Program pty n a -> Program pty n a) -> Program pty n ()
ma forall b. ModelConc n b -> ModelConc n b
umask) (\()
_ -> forall (n :: * -> *). n () -> Action n
AStop (forall (f :: * -> *) a. Applicative f => a -> f a
pure ()))))
supportsBoundThreads :: Program pty n Bool
supportsBoundThreads = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc forall (n :: * -> *). (Bool -> Action n) -> Action n
ASupportsBoundThreads
isCurrentThreadBound :: Program pty n Bool
isCurrentThreadBound = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc forall (n :: * -> *). (Bool -> Action n) -> Action n
AIsBound
getNumCapabilities :: Program pty n Int
getNumCapabilities = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc forall (n :: * -> *). (Int -> Action n) -> Action n
AGetNumCapabilities
setNumCapabilities :: Int -> Program pty n ()
setNumCapabilities Int
caps = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\() -> Action n
c -> forall (n :: * -> *). Int -> Action n -> Action n
ASetNumCapabilities Int
caps (() -> Action n
c ()))
myThreadId :: Program pty n (ThreadId (Program pty n))
myThreadId = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc forall (n :: * -> *). (ThreadId -> Action n) -> Action n
AMyTId
yield :: Program pty n ()
yield = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\() -> Action n
c -> forall (n :: * -> *). Action n -> Action n
AYield (() -> Action n
c ()))
threadDelay :: Int -> Program pty n ()
threadDelay Int
n = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\() -> Action n
c -> forall (n :: * -> *). Int -> Action n -> Action n
ADelay Int
n (() -> Action n
c ()))
newIORefN :: forall a. String -> a -> Program pty n (IORef (Program pty n) a)
newIORefN String
n a
a = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
String -> a -> (ModelIORef n a -> Action n) -> Action n
ANewIORef String
n a
a)
readIORef :: forall a. IORef (Program pty n) a -> Program pty n a
readIORef IORef (Program pty n) a
ref = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
ModelIORef n a -> (a -> Action n) -> Action n
AReadIORef IORef (Program pty n) a
ref)
readForCAS :: forall a.
IORef (Program pty n) a -> Program pty n (Ticket (Program pty n) a)
readForCAS IORef (Program pty n) a
ref = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
ModelIORef n a -> (ModelTicket a -> Action n) -> Action n
AReadIORefCas IORef (Program pty n) a
ref)
peekTicket' :: forall a. Proxy (Program pty n) -> Ticket (Program pty n) a -> a
peekTicket' Proxy (Program pty n)
_ = forall a. ModelTicket a -> a
ticketVal
writeIORef :: forall a. IORef (Program pty n) a -> a -> Program pty n ()
writeIORef IORef (Program pty n) a
ref a
a = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\() -> Action n
c -> forall (n :: * -> *) a. ModelIORef n a -> a -> Action n -> Action n
AWriteIORef IORef (Program pty n) a
ref a
a (() -> Action n
c ()))
casIORef :: forall a.
IORef (Program pty n) a
-> Ticket (Program pty n) a
-> a
-> Program pty n (Bool, Ticket (Program pty n) a)
casIORef IORef (Program pty n) a
ref Ticket (Program pty n) a
tick a
a = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
ModelIORef n a
-> ModelTicket a
-> a
-> ((Bool, ModelTicket a) -> Action n)
-> Action n
ACasIORef IORef (Program pty n) a
ref Ticket (Program pty n) a
tick a
a)
atomicModifyIORef :: forall a b.
IORef (Program pty n) a -> (a -> (a, b)) -> Program pty n b
atomicModifyIORef IORef (Program pty n) a
ref a -> (a, b)
f = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a b.
ModelIORef n a -> (a -> (a, b)) -> (b -> Action n) -> Action n
AModIORef IORef (Program pty n) a
ref a -> (a, b)
f)
modifyIORefCAS :: forall a b.
IORef (Program pty n) a -> (a -> (a, b)) -> Program pty n b
modifyIORefCAS IORef (Program pty n) a
ref a -> (a, b)
f = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a b.
ModelIORef n a -> (a -> (a, b)) -> (b -> Action n) -> Action n
AModIORefCas IORef (Program pty n) a
ref a -> (a, b)
f)
newEmptyMVarN :: forall a. String -> Program pty n (MVar (Program pty n) a)
newEmptyMVarN String
n = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
String -> (ModelMVar n a -> Action n) -> Action n
ANewMVar String
n)
putMVar :: forall a. MVar (Program pty n) a -> a -> Program pty n ()
putMVar MVar (Program pty n) a
var a
a = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\() -> Action n
c -> forall (n :: * -> *) a. ModelMVar n a -> a -> Action n -> Action n
APutMVar MVar (Program pty n) a
var a
a (() -> Action n
c ()))
readMVar :: forall a. MVar (Program pty n) a -> Program pty n a
readMVar MVar (Program pty n) a
var = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
ModelMVar n a -> (a -> Action n) -> Action n
AReadMVar MVar (Program pty n) a
var)
takeMVar :: forall a. MVar (Program pty n) a -> Program pty n a
takeMVar MVar (Program pty n) a
var = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
ModelMVar n a -> (a -> Action n) -> Action n
ATakeMVar MVar (Program pty n) a
var)
tryPutMVar :: forall a. MVar (Program pty n) a -> a -> Program pty n Bool
tryPutMVar MVar (Program pty n) a
var a
a = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
ModelMVar n a -> a -> (Bool -> Action n) -> Action n
ATryPutMVar MVar (Program pty n) a
var a
a)
tryReadMVar :: forall a. MVar (Program pty n) a -> Program pty n (Maybe a)
tryReadMVar MVar (Program pty n) a
var = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
ModelMVar n a -> (Maybe a -> Action n) -> Action n
ATryReadMVar MVar (Program pty n) a
var)
tryTakeMVar :: forall a. MVar (Program pty n) a -> Program pty n (Maybe a)
tryTakeMVar MVar (Program pty n) a
var = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
ModelMVar n a -> (Maybe a -> Action n) -> Action n
ATryTakeMVar MVar (Program pty n) a
var)
throwTo :: forall e.
Exception e =>
ThreadId (Program pty n) -> e -> Program pty n ()
throwTo ThreadId (Program pty n)
tid e
e = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\() -> Action n
c -> forall (n :: * -> *) e.
Exception e =>
ThreadId -> e -> Action n -> Action n
AThrowTo ThreadId (Program pty n)
tid e
e (() -> Action n
c ()))
getMaskingState :: Program pty n MaskingState
getMaskingState = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (\MaskingState -> Action n
c -> forall (n :: * -> *). (MaskingState -> Action n) -> Action n
AGetMasking MaskingState -> Action n
c)
unsafeUnmask :: forall a. Program pty n a -> Program pty n a
unsafeUnmask Program pty n a
ma = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc (forall (n :: * -> *) a.
MaskingState
-> ((forall b. ModelConc n b -> ModelConc n b) -> ModelConc n a)
-> (a -> Action n)
-> Action n
AMasking MaskingState
Unmasked (\forall b. ModelConc n b -> ModelConc n b
_ -> Program pty n a
ma))
atomically :: forall a. STM (Program pty n) a -> Program pty n a
atomically = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (n :: * -> *) a. ModelSTM n a -> (a -> Action n) -> Action n
AAtom
runConcurrent :: MonadDejaFu n
=> Scheduler s
-> MemType
-> s
-> Program pty n a
-> n (Either Condition a, s, Trace)
runConcurrent :: forall (n :: * -> *) s pty a.
MonadDejaFu n =>
Scheduler s
-> MemType
-> s
-> Program pty n a
-> n (Either Condition a, s, Trace)
runConcurrent Scheduler s
sched MemType
memtype s
s ma :: Program pty n a
ma@(ModelConc (a -> Action n) -> Action n
_) = do
CResult n s a
res <- forall (n :: * -> *) g a.
(MonadDejaFu n, HasCallStack) =>
[Invariant n ()]
-> Bool
-> Scheduler g
-> MemType
-> g
-> IdSource
-> Int
-> ModelConc n a
-> n (CResult n g a)
runConcurrency [] Bool
False Scheduler s
sched MemType
memtype s
s IdSource
initialIdSource Int
2 Program pty n a
ma
Either Condition a
out <- forall a. HasCallStack => Maybe a -> a
efromJust forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadDejaFu m => Ref m a -> m a
readRef (forall (n :: * -> *) g a.
CResult n g a -> Ref n (Maybe (Either Condition a))
finalRef CResult n s a
res)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ( Either Condition a
out
, forall (n :: * -> *) g. Context n g -> g
cSchedState (forall (n :: * -> *) g a. CResult n g a -> Context n g
finalContext CResult n s a
res)
, forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList (forall (n :: * -> *) g a. CResult n g a -> SeqTrace
finalTrace CResult n s a
res)
)
runConcurrent Scheduler s
sched MemType
memtype s
s Program pty n a
ma = forall (n :: * -> *) pty a.
MonadDejaFu n =>
Program pty n a
-> n (Maybe (Either Condition (Snapshot pty n a), Trace))
recordSnapshot Program pty n a
ma forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Just (Left Condition
cond, Trace
trc) -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. a -> Either a b
Left Condition
cond, s
s, Trace
trc)
Just (Right Snapshot pty n a
snap, Trace
_) -> forall (n :: * -> *) s pty a.
MonadDejaFu n =>
Scheduler s
-> MemType
-> s
-> Snapshot pty n a
-> n (Either Condition a, s, Trace)
runSnapshot Scheduler s
sched MemType
memtype s
s Snapshot pty n a
snap
Maybe (Either Condition (Snapshot pty n a), Trace)
Nothing -> forall a. HasCallStack => String -> a
fatal String
"failed to record snapshot!"
recordSnapshot
:: MonadDejaFu n
=> Program pty n a
-> n (Maybe (Either Condition (Snapshot pty n a), Trace))
recordSnapshot :: forall (n :: * -> *) pty a.
MonadDejaFu n =>
Program pty n a
-> n (Maybe (Either Condition (Snapshot pty n a), Trace))
recordSnapshot ModelConc{} = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing
recordSnapshot WithSetup{ModelConc n x
x -> ModelConc n a
wsProgram :: forall (n :: * -> *) a a.
Program (WithSetup a) n a -> a -> ModelConc n a
wsSetup :: forall (n :: * -> *) a a.
Program (WithSetup a) n a -> ModelConc n a
wsProgram :: x -> ModelConc n a
wsSetup :: ModelConc n x
..} =
let mkSnapshot :: SimpleSnapshot n a -> p -> Snapshot (WithSetup x) n a
mkSnapshot SimpleSnapshot n a
snap p
_ = forall (n :: * -> *) a a.
SimpleSnapshot n a -> Snapshot (WithSetup a) n a
WS SimpleSnapshot n a
snap
in forall (n :: * -> *) a x snap.
MonadDejaFu n =>
(SimpleSnapshot n a -> x -> snap)
-> ModelConc n x
-> (x -> ModelConc n a)
-> n (Maybe (Either Condition snap, Trace))
defaultRecordSnapshot forall {n :: * -> *} {a} {p} {x}.
SimpleSnapshot n a -> p -> Snapshot (WithSetup x) n a
mkSnapshot ModelConc n x
wsSetup x -> ModelConc n a
wsProgram
recordSnapshot WithSetupAndTeardown{ModelConc n x
x -> ModelConc n y
x -> Either Condition y -> ModelConc n a
wstTeardown :: forall (n :: * -> *) a x a.
Program (WithSetupAndTeardown a x) n a
-> a -> Either Condition x -> ModelConc n a
wstProgram :: forall (n :: * -> *) a x a.
Program (WithSetupAndTeardown a x) n a -> a -> ModelConc n x
wstSetup :: forall (n :: * -> *) a x a.
Program (WithSetupAndTeardown a x) n a -> ModelConc n a
wstTeardown :: x -> Either Condition y -> ModelConc n a
wstProgram :: x -> ModelConc n y
wstSetup :: ModelConc n x
..} =
let mkSnapshot :: SimpleSnapshot n y -> x -> Snapshot (WithSetupAndTeardown x y) n a
mkSnapshot SimpleSnapshot n y
snap = forall (n :: * -> *) a y x.
SimpleSnapshot n a
-> (Either Condition a -> ModelConc n y)
-> Snapshot (WithSetupAndTeardown x a) n y
WSAT SimpleSnapshot n y
snap forall b c a. (b -> c) -> (a -> b) -> a -> c
. x -> Either Condition y -> ModelConc n a
wstTeardown
in forall (n :: * -> *) a x snap.
MonadDejaFu n =>
(SimpleSnapshot n a -> x -> snap)
-> ModelConc n x
-> (x -> ModelConc n a)
-> n (Maybe (Either Condition snap, Trace))
defaultRecordSnapshot SimpleSnapshot n y -> x -> Snapshot (WithSetupAndTeardown x y) n a
mkSnapshot ModelConc n x
wstSetup x -> ModelConc n y
wstProgram
runSnapshot
:: MonadDejaFu n
=> Scheduler s
-> MemType
-> s
-> Snapshot pty n a
-> n (Either Condition a, s, Trace)
runSnapshot :: forall (n :: * -> *) s pty a.
MonadDejaFu n =>
Scheduler s
-> MemType
-> s
-> Snapshot pty n a
-> n (Either Condition a, s, Trace)
runSnapshot Scheduler s
sched MemType
memtype s
s (WS SimpleSnapshot{ModelConc n a
Context n ()
Threads n -> n ()
snapNext :: forall (n :: * -> *) a. SimpleSnapshot n a -> ModelConc n a
snapRestore :: forall (n :: * -> *) a. SimpleSnapshot n a -> Threads n -> n ()
snapContext :: forall (n :: * -> *) a. SimpleSnapshot n a -> Context n ()
snapNext :: ModelConc n a
snapRestore :: Threads n -> n ()
snapContext :: Context n ()
..}) = do
let context :: Context n s
context = forall g (n :: * -> *) s. g -> Context n s -> Context n g
fromSnapContext s
s Context n ()
snapContext
CResult{Maybe (ThreadId, ThreadAction)
SeqTrace
Ref n (Maybe (Either Condition a))
Context n s
Threads n -> n ()
finalDecision :: forall (n :: * -> *) g a.
CResult n g a -> Maybe (ThreadId, ThreadAction)
finalRestore :: forall (n :: * -> *) g a. CResult n g a -> Threads n -> n ()
finalDecision :: Maybe (ThreadId, ThreadAction)
finalTrace :: SeqTrace
finalRestore :: Threads n -> n ()
finalRef :: Ref n (Maybe (Either Condition a))
finalContext :: Context n s
finalTrace :: forall (n :: * -> *) g a. CResult n g a -> SeqTrace
finalContext :: forall (n :: * -> *) g a. CResult n g a -> Context n g
finalRef :: forall (n :: * -> *) g a.
CResult n g a -> Ref n (Maybe (Either Condition a))
..} <- forall (n :: * -> *) g a.
(MonadDejaFu n, HasCallStack) =>
Scheduler g
-> MemType
-> Context n g
-> (Threads n -> n ())
-> ModelConc n a
-> n (CResult n g a)
runConcurrencyWithSnapshot Scheduler s
sched MemType
memtype Context n s
context Threads n -> n ()
snapRestore ModelConc n a
snapNext
Either Condition a
out <- forall a. HasCallStack => Maybe a -> a
efromJust forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadDejaFu m => Ref m a -> m a
readRef Ref n (Maybe (Either Condition a))
finalRef
forall (f :: * -> *) a. Applicative f => a -> f a
pure ( Either Condition a
out
, forall (n :: * -> *) g. Context n g -> g
cSchedState Context n s
finalContext
, forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList SeqTrace
finalTrace
)
runSnapshot Scheduler s
sched MemType
memtype s
s (WSAT SimpleSnapshot{ModelConc n a
Context n ()
Threads n -> n ()
snapNext :: ModelConc n a
snapRestore :: Threads n -> n ()
snapContext :: Context n ()
snapNext :: forall (n :: * -> *) a. SimpleSnapshot n a -> ModelConc n a
snapRestore :: forall (n :: * -> *) a. SimpleSnapshot n a -> Threads n -> n ()
snapContext :: forall (n :: * -> *) a. SimpleSnapshot n a -> Context n ()
..} Either Condition a -> ModelConc n a
teardown) = do
let context :: Context n s
context = forall g (n :: * -> *) s. g -> Context n s -> Context n g
fromSnapContext s
s Context n ()
snapContext
CResult n s a
intermediateResult <- forall (n :: * -> *) g a.
(MonadDejaFu n, HasCallStack) =>
Scheduler g
-> MemType
-> Context n g
-> (Threads n -> n ())
-> ModelConc n a
-> n (CResult n g a)
runConcurrencyWithSnapshot Scheduler s
sched MemType
memtype Context n s
context Threads n -> n ()
snapRestore ModelConc n a
snapNext
let idsrc :: IdSource
idsrc = forall (n :: * -> *) g. Context n g -> IdSource
cIdSource (forall (n :: * -> *) g a. CResult n g a -> Context n g
finalContext CResult n s a
intermediateResult)
Either Condition a
out1 <- forall a. HasCallStack => Maybe a -> a
efromJust forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadDejaFu m => Ref m a -> m a
readRef (forall (n :: * -> *) g a.
CResult n g a -> Ref n (Maybe (Either Condition a))
finalRef CResult n s a
intermediateResult)
CResult n () a
teardownResult <- forall (n :: * -> *) a.
(MonadDejaFu n, HasCallStack) =>
Bool -> IdSource -> ModelConc n a -> n (CResult n () a)
simpleRunConcurrency Bool
False IdSource
idsrc (Either Condition a -> ModelConc n a
teardown Either Condition a
out1)
Either Condition a
out2 <- forall a. HasCallStack => Maybe a -> a
efromJust forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadDejaFu m => Ref m a -> m a
readRef (forall (n :: * -> *) g a.
CResult n g a -> Ref n (Maybe (Either Condition a))
finalRef CResult n () a
teardownResult)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ( Either Condition a
out2
, forall (n :: * -> *) g. Context n g -> g
cSchedState (forall (n :: * -> *) g a. CResult n g a -> Context n g
finalContext CResult n s a
intermediateResult)
, forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList (forall (n :: * -> *) g a. CResult n g a -> SeqTrace
finalTrace CResult n s a
intermediateResult)
)
data Snapshot pty n a where
WS :: SimpleSnapshot n a -> Snapshot (WithSetup x) n a
WSAT :: SimpleSnapshot n a -> (Either Condition a -> ModelConc n y) -> Snapshot (WithSetupAndTeardown x a) n y
data SimpleSnapshot n a = SimpleSnapshot
{ forall (n :: * -> *) a. SimpleSnapshot n a -> Context n ()
snapContext :: Context n ()
, forall (n :: * -> *) a. SimpleSnapshot n a -> Threads n -> n ()
snapRestore :: Threads n -> n ()
, forall (n :: * -> *) a. SimpleSnapshot n a -> ModelConc n a
snapNext :: ModelConc n a
}
contextFromSnapshot :: Snapshot p n a -> Context n ()
contextFromSnapshot :: forall p (n :: * -> *) a. Snapshot p n a -> Context n ()
contextFromSnapshot (WS SimpleSnapshot{ModelConc n a
Context n ()
Threads n -> n ()
snapNext :: ModelConc n a
snapRestore :: Threads n -> n ()
snapContext :: Context n ()
snapNext :: forall (n :: * -> *) a. SimpleSnapshot n a -> ModelConc n a
snapRestore :: forall (n :: * -> *) a. SimpleSnapshot n a -> Threads n -> n ()
snapContext :: forall (n :: * -> *) a. SimpleSnapshot n a -> Context n ()
..}) = Context n ()
snapContext
contextFromSnapshot (WSAT SimpleSnapshot{ModelConc n a
Context n ()
Threads n -> n ()
snapNext :: ModelConc n a
snapRestore :: Threads n -> n ()
snapContext :: Context n ()
snapNext :: forall (n :: * -> *) a. SimpleSnapshot n a -> ModelConc n a
snapRestore :: forall (n :: * -> *) a. SimpleSnapshot n a -> Threads n -> n ()
snapContext :: forall (n :: * -> *) a. SimpleSnapshot n a -> Context n ()
..} Either Condition a -> ModelConc n a
_) = Context n ()
snapContext
threadsFromSnapshot :: Snapshot p n a -> ([ThreadId], [ThreadId])
threadsFromSnapshot :: forall p (n :: * -> *) a.
Snapshot p n a -> ([ThreadId], [ThreadId])
threadsFromSnapshot Snapshot p n a
snap = (ThreadId
initialThread forall a. a -> [a] -> [a]
: [ThreadId]
runnable, [ThreadId]
blocked) where
([ThreadId]
runnable, [ThreadId]
blocked) = forall a. (a -> Bool) -> [a] -> ([a], [a])
partition ThreadId -> Bool
isRunnable (forall k a. Map k a -> [k]
M.keys Threads n
threads)
threads :: Threads n
threads = forall (n :: * -> *) g. Context n g -> Threads n
cThreads (forall p (n :: * -> *) a. Snapshot p n a -> Context n ()
contextFromSnapshot Snapshot p n a
snap)
isRunnable :: ThreadId -> Bool
isRunnable ThreadId
tid = forall a. Maybe a -> Bool
isNothing (forall (n :: * -> *). Thread n -> Maybe BlockedOn
_blocking forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup ThreadId
tid Threads n
threads)
defaultRecordSnapshot :: MonadDejaFu n
=> (SimpleSnapshot n a -> x -> snap)
-> ModelConc n x
-> (x -> ModelConc n a)
-> n (Maybe (Either Condition snap, Trace))
defaultRecordSnapshot :: forall (n :: * -> *) a x snap.
MonadDejaFu n =>
(SimpleSnapshot n a -> x -> snap)
-> ModelConc n x
-> (x -> ModelConc n a)
-> n (Maybe (Either Condition snap, Trace))
defaultRecordSnapshot SimpleSnapshot n a -> x -> snap
mkSnapshot ModelConc n x
setup x -> ModelConc n a
program = do
CResult{Maybe (ThreadId, ThreadAction)
SeqTrace
Ref n (Maybe (Either Condition x))
Context n ()
Threads n -> n ()
finalDecision :: Maybe (ThreadId, ThreadAction)
finalTrace :: SeqTrace
finalRestore :: Threads n -> n ()
finalRef :: Ref n (Maybe (Either Condition x))
finalContext :: Context n ()
finalDecision :: forall (n :: * -> *) g a.
CResult n g a -> Maybe (ThreadId, ThreadAction)
finalRestore :: forall (n :: * -> *) g a. CResult n g a -> Threads n -> n ()
finalTrace :: forall (n :: * -> *) g a. CResult n g a -> SeqTrace
finalContext :: forall (n :: * -> *) g a. CResult n g a -> Context n g
finalRef :: forall (n :: * -> *) g a.
CResult n g a -> Ref n (Maybe (Either Condition a))
..} <- forall (n :: * -> *) a.
(MonadDejaFu n, HasCallStack) =>
Bool -> IdSource -> ModelConc n a -> n (CResult n () a)
simpleRunConcurrency Bool
True IdSource
initialIdSource ModelConc n x
setup
let trc :: Trace
trc = forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList SeqTrace
finalTrace
Maybe (Either Condition x)
out <- forall (m :: * -> *) a. MonadDejaFu m => Ref m a -> m a
readRef Ref n (Maybe (Either Condition x))
finalRef
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ case Maybe (Either Condition x)
out of
Just (Right x
a) ->
let snap :: snap
snap = SimpleSnapshot n a -> x -> snap
mkSnapshot (forall (n :: * -> *) a.
Context n ()
-> (Threads n -> n ()) -> ModelConc n a -> SimpleSnapshot n a
SimpleSnapshot Context n ()
finalContext Threads n -> n ()
finalRestore (x -> ModelConc n a
program x
a)) x
a
in (forall a b. b -> Either a b
Right snap
snap, Trace
trc)
Just (Left Condition
f) -> (forall a b. a -> Either a b
Left Condition
f, Trace
trc)
Maybe (Either Condition x)
Nothing -> forall a. HasCallStack => String -> a
fatal String
"failed to produce snapshot"
simpleRunConcurrency ::(MonadDejaFu n, HasCallStack)
=> Bool
-> IdSource
-> ModelConc n a
-> n (CResult n () a)
simpleRunConcurrency :: forall (n :: * -> *) a.
(MonadDejaFu n, HasCallStack) =>
Bool -> IdSource -> ModelConc n a -> n (CResult n () a)
simpleRunConcurrency Bool
forSnapshot IdSource
idsrc =
forall (n :: * -> *) g a.
(MonadDejaFu n, HasCallStack) =>
[Invariant n ()]
-> Bool
-> Scheduler g
-> MemType
-> g
-> IdSource
-> Int
-> ModelConc n a
-> n (CResult n g a)
runConcurrency [] Bool
forSnapshot Scheduler ()
roundRobinSchedNP MemType
SequentialConsistency () IdSource
idsrc Int
2
fromSnapContext :: g -> Context n s -> Context n g
fromSnapContext :: forall g (n :: * -> *) s. g -> Context n s -> Context n g
fromSnapContext g
g ctx :: Context n s
ctx@Context{s
Int
[Invariant n ()]
Threads n
ConcurrencyState
IdSource
WriteBuffer n
InvariantContext n
cCState :: forall (n :: * -> *) g. Context n g -> ConcurrencyState
cNewInvariants :: forall (n :: * -> *) g. Context n g -> [Invariant n ()]
cInvariants :: forall (n :: * -> *) g. Context n g -> InvariantContext n
cCaps :: forall (n :: * -> *) g. Context n g -> Int
cWriteBuf :: forall (n :: * -> *) g. Context n g -> WriteBuffer n
cCState :: ConcurrencyState
cNewInvariants :: [Invariant n ()]
cInvariants :: InvariantContext n
cCaps :: Int
cWriteBuf :: WriteBuffer n
cThreads :: Threads n
cIdSource :: IdSource
cSchedState :: s
cThreads :: forall (n :: * -> *) g. Context n g -> Threads n
cIdSource :: forall (n :: * -> *) g. Context n g -> IdSource
cSchedState :: forall (n :: * -> *) g. Context n g -> g
..} = Context n s
ctx
{ cSchedState :: g
cSchedState = g
g
, cInvariants :: InvariantContext n
cInvariants = InvariantContext
{ icActive :: [Invariant n ()]
icActive = [Invariant n ()]
cNewInvariants
, icBlocked :: [(Invariant n (), ([IORefId], [MVarId], [TVarId]))]
icBlocked = []
}
, cNewInvariants :: [Invariant n ()]
cNewInvariants = []
}
wrap :: (((a -> Action n) -> Action n) -> ((a -> Action n) -> Action n)) -> ModelConc n a -> ModelConc n a
wrap :: forall a (n :: * -> *).
(((a -> Action n) -> Action n) -> (a -> Action n) -> Action n)
-> ModelConc n a -> ModelConc n a
wrap ((a -> Action n) -> Action n) -> (a -> Action n) -> Action n
f = forall a (n :: * -> *).
((a -> Action n) -> Action n) -> Program Basic n a
ModelConc forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> Action n) -> Action n) -> (a -> Action n) -> Action n
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a (n :: * -> *).
Program Basic n a -> (a -> Action n) -> Action n
runModelConc