-- | -- Module : Simulation.Aivika.RealTime.RT -- Copyright : Copyright (c) 2016, David Sorokin -- License : BSD3 -- Maintainer : David Sorokin -- 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