module Simulation.Aivika.Trans.Server
(
Server,
newServer,
newStateServer,
serverProcessor,
serverInitState,
serverState,
serverTotalInputWaitTime,
serverTotalProcessingTime,
serverTotalOutputWaitTime,
serverInputWaitTime,
serverProcessingTime,
serverOutputWaitTime,
serverInputWaitFactor,
serverProcessingFactor,
serverOutputWaitFactor,
serverSummary,
serverStateChanged,
serverStateChanged_,
serverTotalInputWaitTimeChanged,
serverTotalInputWaitTimeChanged_,
serverTotalProcessingTimeChanged,
serverTotalProcessingTimeChanged_,
serverTotalOutputWaitTimeChanged,
serverTotalOutputWaitTimeChanged_,
serverInputWaitTimeChanged,
serverInputWaitTimeChanged_,
serverProcessingTimeChanged,
serverProcessingTimeChanged_,
serverOutputWaitTimeChanged,
serverOutputWaitTimeChanged_,
serverInputWaitFactorChanged,
serverInputWaitFactorChanged_,
serverProcessingFactorChanged,
serverProcessingFactorChanged_,
serverOutputWaitFactorChanged,
serverOutputWaitFactorChanged_,
serverInputReceived,
serverTaskProcessed,
serverOutputProvided,
serverChanged_) where
import Data.Monoid
import Control.Arrow
import Simulation.Aivika.Trans.Session
import Simulation.Aivika.Trans.ProtoRef
import Simulation.Aivika.Trans.Comp
import Simulation.Aivika.Trans.Parameter
import Simulation.Aivika.Trans.Simulation
import Simulation.Aivika.Trans.Dynamics
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Internal.Signal
import Simulation.Aivika.Trans.Resource
import Simulation.Aivika.Trans.Cont
import Simulation.Aivika.Trans.Process
import Simulation.Aivika.Trans.Processor
import Simulation.Aivika.Trans.Stream
import Simulation.Aivika.Trans.Statistics
data Server m s a b =
Server { serverInitState :: s,
serverStateRef :: ProtoRef m s,
serverProcess :: s -> a -> Process m (s, b),
serverTotalInputWaitTimeRef :: ProtoRef m Double,
serverTotalProcessingTimeRef :: ProtoRef m Double,
serverTotalOutputWaitTimeRef :: ProtoRef m Double,
serverInputWaitTimeRef :: ProtoRef m (SamplingStats Double),
serverProcessingTimeRef :: ProtoRef m (SamplingStats Double),
serverOutputWaitTimeRef :: ProtoRef m (SamplingStats Double),
serverInputReceivedSource :: SignalSource m a,
serverTaskProcessedSource :: SignalSource m (a, b),
serverOutputProvidedSource :: SignalSource m (a, b)
}
newServer :: MonadComp m
=> (a -> Process m b)
-> Simulation m (Server m () a b)
newServer provide =
flip newStateServer () $ \s a ->
do b <- provide a
return (s, b)
newStateServer :: MonadComp m
=> (s -> a -> Process m (s, b))
-> s
-> Simulation m (Server m s a b)
newStateServer provide state =
do sn <- liftParameter simulationSession
r0 <- liftComp $ newProtoRef sn state
r1 <- liftComp $ newProtoRef sn 0
r2 <- liftComp $ newProtoRef sn 0
r3 <- liftComp $ newProtoRef sn 0
r4 <- liftComp $ newProtoRef sn emptySamplingStats
r5 <- liftComp $ newProtoRef sn emptySamplingStats
r6 <- liftComp $ newProtoRef sn emptySamplingStats
s1 <- newSignalSource
s2 <- newSignalSource
s3 <- newSignalSource
let server = Server { serverInitState = state,
serverStateRef = r0,
serverProcess = provide,
serverTotalInputWaitTimeRef = r1,
serverTotalProcessingTimeRef = r2,
serverTotalOutputWaitTimeRef = r3,
serverInputWaitTimeRef = r4,
serverProcessingTimeRef = r5,
serverOutputWaitTimeRef = r6,
serverInputReceivedSource = s1,
serverTaskProcessedSource = s2,
serverOutputProvidedSource = s3 }
return server
serverProcessor :: MonadComp m => Server m s a b -> Processor m 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 liftComp $
do modifyProtoRef' (serverTotalOutputWaitTimeRef server) (+ (t0 t'))
modifyProtoRef' (serverOutputWaitTimeRef server) $
addSamplingStats (t0 t')
triggerSignal (serverOutputProvidedSource server) (a', b')
(a, xs') <- runStream xs
t1 <- liftDynamics time
liftEvent $
do liftComp $
do modifyProtoRef' (serverTotalInputWaitTimeRef server) (+ (t1 t0))
modifyProtoRef' (serverInputWaitTimeRef server) $
addSamplingStats (t1 t0)
triggerSignal (serverInputReceivedSource server) a
(s', b) <- serverProcess server s a
t2 <- liftDynamics time
liftEvent $
do liftComp $
do writeProtoRef (serverStateRef server) $! s'
modifyProtoRef' (serverTotalProcessingTimeRef server) (+ (t2 t1))
modifyProtoRef' (serverProcessingTimeRef server) $
addSamplingStats (t2 t1)
triggerSignal (serverTaskProcessedSource server) (a, b)
return (b, loop s' (Just (t2, a, b)) xs')
serverState :: MonadComp m => Server m s a b -> Event m s
serverState server =
Event $ \p -> readProtoRef (serverStateRef server)
serverStateChanged :: MonadComp m => Server m s a b -> Signal m s
serverStateChanged server =
mapSignalM (const $ serverState server) (serverStateChanged_ server)
serverStateChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverStateChanged_ server =
mapSignal (const ()) (serverTaskProcessed server)
serverTotalInputWaitTime :: MonadComp m => Server m s a b -> Event m Double
serverTotalInputWaitTime server =
Event $ \p -> readProtoRef (serverTotalInputWaitTimeRef server)
serverTotalInputWaitTimeChanged :: MonadComp m => Server m s a b -> Signal m Double
serverTotalInputWaitTimeChanged server =
mapSignalM (const $ serverTotalInputWaitTime server) (serverTotalInputWaitTimeChanged_ server)
serverTotalInputWaitTimeChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverTotalInputWaitTimeChanged_ server =
mapSignal (const ()) (serverInputReceived server)
serverTotalProcessingTime :: MonadComp m => Server m s a b -> Event m Double
serverTotalProcessingTime server =
Event $ \p -> readProtoRef (serverTotalProcessingTimeRef server)
serverTotalProcessingTimeChanged :: MonadComp m => Server m s a b -> Signal m Double
serverTotalProcessingTimeChanged server =
mapSignalM (const $ serverTotalProcessingTime server) (serverTotalProcessingTimeChanged_ server)
serverTotalProcessingTimeChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverTotalProcessingTimeChanged_ server =
mapSignal (const ()) (serverTaskProcessed server)
serverTotalOutputWaitTime :: MonadComp m => Server m s a b -> Event m Double
serverTotalOutputWaitTime server =
Event $ \p -> readProtoRef (serverTotalOutputWaitTimeRef server)
serverTotalOutputWaitTimeChanged :: MonadComp m => Server m s a b -> Signal m Double
serverTotalOutputWaitTimeChanged server =
mapSignalM (const $ serverTotalOutputWaitTime server) (serverTotalOutputWaitTimeChanged_ server)
serverTotalOutputWaitTimeChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverTotalOutputWaitTimeChanged_ server =
mapSignal (const ()) (serverOutputProvided server)
serverInputWaitTime :: MonadComp m => Server m s a b -> Event m (SamplingStats Double)
serverInputWaitTime server =
Event $ \p -> readProtoRef (serverInputWaitTimeRef server)
serverInputWaitTimeChanged :: MonadComp m => Server m s a b -> Signal m (SamplingStats Double)
serverInputWaitTimeChanged server =
mapSignalM (const $ serverInputWaitTime server) (serverInputWaitTimeChanged_ server)
serverInputWaitTimeChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverInputWaitTimeChanged_ server =
mapSignal (const ()) (serverInputReceived server)
serverProcessingTime :: MonadComp m => Server m s a b -> Event m (SamplingStats Double)
serverProcessingTime server =
Event $ \p -> readProtoRef (serverProcessingTimeRef server)
serverProcessingTimeChanged :: MonadComp m => Server m s a b -> Signal m (SamplingStats Double)
serverProcessingTimeChanged server =
mapSignalM (const $ serverProcessingTime server) (serverProcessingTimeChanged_ server)
serverProcessingTimeChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverProcessingTimeChanged_ server =
mapSignal (const ()) (serverTaskProcessed server)
serverOutputWaitTime :: MonadComp m => Server m s a b -> Event m (SamplingStats Double)
serverOutputWaitTime server =
Event $ \p -> readProtoRef (serverOutputWaitTimeRef server)
serverOutputWaitTimeChanged :: MonadComp m => Server m s a b -> Signal m (SamplingStats Double)
serverOutputWaitTimeChanged server =
mapSignalM (const $ serverOutputWaitTime server) (serverOutputWaitTimeChanged_ server)
serverOutputWaitTimeChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverOutputWaitTimeChanged_ server =
mapSignal (const ()) (serverOutputProvided server)
serverInputWaitFactor :: MonadComp m => Server m s a b -> Event m Double
serverInputWaitFactor server =
Event $ \p ->
do x1 <- readProtoRef (serverTotalInputWaitTimeRef server)
x2 <- readProtoRef (serverTotalProcessingTimeRef server)
x3 <- readProtoRef (serverTotalOutputWaitTimeRef server)
return (x1 / (x1 + x2 + x3))
serverInputWaitFactorChanged :: MonadComp m => Server m s a b -> Signal m Double
serverInputWaitFactorChanged server =
mapSignalM (const $ serverInputWaitFactor server) (serverInputWaitFactorChanged_ server)
serverInputWaitFactorChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverInputWaitFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server)
serverProcessingFactor :: MonadComp m => Server m s a b -> Event m Double
serverProcessingFactor server =
Event $ \p ->
do x1 <- readProtoRef (serverTotalInputWaitTimeRef server)
x2 <- readProtoRef (serverTotalProcessingTimeRef server)
x3 <- readProtoRef (serverTotalOutputWaitTimeRef server)
return (x2 / (x1 + x2 + x3))
serverProcessingFactorChanged :: MonadComp m => Server m s a b -> Signal m Double
serverProcessingFactorChanged server =
mapSignalM (const $ serverProcessingFactor server) (serverProcessingFactorChanged_ server)
serverProcessingFactorChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverProcessingFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server)
serverOutputWaitFactor :: MonadComp m => Server m s a b -> Event m Double
serverOutputWaitFactor server =
Event $ \p ->
do x1 <- readProtoRef (serverTotalInputWaitTimeRef server)
x2 <- readProtoRef (serverTotalProcessingTimeRef server)
x3 <- readProtoRef (serverTotalOutputWaitTimeRef server)
return (x3 / (x1 + x2 + x3))
serverOutputWaitFactorChanged :: MonadComp m => Server m s a b -> Signal m Double
serverOutputWaitFactorChanged server =
mapSignalM (const $ serverOutputWaitFactor server) (serverOutputWaitFactorChanged_ server)
serverOutputWaitFactorChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverOutputWaitFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server)
serverInputReceived :: MonadComp m => Server m s a b -> Signal m a
serverInputReceived = publishSignal . serverInputReceivedSource
serverTaskProcessed :: MonadComp m => Server m s a b -> Signal m (a, b)
serverTaskProcessed = publishSignal . serverTaskProcessedSource
serverOutputProvided :: MonadComp m => Server m s a b -> Signal m (a, b)
serverOutputProvided = publishSignal . serverOutputProvidedSource
serverChanged_ :: MonadComp m => Server m s a b -> Signal m ()
serverChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server)
serverSummary :: MonadComp m => Server m s a b -> Int -> Event m ShowS
serverSummary server indent =
Event $ \p ->
do tx1 <- readProtoRef (serverTotalInputWaitTimeRef server)
tx2 <- readProtoRef (serverTotalProcessingTimeRef server)
tx3 <- readProtoRef (serverTotalOutputWaitTimeRef server)
let xf1 = tx1 / (tx1 + tx2 + tx3)
xf2 = tx2 / (tx1 + tx2 + tx3)
xf3 = tx3 / (tx1 + tx2 + tx3)
xs1 <- readProtoRef (serverInputWaitTimeRef server)
xs2 <- readProtoRef (serverProcessingTimeRef server)
xs3 <- readProtoRef (serverOutputWaitTimeRef server)
let tab = replicate indent ' '
return $
showString tab .
showString "total input wait time (locked while awaiting the input) = " . shows tx1 .
showString "\n" .
showString tab .
showString "total processing time = " . shows tx2 .
showString "\n" .
showString tab .
showString "total output wait time (locked while delivering the output) = " . shows tx3 .
showString "\n\n" .
showString tab .
showString "input wait factor (from 0 to 1) = " . shows xf1 .
showString "\n" .
showString tab .
showString "processing factor (from 0 to 1) = " . shows xf2 .
showString "\n" .
showString tab .
showString "output wait factor (from 0 to 1) = " . shows xf3 .
showString "\n\n" .
showString tab .
showString "input wait time (locked while awaiting the input):\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 wait time (locked while delivering the output):\n\n" .
samplingStatsSummary xs3 (2 + indent)