{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
module Simulation.Aivika.Trans.Internal.Cont
(ContParams,
ContCancellation(..),
Cont(..),
ContId,
ContEvent(..),
FrozenCont,
newContId,
contSignal,
contCancellationInitiated,
contCancellationInitiate,
contCancellationInitiating,
contCancellationActivated,
contCancellationBind,
contCancellationConnect,
contPreemptionBegun,
contPreemptionBegin,
contPreemptionBeginning,
contPreemptionEnd,
contPreemptionEnding,
invokeCont,
runCont,
rerunCont,
spawnCont,
contParallel,
contParallel_,
catchCont,
finallyCont,
throwCont,
resumeCont,
resumeECont,
reenterCont,
freezeCont,
freezeContReentering,
unfreezeCont,
substituteCont,
contCanceled,
contAwait,
transferCont,
traceCont) where
import Data.Array
import Data.Monoid
import Control.Exception
import Control.Monad
import Control.Monad.Trans
import qualified Control.Monad.Catch as MC
import Control.Applicative
import Debug.Trace (trace)
import Simulation.Aivika.Trans.Ref.Base
import Simulation.Aivika.Trans.Exception
import Simulation.Aivika.Trans.Comp
import Simulation.Aivika.Trans.DES
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Parameter
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Dynamics
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Signal
data ContCancellation = CancelTogether
| CancelChildAfterParent
| CancelParentAfterChild
| CancelInIsolation
data ContId m =
ContId { contCancellationInitiatedRef :: Ref m Bool,
contCancellationActivatedRef :: Ref m Bool,
contPreemptionCountRef :: Ref m Int,
contSignalSource :: SignalSource m ContEvent
}
instance MonadDES m => Eq (ContId m) where
x == y = contCancellationInitiatedRef x == contCancellationInitiatedRef y
data ContEvent = ContCancellationInitiating
| ContPreemptionBeginning
| ContPreemptionEnding
deriving (Eq, Ord, Show)
newContId :: MonadDES m => Simulation m (ContId m)
{-# INLINABLE newContId #-}
newContId =
Simulation $ \r ->
do r1 <- invokeSimulation r $ newRef False
r2 <- invokeSimulation r $ newRef False
r3 <- invokeSimulation r $ newRef 0
s <- invokeSimulation r newSignalSource
return ContId { contCancellationInitiatedRef = r1,
contCancellationActivatedRef = r2,
contPreemptionCountRef = r3,
contSignalSource = s
}
contSignal :: ContId m -> Signal m ContEvent
{-# INLINABLE contSignal #-}
contSignal = publishSignal . contSignalSource
contCancellationInitiating :: MonadDES m => ContId m -> Signal m ()
{-# INLINABLE contCancellationInitiating #-}
contCancellationInitiating =
filterSignal_ (ContCancellationInitiating ==) . contSignal
contCancellationInitiated :: MonadDES m => ContId m -> Event m Bool
{-# INLINABLE contCancellationInitiated #-}
contCancellationInitiated =
readRef . contCancellationInitiatedRef
contCancellationActivated :: MonadDES m => ContId m -> Event m Bool
{-# INLINABLE contCancellationActivated #-}
contCancellationActivated =
readRef . contCancellationActivatedRef
contCancellationDeactivate :: MonadDES m => ContId m -> Event m ()
{-# INLINABLE contCancellationDeactivate #-}
contCancellationDeactivate x =
writeRef (contCancellationActivatedRef x) False
contCancellationBind :: MonadDES m => ContId m -> [ContId m] -> Event m (DisposableEvent m)
{-# INLINABLE contCancellationBind #-}
contCancellationBind x ys =
Event $ \p ->
do hs1 <- forM ys $ \y ->
invokeEvent p $
handleSignal (contCancellationInitiating x) $ \_ ->
contCancellationInitiate y
hs2 <- forM ys $ \y ->
invokeEvent p $
handleSignal (contCancellationInitiating y) $ \_ ->
contCancellationInitiate x
return $ mconcat hs1 <> mconcat hs2
contCancellationConnect :: MonadDES m
=> ContId m
-> ContCancellation
-> ContId m
-> Event m (DisposableEvent m)
{-# INLINABLE contCancellationConnect #-}
contCancellationConnect parent cancellation child =
Event $ \p ->
do let m1 =
handleSignal (contCancellationInitiating parent) $ \_ ->
contCancellationInitiate child
m2 =
handleSignal (contCancellationInitiating child) $ \_ ->
contCancellationInitiate parent
h1 <-
case cancellation of
CancelTogether -> invokeEvent p m1
CancelChildAfterParent -> invokeEvent p m1
CancelParentAfterChild -> return mempty
CancelInIsolation -> return mempty
h2 <-
case cancellation of
CancelTogether -> invokeEvent p m2
CancelChildAfterParent -> return mempty
CancelParentAfterChild -> invokeEvent p m2
CancelInIsolation -> return mempty
return $ h1 <> h2
contCancellationInitiate :: MonadDES m => ContId m -> Event m ()
{-# INLINABLE contCancellationInitiate #-}
contCancellationInitiate x =
Event $ \p ->
do f <- invokeEvent p $ readRef (contCancellationInitiatedRef x)
unless f $
do invokeEvent p $ writeRef (contCancellationInitiatedRef x) True
invokeEvent p $ writeRef (contCancellationActivatedRef x) True
invokeEvent p $ triggerSignal (contSignalSource x) ContCancellationInitiating
contPreemptionBegin :: MonadDES m => ContId m -> Event m ()
{-# INLINABLE contPreemptionBegin #-}
contPreemptionBegin x =
Event $ \p ->
do f <- invokeEvent p $ readRef (contCancellationInitiatedRef x)
unless f $
do n <- invokeEvent p $ readRef (contPreemptionCountRef x)
let n' = n + 1
n' `seq` invokeEvent p $ writeRef (contPreemptionCountRef x) n'
when (n == 0) $
invokeEvent p $
triggerSignal (contSignalSource x) ContPreemptionBeginning
contPreemptionEnd :: MonadDES m => ContId m -> Event m ()
{-# INLINABLE contPreemptionEnd #-}
contPreemptionEnd x =
Event $ \p ->
do f <- invokeEvent p $ readRef (contCancellationInitiatedRef x)
unless f $
do n <- invokeEvent p $ readRef (contPreemptionCountRef x)
let n' = n - 1
n' `seq` invokeEvent p $ writeRef (contPreemptionCountRef x) n'
when (n' == 0) $
invokeEvent p $
triggerSignal (contSignalSource x) ContPreemptionEnding
contPreemptionBeginning :: MonadDES m => ContId m -> Signal m ()
{-# INLINABLE contPreemptionBeginning #-}
contPreemptionBeginning =
filterSignal_ (ContPreemptionBeginning ==) . contSignal
contPreemptionEnding :: MonadDES m => ContId m -> Signal m ()
{-# INLINABLE contPreemptionEnding #-}
contPreemptionEnding =
filterSignal_ (ContPreemptionEnding ==) . contSignal
contPreemptionBegun :: MonadDES m => ContId m -> Event m Bool
{-# INLINABLE contPreemptionBegun #-}
contPreemptionBegun x =
Event $ \p ->
do n <- invokeEvent p $ readRef (contPreemptionCountRef x)
return (n > 0)
newtype Cont m a = Cont (ContParams m a -> Event m ())
data ContParams m a =
ContParams { contCont :: a -> Event m (),
contAux :: ContParamsAux m }
data ContParamsAux m =
ContParamsAux { contECont :: SomeException -> Event m (),
contCCont :: () -> Event m (),
contId :: ContId m,
contCancelRef :: Ref m Bool,
contCatchFlag :: Bool }
instance MonadDES m => Monad (Cont m) where
{-# INLINE return #-}
return a =
Cont $ \c ->
Event $ \p ->
do z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else invokeEvent p $ contCont c a
{-# INLINE (>>=) #-}
(Cont m) >>= k =
Cont $ \c ->
Event $ \p ->
do z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else invokeEvent p $ m $
let cont a = invokeCont c (k a)
in c { contCont = cont }
instance MonadDES m => MonadCompTrans Cont m where
{-# INLINE liftComp #-}
liftComp m =
Cont $ \c ->
Event $ \p ->
if contCatchFlag . contAux $ c
then liftWithCatching m p c
else liftWithoutCatching m p c
instance MonadDES m => ParameterLift Cont m where
{-# INLINE liftParameter #-}
liftParameter (Parameter m) =
Cont $ \c ->
Event $ \p ->
if contCatchFlag . contAux $ c
then liftWithCatching (m $ pointRun p) p c
else liftWithoutCatching (m $ pointRun p) p c
instance MonadDES m => SimulationLift Cont m where
{-# INLINE liftSimulation #-}
liftSimulation (Simulation m) =
Cont $ \c ->
Event $ \p ->
if contCatchFlag . contAux $ c
then liftWithCatching (m $ pointRun p) p c
else liftWithoutCatching (m $ pointRun p) p c
instance MonadDES m => DynamicsLift Cont m where
{-# INLINE liftDynamics #-}
liftDynamics (Dynamics m) =
Cont $ \c ->
Event $ \p ->
if contCatchFlag . contAux $ c
then liftWithCatching (m p) p c
else liftWithoutCatching (m p) p c
instance MonadDES m => EventLift Cont m where
{-# INLINE liftEvent #-}
liftEvent (Event m) =
Cont $ \c ->
Event $ \p ->
if contCatchFlag . contAux $ c
then liftWithCatching (m p) p c
else liftWithoutCatching (m p) p c
instance (MonadDES m, MonadIO m) => MonadIO (Cont m) where
{-# INLINE liftIO #-}
liftIO m =
Cont $ \c ->
Event $ \p ->
if contCatchFlag . contAux $ c
then liftWithCatching (liftIO m) p c
else liftWithoutCatching (liftIO m) p c
instance MonadDES m => Functor (Cont m) where
{-# INLINE fmap #-}
fmap = liftM
instance MonadDES m => Applicative (Cont m) where
{-# INLINE pure #-}
pure = return
{-# INLINE (<*>) #-}
(<*>) = ap
instance MonadDES m => MC.MonadThrow (Cont m) where
{-# INLINE throwM #-}
throwM = throwCont
instance MonadDES m => MC.MonadCatch (Cont m) where
{-# INLINE catch #-}
catch = catchCont
invokeCont :: ContParams m a -> Cont m a -> Event m ()
{-# INLINE invokeCont #-}
invokeCont p (Cont m) = m p
cancelCont :: MonadDES m => ContParams m a -> Event m ()
{-# NOINLINE cancelCont #-}
cancelCont c =
Event $ \p ->
do invokeEvent p $ contCancellationDeactivate (contId $ contAux c)
invokeEvent p $ (contCCont $ contAux c) ()
callCont :: MonadDES m => (a -> Cont m b) -> a -> ContParams m b -> Event m ()
{-# INLINABLE callCont #-}
callCont k a c =
Event $ \p ->
do z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else invokeEvent p $ invokeCont c (k a)
catchCont :: (MonadDES m, Exception e) => Cont m a -> (e -> Cont m a) -> Cont m a
{-# INLINABLE catchCont #-}
catchCont (Cont m) h =
Cont $ \c0 ->
Event $ \p ->
do let c = c0 { contAux = (contAux c0) { contCatchFlag = True } }
z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else invokeEvent p $ m $
let econt e0 =
case fromException e0 of
Just e -> callCont h e c
Nothing -> (contECont . contAux $ c) e0
in c { contAux = (contAux c) { contECont = econt } }
finallyCont :: MonadDES m => Cont m a -> Cont m b -> Cont m a
{-# INLINABLE finallyCont #-}
finallyCont (Cont m) (Cont m') =
Cont $ \c0 ->
Event $ \p ->
do let c = c0 { contAux = (contAux c0) { contCatchFlag = True } }
z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else invokeEvent p $ m $
let cont a =
Event $ \p ->
invokeEvent p $ m' $
let cont b = contCont c a
in c { contCont = cont }
econt e =
Event $ \p ->
invokeEvent p $ m' $
let cont b = (contECont . contAux $ c) e
in c { contCont = cont }
ccont () =
Event $ \p ->
invokeEvent p $ m' $
let cont b = (contCCont . contAux $ c) ()
econt e = (contCCont . contAux $ c) ()
in c { contCont = cont,
contAux = (contAux c) { contECont = econt } }
in c { contCont = cont,
contAux = (contAux c) { contECont = econt,
contCCont = ccont } }
throwCont :: (MonadDES m, Exception e) => e -> Cont m a
{-# INLINABLE throwCont #-}
throwCont = liftEvent . throwEvent
runCont :: MonadDES m
=> Cont m a
-> (a -> Event m ())
-> (SomeException -> Event m ())
-> (() -> Event m ())
-> ContId m
-> Bool
-> Event m ()
{-# INLINABLE runCont #-}
runCont (Cont m) cont econt ccont cid catchFlag =
m ContParams { contCont = cont,
contAux =
ContParamsAux { contECont = econt,
contCCont = ccont,
contId = cid,
contCancelRef = contCancellationActivatedRef cid,
contCatchFlag = catchFlag } }
liftWithoutCatching :: MonadDES m => m a -> Point m -> ContParams m a -> m ()
{-# INLINE liftWithoutCatching #-}
liftWithoutCatching m p c =
do z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else do a <- m
invokeEvent p $ contCont c a
liftWithCatching :: MonadDES m => m a -> Point m -> ContParams m a -> m ()
{-# NOINLINE liftWithCatching #-}
liftWithCatching m p c =
do z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else do let r = pointRun p
aref <- invokeSimulation r $ newRef undefined
eref <- invokeSimulation r $ newRef Nothing
catchComp
(m >>= invokeEvent p . writeRef aref)
(invokeEvent p . writeRef eref . Just)
e <- invokeEvent p $ readRef eref
case e of
Nothing ->
do a <- invokeEvent p $ readRef aref
invokeEvent p $ contCont c a
Just e ->
invokeEvent p $ (contECont . contAux) c e
resumeCont :: MonadDES m => ContParams m a -> a -> Event m ()
{-# INLINE resumeCont #-}
resumeCont c a =
Event $ \p ->
do z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else invokeEvent p $ contCont c a
resumeECont :: MonadDES m => ContParams m a -> SomeException -> Event m ()
{-# INLINE resumeECont #-}
resumeECont c e =
Event $ \p ->
do z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else invokeEvent p $ (contECont $ contAux c) e
contCanceled :: MonadDES m => ContParams m a -> Event m Bool
{-# INLINE contCanceled #-}
contCanceled c = readRef $ contCancelRef $ contAux c
contParallel :: MonadDES m
=> [(Cont m a, ContId m)]
-> Cont m [a]
{-# INLINABLE contParallel #-}
contParallel xs =
Cont $ \c ->
Event $ \p ->
do let n = length xs
r = pointRun p
worker =
do results <- forM [1..n] $ \i -> invokeSimulation r $ newRef undefined
counter <- invokeSimulation r $ newRef 0
catchRef <- invokeSimulation r $ newRef Nothing
hs <- invokeEvent p $
contCancellationBind (contId $ contAux c) $
map snd xs
let propagate =
Event $ \p ->
do n' <- invokeEvent p $ readRef counter
when (n' == n) $
do invokeEvent p $ disposeEvent hs
f1 <- invokeEvent p $ contCanceled c
f2 <- invokeEvent p $ readRef catchRef
case (f1, f2) of
(False, Nothing) ->
do rs <- forM results $ invokeEvent p . readRef
invokeEvent p $ resumeCont c rs
(False, Just e) ->
invokeEvent p $ resumeECont c e
(True, _) ->
invokeEvent p $ cancelCont c
cont result a =
Event $ \p ->
do invokeEvent p $ modifyRef counter (+ 1)
invokeEvent p $ writeRef result a
invokeEvent p propagate
econt e =
Event $ \p ->
do invokeEvent p $ modifyRef counter (+ 1)
r <- invokeEvent p $ readRef catchRef
case r of
Nothing -> invokeEvent p $ writeRef catchRef $ Just e
Just e' -> return ()
invokeEvent p propagate
ccont e =
Event $ \p ->
do invokeEvent p $ modifyRef counter (+ 1)
invokeEvent p propagate
forM_ (zip results xs) $ \(result, (x, cid)) ->
invokeEvent p $
runCont x (cont result) econt ccont cid (contCatchFlag $ contAux c)
z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else if n == 0
then invokeEvent p $ contCont c []
else worker
contParallel_ :: MonadDES m
=> [(Cont m a, ContId m)]
-> Cont m ()
{-# INLINABLE contParallel_ #-}
contParallel_ xs =
Cont $ \c ->
Event $ \p ->
do let n = length xs
r = pointRun p
worker =
do counter <- invokeSimulation r $ newRef 0
catchRef <- invokeSimulation r $ newRef Nothing
hs <- invokeEvent p $
contCancellationBind (contId $ contAux c) $
map snd xs
let propagate =
Event $ \p ->
do n' <- invokeEvent p $ readRef counter
when (n' == n) $
do invokeEvent p $ disposeEvent hs
f1 <- invokeEvent p $ contCanceled c
f2 <- invokeEvent p $ readRef catchRef
case (f1, f2) of
(False, Nothing) ->
invokeEvent p $ resumeCont c ()
(False, Just e) ->
invokeEvent p $ resumeECont c e
(True, _) ->
invokeEvent p $ cancelCont c
cont a =
Event $ \p ->
do invokeEvent p $ modifyRef counter (+ 1)
invokeEvent p propagate
econt e =
Event $ \p ->
do invokeEvent p $ modifyRef counter (+ 1)
r <- invokeEvent p $ readRef catchRef
case r of
Nothing -> invokeEvent p $ writeRef catchRef $ Just e
Just e' -> return ()
invokeEvent p propagate
ccont e =
Event $ \p ->
do invokeEvent p $ modifyRef counter (+ 1)
invokeEvent p propagate
forM_ (zip [0..n-1] xs) $ \(i, (x, cid)) ->
invokeEvent p $
runCont x cont econt ccont cid (contCatchFlag $ contAux c)
z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else if n == 0
then invokeEvent p $ contCont c ()
else worker
rerunCont :: MonadDES m => Cont m a -> ContId m -> Cont m a
{-# INLINABLE rerunCont #-}
rerunCont x cid =
Cont $ \c ->
Event $ \p ->
do let worker =
do hs <- invokeEvent p $
contCancellationBind (contId $ contAux c) [cid]
let cont a =
Event $ \p ->
do invokeEvent p $ disposeEvent hs
invokeEvent p $ resumeCont c a
econt e =
Event $ \p ->
do invokeEvent p $ disposeEvent hs
invokeEvent p $ resumeECont c e
ccont e =
Event $ \p ->
do invokeEvent p $ disposeEvent hs
invokeEvent p $ cancelCont c
invokeEvent p $
runCont x cont econt ccont cid (contCatchFlag $ contAux c)
z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else worker
spawnCont :: MonadDES m => ContCancellation -> Cont m () -> ContId m -> Cont m ()
{-# INLINABLE spawnCont #-}
spawnCont cancellation x cid =
Cont $ \c ->
Event $ \p ->
do let worker =
do hs <- invokeEvent p $
contCancellationConnect
(contId $ contAux c) cancellation cid
let cont a =
Event $ \p ->
do invokeEvent p $ disposeEvent hs
econt e =
Event $ \p ->
do invokeEvent p $ disposeEvent hs
invokeEvent p $ throwEvent e
ccont e =
Event $ \p ->
do invokeEvent p $ disposeEvent hs
invokeEvent p $
enqueueEvent (pointTime p) $
runCont x cont econt ccont cid False
invokeEvent p $
resumeCont c ()
z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else worker
newtype FrozenCont m a =
FrozenCont { unfreezeCont :: Event m (Maybe (ContParams m a))
}
freezeCont :: MonadDES m => ContParams m a -> Event m (FrozenCont m a)
{-# INLINABLE freezeCont #-}
freezeCont c =
Event $ \p ->
do let r = pointRun p
rh <- invokeSimulation r $ newRef Nothing
rc <- invokeSimulation r $ newRef $ Just c
h <- invokeEvent p $
handleSignal (contCancellationInitiating $
contId $
contAux c) $ \e ->
Event $ \p ->
do h <- invokeEvent p $ readRef rh
case h of
Nothing ->
error "The handler was lost: freezeCont."
Just h ->
do invokeEvent p $ disposeEvent h
c <- invokeEvent p $ readRef rc
case c of
Nothing -> return ()
Just c ->
do invokeEvent p $ writeRef rc Nothing
invokeEvent p $
enqueueEvent (pointTime p) $
Event $ \p ->
do z <- invokeEvent p $ contCanceled c
when z $ invokeEvent p $ cancelCont c
invokeEvent p $ writeRef rh (Just h)
return $
FrozenCont $
Event $ \p ->
do invokeEvent p $ disposeEvent h
c <- invokeEvent p $ readRef rc
invokeEvent p $ writeRef rc Nothing
return c
freezeContReentering :: MonadDES m => ContParams m a -> a -> Event m () -> Event m (FrozenCont m a)
{-# INLINABLE freezeContReentering #-}
freezeContReentering c a m =
Event $ \p ->
do let r = pointRun p
rh <- invokeSimulation r $ newRef Nothing
rc <- invokeSimulation r $ newRef $ Just c
h <- invokeEvent p $
handleSignal (contCancellationInitiating $
contId $ contAux c) $ \e ->
Event $ \p ->
do h <- invokeEvent p $ readRef rh
case h of
Nothing ->
error "The handler was lost: freezeContReentering."
Just h ->
do invokeEvent p $ disposeEvent h
c <- invokeEvent p $ readRef rc
case c of
Nothing -> return ()
Just c ->
do invokeEvent p $ writeRef rc Nothing
invokeEvent p $
enqueueEvent (pointTime p) $
Event $ \p ->
do z <- invokeEvent p $ contCanceled c
when z $ invokeEvent p $ cancelCont c
invokeEvent p $ writeRef rh (Just h)
return $
FrozenCont $
Event $ \p ->
do invokeEvent p $ disposeEvent h
c <- invokeEvent p $ readRef rc
invokeEvent p $ writeRef rc Nothing
case c of
Nothing -> return Nothing
z @ (Just c) ->
do f <- invokeEvent p $
contPreemptionBegun $
contId $ contAux c
if not f
then return z
else do let c = c { contCont = \a -> m }
invokeEvent p $ sleepCont c a
return Nothing
reenterCont :: MonadDES m => ContParams m a -> a -> Event m ()
{-# INLINE reenterCont #-}
reenterCont c a =
Event $ \p ->
do f <- invokeEvent p $
contPreemptionBegun $
contId $ contAux c
if not f
then invokeEvent p $
enqueueEvent (pointTime p) $
Event $ \p ->
do f <- invokeEvent p $
contPreemptionBegun $
contId $ contAux c
if not f
then invokeEvent p $
resumeCont c a
else invokeEvent p $
sleepCont c a
else invokeEvent p $
sleepCont c a
sleepCont :: MonadDES m => ContParams m a -> a -> Event m ()
{-# INLINABLE sleepCont #-}
sleepCont c a =
Event $ \p ->
do let r = pointRun p
rh <- invokeSimulation r $ newRef Nothing
h <- invokeEvent p $
handleSignal (contSignal $
contId $ contAux c) $ \e ->
Event $ \p ->
do h <- invokeEvent p $ readRef rh
case h of
Nothing ->
error "The handler was lost: sleepCont."
Just h ->
do invokeEvent p $ disposeEvent h
case e of
ContCancellationInitiating ->
invokeEvent p $
enqueueEvent (pointTime p) $
Event $ \p ->
do z <- invokeEvent p $ contCanceled c
when z $ invokeEvent p $ cancelCont c
ContPreemptionEnding ->
invokeEvent p $
enqueueEvent (pointTime p) $
reenterCont c a
ContPreemptionBeginning ->
error "The computation was already preempted: sleepCont."
invokeEvent p $ writeRef rh (Just h)
substituteCont :: MonadDES m => ContParams m a -> (a -> Event m ()) -> ContParams m a
{-# INLINE substituteCont #-}
substituteCont c m = c { contCont = m }
contAwait :: MonadDES m => Signal m a -> Cont m a
{-# INLINABLE contAwait #-}
contAwait signal =
Cont $ \c ->
Event $ \p ->
do let r = pointRun p
c <- invokeEvent p $ freezeCont c
rh <- invokeSimulation r $ newRef Nothing
h <- invokeEvent p $
handleSignal signal $
\a -> Event $
\p -> do x <- invokeEvent p $ readRef rh
case x of
Nothing ->
error "The signal was lost: contAwait."
Just x ->
do invokeEvent p $ disposeEvent x
c <- invokeEvent p $ unfreezeCont c
case c of
Nothing -> return ()
Just c ->
invokeEvent p $ reenterCont c a
invokeEvent p $ writeRef rh $ Just h
transferCont :: MonadDES m => Cont m () -> Cont m a
{-# INLINABLE transferCont #-}
transferCont x =
Cont $ \c ->
Event $ \p ->
do let worker =
do let cid = contId $ contAux c
cont = return
econt = throwEvent
ccont = return
when (contCatchFlag $ contAux c) $
error "Cannot be combined with the exception handling: unsafeTransferCont"
invokeEvent p $
runCont x cont econt ccont cid False
z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else worker
traceCont :: MonadDES m => String -> Cont m a -> Cont m a
{-# INLINABLE traceCont #-}
traceCont message (Cont m) =
Cont $ \c ->
Event $ \p ->
do z <- invokeEvent p $ contCanceled c
if z
then invokeEvent p $ cancelCont c
else trace ("t = " ++ show (pointTime p) ++ ": " ++ message) $
invokeEvent p $ m c