aivika-realtime-0.1: Simulation/Aivika/RealTime/RT.hs
-- |
-- Module : Simulation.Aivika.RealTime.RT
-- Copyright : Copyright (c) 2016, David Sorokin <david.sorokin@gmail.com>
-- License : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability : experimental
-- Tested with: GHC 8.0.1
--
-- This module defines a soft real-time computation based on 'IO'.
--
module Simulation.Aivika.RealTime.RT
(-- * Soft real-time computation
RT,
RTParams(..),
RTContext,
RTScaling(..),
runRT,
defaultRTParams,
newRTContext,
rtParams,
rtScale,
-- * Invoking actions within the simulation
applyEventRT,
applyEventRT_,
enqueueEventRT,
enqueueEventRT_) where
import Control.Monad
import Control.Monad.Trans
import Control.Concurrent.STM
import Control.Concurrent.Async
import Simulation.Aivika.Trans
import Simulation.Aivika.IO.Comp
import Simulation.Aivika.IO.Ref.Base
import Simulation.Aivika.IO.QueueStrategy
import Simulation.Aivika.IO.Exception
import Simulation.Aivika.RealTime.Internal.RT
import Simulation.Aivika.RealTime.Internal.Channel
import Simulation.Aivika.RealTime.Event
-- | An implementation of the 'MonadTemplate' type class.
instance (Monad m, MonadIO m, MonadException m) => MonadTemplate (RT m)
-- | An implementation of the 'MonadDES' type class.
instance (Monad m, MonadIO m, MonadException m) => MonadDES (RT m) where
{-# SPECIALIZE instance MonadDES (RT IO) #-}
-- | An implementation of the 'EventIOQueueing' type class.
instance (Monad m, MonadIO m, MonadException m) => EventIOQueueing (RT m) where
{-# SPECIALIZE instance EventIOQueueing (RT IO) #-}
enqueueEventIO = enqueueEvent
-- | Invoke the action within the soft real-time simulation.
invokeEventRT_ :: MonadIO m
=> RTContext m
-- ^ the computation context
-> (Event (RT m) () -> Event (RT m) ())
-- ^ the computation transform
-> Event (RT m) ()
-- ^ the computation to invoke
-> m ()
-- ^ the action of invoking the computation
{-# INLINABLE invokeEventRT_ #-}
invokeEventRT_ ctx f m =
let ch = rtChannel0 ctx
in liftIO $ writeChannel ch $ f m
-- | Invoke the action within the soft real-time simulation.
invokeEventRT :: MonadIO m
=> RTContext m
-- ^ the computation context
-> (Event (RT m) () -> Event (RT m) ())
-- ^ the computation transform
-> Event (RT m) a
-- ^ the computation to invoke
-> m (Async a)
-- ^ the result of computation
{-# INLINABLE invokeEventRT #-}
invokeEventRT ctx f m =
do let ch = rtChannel0 ctx
v <- liftIO $ newTVarIO Nothing
liftIO $
writeChannel ch $
f $
do a <- m
liftIO $
atomically $
writeTVar v (Just a)
liftIO $
async $
atomically $
do b <- readTVar v
case b of
Just a -> return a
Nothing -> retry
-- | Apply the 'Event' computation within the soft real-time simulation
-- with the specified context and return the result.
applyEventRT :: MonadIO m => RTContext m -> Event (RT m) a -> m (Async a)
{-# INLINABLE applyEventRT #-}
applyEventRT ctx m = invokeEventRT ctx id m
-- | Apply the 'Event' computation within the soft real-time simulation
-- with the specified context.
applyEventRT_ :: MonadIO m => RTContext m -> Event (RT m) () -> m ()
{-# INLINABLE applyEventRT_ #-}
applyEventRT_ ctx m = invokeEventRT_ ctx id m
-- | Enqueue the 'Event' computation within the soft real-time simulation
-- with the specified context at the modeling time provided and
-- then return the result.
enqueueEventRT :: MonadIO m => RTContext m -> Double -> Event (RT m) a -> m (Async a)
{-# INLINABLE enqueueEventRT #-}
enqueueEventRT ctx t m = invokeEventRT ctx (enqueueEvent t) m
-- | Enqueue the 'Event' computation within the soft real-time simulation
-- with the specified context at the modeling time provided.
enqueueEventRT_ :: MonadIO m => RTContext m -> Double -> Event (RT m) () -> m ()
{-# INLINABLE enqueueEventRT_ #-}
enqueueEventRT_ ctx t m = invokeEventRT_ ctx (enqueueEvent t) m