module Simulation.Aivika.Server
(
Server,
newServer,
newServerWithState,
serverProcessor,
serverInitState,
serverState,
serverTotalInputTime,
serverTotalProcessingTime,
serverTotalOutputTime,
serverInputTime,
serverProcessingTime,
serverOutputTime,
serverInputTimeFactor,
serverProcessingTimeFactor,
serverOutputTimeFactor,
serverSummary,
serverStateChanged,
serverStateChanged_,
serverTotalInputTimeChanged,
serverTotalInputTimeChanged_,
serverTotalProcessingTimeChanged,
serverTotalProcessingTimeChanged_,
serverTotalOutputTimeChanged,
serverTotalOutputTimeChanged_,
serverInputTimeChanged,
serverInputTimeChanged_,
serverProcessingTimeChanged,
serverProcessingTimeChanged_,
serverOutputTimeChanged,
serverOutputTimeChanged_,
serverInputTimeFactorChanged,
serverInputTimeFactorChanged_,
serverProcessingTimeFactorChanged,
serverProcessingTimeFactorChanged_,
serverOutputTimeFactorChanged,
serverOutputTimeFactorChanged_,
serverInputReceived,
serverTaskProcessed,
serverOutputProvided,
serverChanged_) where
import Data.IORef
import Data.Monoid
import Control.Monad.Trans
import Simulation.Aivika.Simulation
import Simulation.Aivika.Dynamics
import Simulation.Aivika.Internal.Event
import Simulation.Aivika.Internal.Signal
import Simulation.Aivika.Resource
import Simulation.Aivika.Cont
import Simulation.Aivika.Process
import Simulation.Aivika.Processor
import Simulation.Aivika.Stream
import Simulation.Aivika.Statistics
data Server s a b =
Server { serverInitState :: s,
serverStateRef :: IORef s,
serverProcess :: (s, a) -> Process (s, b),
serverTotalInputTimeRef :: IORef Double,
serverTotalProcessingTimeRef :: IORef Double,
serverTotalOutputTimeRef :: IORef Double,
serverInputTimeRef :: IORef (SamplingStats Double),
serverProcessingTimeRef :: IORef (SamplingStats Double),
serverOutputTimeRef :: IORef (SamplingStats Double),
serverInputReceivedSource :: SignalSource a,
serverTaskProcessedSource :: SignalSource (a, b),
serverOutputProvidedSource :: SignalSource (a, b)
}
newServer :: (a -> Process b)
-> Simulation (Server () a b)
newServer provide =
newServerWithState () $ \(s, a) ->
do b <- provide a
return (s, b)
newServerWithState :: s
-> ((s, a) -> Process (s, b))
-> Simulation (Server s a b)
newServerWithState state provide =
do r0 <- liftIO $ newIORef state
r1 <- liftIO $ newIORef 0
r2 <- liftIO $ newIORef 0
r3 <- liftIO $ newIORef 0
r4 <- liftIO $ newIORef emptySamplingStats
r5 <- liftIO $ newIORef emptySamplingStats
r6 <- liftIO $ newIORef emptySamplingStats
s1 <- newSignalSource
s2 <- newSignalSource
s3 <- newSignalSource
let server = Server { serverInitState = state,
serverStateRef = r0,
serverProcess = provide,
serverTotalInputTimeRef = r1,
serverTotalProcessingTimeRef = r2,
serverTotalOutputTimeRef = r3,
serverInputTimeRef = r4,
serverProcessingTimeRef = r5,
serverOutputTimeRef = r6,
serverInputReceivedSource = s1,
serverTaskProcessedSource = s2,
serverOutputProvidedSource = s3 }
return server
serverProcessor :: Server s a b -> Processor a b
serverProcessor server =
Processor $ \xs -> loop (serverInitState server) Nothing xs
where
loop s r xs =
Cons $
do t0 <- liftDynamics time
liftEvent $
case r of
Nothing -> return ()
Just (t', a', b') ->
do liftIO $
do modifyIORef (serverTotalOutputTimeRef server) (+ (t0 t'))
modifyIORef (serverOutputTimeRef server) $
addSamplingStats (t0 t')
triggerSignal (serverOutputProvidedSource server) (a', b')
(a, xs') <- runStream xs
t1 <- liftDynamics time
liftEvent $
do liftIO $
do modifyIORef (serverTotalInputTimeRef server) (+ (t1 t0))
modifyIORef (serverInputTimeRef server) $
addSamplingStats (t1 t0)
triggerSignal (serverInputReceivedSource server) a
(s', b) <- serverProcess server (s, a)
t2 <- liftDynamics time
liftEvent $
do liftIO $
do writeIORef (serverStateRef server) s'
modifyIORef (serverTotalProcessingTimeRef server) (+ (t2 t1))
modifyIORef (serverProcessingTimeRef server) $
addSamplingStats (t2 t1)
triggerSignal (serverTaskProcessedSource server) (a, b)
return (b, loop s' (Just $ (t2, a, b)) xs')
serverState :: Server s a b -> Event s
serverState server =
Event $ \p -> readIORef (serverStateRef server)
serverStateChanged :: Server s a b -> Signal s
serverStateChanged server =
mapSignalM (const $ serverState server) (serverStateChanged_ server)
serverStateChanged_ :: Server s a b -> Signal ()
serverStateChanged_ server =
mapSignal (const ()) (serverTaskProcessed server)
serverTotalInputTime :: Server s a b -> Event Double
serverTotalInputTime server =
Event $ \p -> readIORef (serverTotalInputTimeRef server)
serverTotalInputTimeChanged :: Server s a b -> Signal Double
serverTotalInputTimeChanged server =
mapSignalM (const $ serverTotalInputTime server) (serverTotalInputTimeChanged_ server)
serverTotalInputTimeChanged_ :: Server s a b -> Signal ()
serverTotalInputTimeChanged_ server =
mapSignal (const ()) (serverInputReceived server)
serverTotalProcessingTime :: Server s a b -> Event Double
serverTotalProcessingTime server =
Event $ \p -> readIORef (serverTotalProcessingTimeRef server)
serverTotalProcessingTimeChanged :: Server s a b -> Signal Double
serverTotalProcessingTimeChanged server =
mapSignalM (const $ serverTotalProcessingTime server) (serverTotalProcessingTimeChanged_ server)
serverTotalProcessingTimeChanged_ :: Server s a b -> Signal ()
serverTotalProcessingTimeChanged_ server =
mapSignal (const ()) (serverTaskProcessed server)
serverTotalOutputTime :: Server s a b -> Event Double
serverTotalOutputTime server =
Event $ \p -> readIORef (serverTotalOutputTimeRef server)
serverTotalOutputTimeChanged :: Server s a b -> Signal Double
serverTotalOutputTimeChanged server =
mapSignalM (const $ serverTotalOutputTime server) (serverTotalOutputTimeChanged_ server)
serverTotalOutputTimeChanged_ :: Server s a b -> Signal ()
serverTotalOutputTimeChanged_ server =
mapSignal (const ()) (serverOutputProvided server)
serverInputTime :: Server s a b -> Event (SamplingStats Double)
serverInputTime server =
Event $ \p -> readIORef (serverInputTimeRef server)
serverInputTimeChanged :: Server s a b -> Signal (SamplingStats Double)
serverInputTimeChanged server =
mapSignalM (const $ serverInputTime server) (serverInputTimeChanged_ server)
serverInputTimeChanged_ :: Server s a b -> Signal ()
serverInputTimeChanged_ server =
mapSignal (const ()) (serverInputReceived server)
serverProcessingTime :: Server s a b -> Event (SamplingStats Double)
serverProcessingTime server =
Event $ \p -> readIORef (serverProcessingTimeRef server)
serverProcessingTimeChanged :: Server s a b -> Signal (SamplingStats Double)
serverProcessingTimeChanged server =
mapSignalM (const $ serverProcessingTime server) (serverProcessingTimeChanged_ server)
serverProcessingTimeChanged_ :: Server s a b -> Signal ()
serverProcessingTimeChanged_ server =
mapSignal (const ()) (serverTaskProcessed server)
serverOutputTime :: Server s a b -> Event (SamplingStats Double)
serverOutputTime server =
Event $ \p -> readIORef (serverOutputTimeRef server)
serverOutputTimeChanged :: Server s a b -> Signal (SamplingStats Double)
serverOutputTimeChanged server =
mapSignalM (const $ serverOutputTime server) (serverOutputTimeChanged_ server)
serverOutputTimeChanged_ :: Server s a b -> Signal ()
serverOutputTimeChanged_ server =
mapSignal (const ()) (serverOutputProvided server)
serverInputTimeFactor :: Server s a b -> Event Double
serverInputTimeFactor server =
Event $ \p ->
do x1 <- readIORef (serverTotalInputTimeRef server)
x2 <- readIORef (serverTotalProcessingTimeRef server)
x3 <- readIORef (serverTotalOutputTimeRef server)
return (x1 / (x1 + x2 + x3))
serverInputTimeFactorChanged :: Server s a b -> Signal Double
serverInputTimeFactorChanged server =
mapSignalM (const $ serverInputTimeFactor server) (serverInputTimeFactorChanged_ server)
serverInputTimeFactorChanged_ :: Server s a b -> Signal ()
serverInputTimeFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server)
serverProcessingTimeFactor :: Server s a b -> Event Double
serverProcessingTimeFactor server =
Event $ \p ->
do x1 <- readIORef (serverTotalInputTimeRef server)
x2 <- readIORef (serverTotalProcessingTimeRef server)
x3 <- readIORef (serverTotalOutputTimeRef server)
return (x2 / (x1 + x2 + x3))
serverProcessingTimeFactorChanged :: Server s a b -> Signal Double
serverProcessingTimeFactorChanged server =
mapSignalM (const $ serverProcessingTimeFactor server) (serverProcessingTimeFactorChanged_ server)
serverProcessingTimeFactorChanged_ :: Server s a b -> Signal ()
serverProcessingTimeFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server)
serverOutputTimeFactor :: Server s a b -> Event Double
serverOutputTimeFactor server =
Event $ \p ->
do x1 <- readIORef (serverTotalInputTimeRef server)
x2 <- readIORef (serverTotalProcessingTimeRef server)
x3 <- readIORef (serverTotalOutputTimeRef server)
return (x3 / (x1 + x2 + x3))
serverOutputTimeFactorChanged :: Server s a b -> Signal Double
serverOutputTimeFactorChanged server =
mapSignalM (const $ serverOutputTimeFactor server) (serverOutputTimeFactorChanged_ server)
serverOutputTimeFactorChanged_ :: Server s a b -> Signal ()
serverOutputTimeFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server)
serverInputReceived :: Server s a b -> Signal a
serverInputReceived = publishSignal . serverInputReceivedSource
serverTaskProcessed :: Server s a b -> Signal (a, b)
serverTaskProcessed = publishSignal . serverTaskProcessedSource
serverOutputProvided :: Server s a b -> Signal (a, b)
serverOutputProvided = publishSignal . serverOutputProvidedSource
serverChanged_ :: Server s a b -> Signal ()
serverChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server)
serverSummary :: Server s a b -> Int -> Event ShowS
serverSummary server indent =
Event $ \p ->
do tx1 <- readIORef (serverTotalInputTimeRef server)
tx2 <- readIORef (serverTotalProcessingTimeRef server)
tx3 <- readIORef (serverTotalOutputTimeRef server)
let xf1 = tx1 / (tx1 + tx2 + tx3)
xf2 = tx2 / (tx1 + tx2 + tx3)
xf3 = tx3 / (tx1 + tx2 + tx3)
xs1 <- readIORef (serverInputTimeRef server)
xs2 <- readIORef (serverProcessingTimeRef server)
xs3 <- readIORef (serverOutputTimeRef server)
let tab = replicate indent ' '
return $
showString tab .
showString "total input time (in awaiting the input) = " . shows tx1 .
showString "\n" .
showString tab .
showString "total processing time = " . shows tx2 .
showString "\n" .
showString tab .
showString "total output time (to deliver the output) = " . shows tx3 .
showString "\n\n" .
showString tab .
showString "input time factor (from 0 to 1) = " . shows xf1 .
showString "\n" .
showString tab .
showString "processing time factor (from 0 to 1) = " . shows xf2 .
showString "\n" .
showString tab .
showString "output time factor (from 0 to 1) = " . shows xf3 .
showString "\n\n" .
showString tab .
showString "input time:\n\n" .
samplingStatsSummary xs1 (2 + indent) .
showString "\n\n" .
showString tab .
showString "processing time:\n\n" .
samplingStatsSummary xs2 (2 + indent) .
showString "\n\n" .
showString tab .
showString "output time:\n\n" .
samplingStatsSummary xs3 (2 + indent)