module Simulation.Aivika.Trans.Internal.Event
(
EventLift(..),
runEventInStartTime,
runEventInStopTime,
enqueueEventWithCancellation,
enqueueEventWithTimes,
enqueueEventWithPoints,
enqueueEventWithIntegTimes,
yieldEvent,
EventCancellation,
cancelEvent,
eventCancelled,
eventFinished,
catchEvent,
finallyEvent,
throwEvent,
memoEvent,
memoEventInTime,
DisposableEvent(..)) where
import Data.Monoid
import Control.Exception
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Fix
import Control.Applicative
import Simulation.Aivika.Trans.Exception
import Simulation.Aivika.Trans.Session
import Simulation.Aivika.Trans.ProtoRef
import Simulation.Aivika.Trans.Comp
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Parameter
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Dynamics
instance Monad m => Monad (Event m) where
return a = Event $ \p -> return a
(Event m) >>= k =
Event $ \p ->
do a <- m p
let Event m' = k a
m' p
instance Functor m => Functor (Event m) where
fmap f (Event x) = Event $ \p -> fmap f $ x p
instance Applicative m => Applicative (Event m) where
pure = Event . const . pure
(Event x) <*> (Event y) = Event $ \p -> x p <*> y p
instance MonadTrans Event where
lift = Event . const
instance MonadIO m => MonadIO (Event m) where
liftIO = Event . const . liftIO
instance MonadCompTrans Event where
liftComp = Event . const
class EventLift t where
liftEvent :: MonadComp m => Event m a -> t m a
instance EventLift Event where
liftEvent = id
instance DynamicsLift Event where
liftDynamics (Dynamics x) = Event x
instance SimulationLift Event where
liftSimulation (Simulation x) = Event $ x . pointRun
instance ParameterLift Event where
liftParameter (Parameter x) = Event $ x . pointRun
catchEvent :: (MonadComp m, Exception e) => Event m a -> (e -> Event m a) -> Event m a
catchEvent (Event m) h =
Event $ \p ->
catchComp (m p) $ \e ->
let Event m' = h e in m' p
finallyEvent :: MonadComp m => Event m a -> Event m b -> Event m a
finallyEvent (Event m) (Event m') =
Event $ \p ->
finallyComp (m p) (m' p)
throwEvent :: (MonadComp m, Exception e) => e -> Event m a
throwEvent = throw
instance MonadFix m => MonadFix (Event m) where
mfix f =
Event $ \p ->
do { rec { a <- invokeEvent p (f a) }; return a }
runEventInStartTime :: MonadComp m => Event m a -> Simulation m a
runEventInStartTime = runDynamicsInStartTime . runEvent
runEventInStopTime :: MonadComp m => Event m a -> Simulation m a
runEventInStopTime = runDynamicsInStopTime . runEvent
enqueueEventWithTimes :: MonadComp m => [Double] -> Event m () -> Event m ()
enqueueEventWithTimes ts e = loop ts
where loop [] = return ()
loop (t : ts) = enqueueEvent t $ e >> loop ts
enqueueEventWithPoints :: MonadComp m => [Point m] -> Event m () -> Event m ()
enqueueEventWithPoints xs (Event e) = loop xs
where loop [] = return ()
loop (x : xs) = enqueueEvent (pointTime x) $
Event $ \p ->
do e x
invokeEvent p $ loop xs
enqueueEventWithIntegTimes :: MonadComp m => Event m () -> Event m ()
enqueueEventWithIntegTimes e =
Event $ \p ->
let points = integPoints $ pointRun p
in invokeEvent p $ enqueueEventWithPoints points e
data EventCancellation m =
EventCancellation { cancelEvent :: Event m (),
eventCancelled :: Event m Bool,
eventFinished :: Event m Bool
}
enqueueEventWithCancellation :: MonadComp m => Double -> Event m () -> Event m (EventCancellation m)
enqueueEventWithCancellation t e =
Event $ \p ->
do let s = runSession $ pointRun p
cancelledRef <- newProtoRef s False
cancellableRef <- newProtoRef s True
finishedRef <- newProtoRef s False
let cancel =
Event $ \p ->
do x <- readProtoRef cancellableRef
when x $
writeProtoRef cancelledRef True
cancelled =
Event $ \p -> readProtoRef cancelledRef
finished =
Event $ \p -> readProtoRef finishedRef
invokeEvent p $
enqueueEvent t $
Event $ \p ->
do writeProtoRef cancellableRef False
x <- readProtoRef cancelledRef
unless x $
do invokeEvent p e
writeProtoRef finishedRef True
return EventCancellation { cancelEvent = cancel,
eventCancelled = cancelled,
eventFinished = finished }
memoEvent :: MonadComp m => Event m a -> Simulation m (Event m a)
memoEvent m =
Simulation $ \r ->
do let s = runSession r
ref <- newProtoRef s Nothing
return $ Event $ \p ->
do x <- readProtoRef ref
case x of
Just v -> return v
Nothing ->
do v <- invokeEvent p m
writeProtoRef ref (Just v)
return v
memoEventInTime :: MonadComp m => Event m a -> Simulation m (Event m a)
memoEventInTime m =
Simulation $ \r ->
do let s = runSession r
ref <- newProtoRef s Nothing
return $ Event $ \p ->
do x <- readProtoRef ref
case x of
Just (t, v) | t == pointTime p ->
return v
_ ->
do v <- invokeEvent p m
writeProtoRef ref (Just (pointTime p, v))
return v
yieldEvent :: MonadComp m => Event m () -> Event m ()
yieldEvent m =
Event $ \p ->
invokeEvent p $
enqueueEvent (pointTime p) m
newtype DisposableEvent m =
DisposableEvent { disposeEvent :: Event m ()
}
instance Monad m => Monoid (DisposableEvent m) where
mempty = DisposableEvent $ return ()
mappend (DisposableEvent x) (DisposableEvent y) = DisposableEvent $ x >> y