module Simulation.Aivika.Trans.Server
(
Server,
newServer,
newStateServer,
newPreemptibleServer,
newPreemptibleStateServer,
serverProcessor,
serverInitState,
serverState,
serverTotalInputWaitTime,
serverTotalProcessingTime,
serverTotalOutputWaitTime,
serverTotalPreemptionTime,
serverInputWaitTime,
serverProcessingTime,
serverOutputWaitTime,
serverPreemptionTime,
serverInputWaitFactor,
serverProcessingFactor,
serverOutputWaitFactor,
serverPreemptionFactor,
resetServer,
serverSummary,
serverStateChanged,
serverStateChanged_,
serverTotalInputWaitTimeChanged,
serverTotalInputWaitTimeChanged_,
serverTotalProcessingTimeChanged,
serverTotalProcessingTimeChanged_,
serverTotalOutputWaitTimeChanged,
serverTotalOutputWaitTimeChanged_,
serverTotalPreemptionTimeChanged,
serverTotalPreemptionTimeChanged_,
serverInputWaitTimeChanged,
serverInputWaitTimeChanged_,
serverProcessingTimeChanged,
serverProcessingTimeChanged_,
serverOutputWaitTimeChanged,
serverOutputWaitTimeChanged_,
serverPreemptionTimeChanged,
serverPreemptionTimeChanged_,
serverInputWaitFactorChanged,
serverInputWaitFactorChanged_,
serverProcessingFactorChanged,
serverProcessingFactorChanged_,
serverOutputWaitFactorChanged,
serverOutputWaitFactorChanged_,
serverPreemptionFactorChanged,
serverPreemptionFactorChanged_,
serverInputReceived,
serverTaskPreemptionBeginning,
serverTaskPreemptionEnding,
serverTaskProcessed,
serverOutputProvided,
serverChanged_) where
import Data.Monoid
import Control.Monad
import Control.Arrow
import Simulation.Aivika.Trans.Ref.Base
import Simulation.Aivika.Trans.DES
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.Signal
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 :: Ref m s,
serverProcess :: s -> a -> Process m (s, b),
serverProcessPreemptible :: Bool,
serverTotalInputWaitTimeRef :: Ref m Double,
serverTotalProcessingTimeRef :: Ref m Double,
serverTotalOutputWaitTimeRef :: Ref m Double,
serverTotalPreemptionTimeRef :: Ref m Double,
serverInputWaitTimeRef :: Ref m (SamplingStats Double),
serverProcessingTimeRef :: Ref m (SamplingStats Double),
serverOutputWaitTimeRef :: Ref m (SamplingStats Double),
serverPreemptionTimeRef :: Ref m (SamplingStats Double),
serverInputReceivedSource :: SignalSource m a,
serverTaskPreemptionBeginningSource :: SignalSource m a,
serverTaskPreemptionEndingSource :: SignalSource m a,
serverTaskProcessedSource :: SignalSource m (a, b),
serverOutputProvidedSource :: SignalSource m (a, b)
}
newServer :: MonadDES m
=> (a -> Process m b)
-> Simulation m (Server m () a b)
newServer = newPreemptibleServer False
newStateServer :: MonadDES m
=> (s -> a -> Process m (s, b))
-> s
-> Simulation m (Server m s a b)
newStateServer = newPreemptibleStateServer False
newPreemptibleServer :: MonadDES m
=> Bool
-> (a -> Process m b)
-> Simulation m (Server m () a b)
newPreemptibleServer preemptible provide =
flip (newPreemptibleStateServer preemptible) () $ \s a ->
do b <- provide a
return (s, b)
newPreemptibleStateServer :: MonadDES m
=> Bool
-> (s -> a -> Process m (s, b))
-> s
-> Simulation m (Server m s a b)
newPreemptibleStateServer preemptible provide state =
do r0 <- newRef state
r1 <- newRef 0
r2 <- newRef 0
r3 <- newRef 0
r4 <- newRef 0
r5 <- newRef emptySamplingStats
r6 <- newRef emptySamplingStats
r7 <- newRef emptySamplingStats
r8 <- newRef emptySamplingStats
s1 <- newSignalSource
s2 <- newSignalSource
s3 <- newSignalSource
s4 <- newSignalSource
s5 <- newSignalSource
let server = Server { serverInitState = state,
serverStateRef = r0,
serverProcess = provide,
serverProcessPreemptible = preemptible,
serverTotalInputWaitTimeRef = r1,
serverTotalProcessingTimeRef = r2,
serverTotalOutputWaitTimeRef = r3,
serverTotalPreemptionTimeRef = r4,
serverInputWaitTimeRef = r5,
serverProcessingTimeRef = r6,
serverOutputWaitTimeRef = r7,
serverPreemptionTimeRef = r8,
serverInputReceivedSource = s1,
serverTaskPreemptionBeginningSource = s2,
serverTaskPreemptionEndingSource = s3,
serverTaskProcessedSource = s4,
serverOutputProvidedSource = s5 }
return server
serverProcessor :: MonadDES 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 modifyRef (serverTotalOutputWaitTimeRef server) (+ (t0 t'))
modifyRef (serverOutputWaitTimeRef server) $
addSamplingStats (t0 t')
triggerSignal (serverOutputProvidedSource server) (a', b')
(a, xs') <- runStream xs
t1 <- liftDynamics time
liftEvent $
do modifyRef (serverTotalInputWaitTimeRef server) (+ (t1 t0))
modifyRef (serverInputWaitTimeRef server) $
addSamplingStats (t1 t0)
triggerSignal (serverInputReceivedSource server) a
(s', b, dt) <-
if serverProcessPreemptible server
then serverProcessPreempting server s a
else do (s', b) <- serverProcess server s a
return (s', b, 0)
t2 <- liftDynamics time
liftEvent $
do writeRef (serverStateRef server) $! s'
modifyRef (serverTotalProcessingTimeRef server) (+ (t2 t1 dt))
modifyRef (serverProcessingTimeRef server) $
addSamplingStats (t2 t1 dt)
triggerSignal (serverTaskProcessedSource server) (a, b)
return (b, loop s' (Just (t2, a, b)) xs')
serverProcessPreempting :: MonadDES m => Server m s a b -> s -> a -> Process m (s, b, Double)
serverProcessPreempting server s a =
do pid <- processId
t1 <- liftDynamics time
rs <- liftSimulation $ newRef 0
r1 <- liftSimulation $ newRef t1
h1 <- liftEvent $
handleSignal (processPreemptionBeginning pid) $ \() ->
do t1 <- liftDynamics time
writeRef r1 t1
triggerSignal (serverTaskPreemptionBeginningSource server) a
h2 <- liftEvent $
handleSignal (processPreemptionEnding pid) $ \() ->
do t1 <- readRef r1
t2 <- liftDynamics time
let dt = t2 t1
modifyRef rs (+ dt)
modifyRef (serverTotalPreemptionTimeRef server) (+ dt)
modifyRef (serverPreemptionTimeRef server) $
addSamplingStats dt
triggerSignal (serverTaskPreemptionEndingSource server) a
let m1 =
do (s', b) <- serverProcess server s a
dt <- liftEvent $ readRef rs
return (s', b, dt)
m2 =
liftEvent $
do disposeEvent h1
disposeEvent h2
finallyProcess m1 m2
serverState :: MonadDES m => Server m s a b -> Event m s
serverState server =
Event $ \p -> invokeEvent p $ readRef (serverStateRef server)
serverStateChanged :: MonadDES m => Server m s a b -> Signal m s
serverStateChanged server =
mapSignalM (const $ serverState server) (serverStateChanged_ server)
serverStateChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverStateChanged_ server =
mapSignal (const ()) (serverTaskProcessed server)
serverTotalInputWaitTime :: MonadDES m => Server m s a b -> Event m Double
serverTotalInputWaitTime server =
Event $ \p -> invokeEvent p $ readRef (serverTotalInputWaitTimeRef server)
serverTotalInputWaitTimeChanged :: MonadDES m => Server m s a b -> Signal m Double
serverTotalInputWaitTimeChanged server =
mapSignalM (const $ serverTotalInputWaitTime server) (serverTotalInputWaitTimeChanged_ server)
serverTotalInputWaitTimeChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverTotalInputWaitTimeChanged_ server =
mapSignal (const ()) (serverInputReceived server)
serverTotalProcessingTime :: MonadDES m => Server m s a b -> Event m Double
serverTotalProcessingTime server =
Event $ \p -> invokeEvent p $ readRef (serverTotalProcessingTimeRef server)
serverTotalProcessingTimeChanged :: MonadDES m => Server m s a b -> Signal m Double
serverTotalProcessingTimeChanged server =
mapSignalM (const $ serverTotalProcessingTime server) (serverTotalProcessingTimeChanged_ server)
serverTotalProcessingTimeChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverTotalProcessingTimeChanged_ server =
mapSignal (const ()) (serverTaskProcessed server)
serverTotalOutputWaitTime :: MonadDES m => Server m s a b -> Event m Double
serverTotalOutputWaitTime server =
Event $ \p -> invokeEvent p $ readRef (serverTotalOutputWaitTimeRef server)
serverTotalOutputWaitTimeChanged :: MonadDES m => Server m s a b -> Signal m Double
serverTotalOutputWaitTimeChanged server =
mapSignalM (const $ serverTotalOutputWaitTime server) (serverTotalOutputWaitTimeChanged_ server)
serverTotalOutputWaitTimeChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverTotalOutputWaitTimeChanged_ server =
mapSignal (const ()) (serverOutputProvided server)
serverTotalPreemptionTime :: MonadDES m => Server m s a b -> Event m Double
serverTotalPreemptionTime server =
Event $ \p -> invokeEvent p $ readRef (serverTotalPreemptionTimeRef server)
serverTotalPreemptionTimeChanged :: MonadDES m => Server m s a b -> Signal m Double
serverTotalPreemptionTimeChanged server =
mapSignalM (const $ serverTotalPreemptionTime server) (serverTotalPreemptionTimeChanged_ server)
serverTotalPreemptionTimeChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverTotalPreemptionTimeChanged_ server =
mapSignal (const ()) (serverTaskPreemptionEnding server)
serverInputWaitTime :: MonadDES m => Server m s a b -> Event m (SamplingStats Double)
serverInputWaitTime server =
Event $ \p -> invokeEvent p $ readRef (serverInputWaitTimeRef server)
serverInputWaitTimeChanged :: MonadDES m => Server m s a b -> Signal m (SamplingStats Double)
serverInputWaitTimeChanged server =
mapSignalM (const $ serverInputWaitTime server) (serverInputWaitTimeChanged_ server)
serverInputWaitTimeChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverInputWaitTimeChanged_ server =
mapSignal (const ()) (serverInputReceived server)
serverProcessingTime :: MonadDES m => Server m s a b -> Event m (SamplingStats Double)
serverProcessingTime server =
Event $ \p -> invokeEvent p $ readRef (serverProcessingTimeRef server)
serverProcessingTimeChanged :: MonadDES m => Server m s a b -> Signal m (SamplingStats Double)
serverProcessingTimeChanged server =
mapSignalM (const $ serverProcessingTime server) (serverProcessingTimeChanged_ server)
serverProcessingTimeChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverProcessingTimeChanged_ server =
mapSignal (const ()) (serverTaskProcessed server)
serverOutputWaitTime :: MonadDES m => Server m s a b -> Event m (SamplingStats Double)
serverOutputWaitTime server =
Event $ \p -> invokeEvent p $ readRef (serverOutputWaitTimeRef server)
serverOutputWaitTimeChanged :: MonadDES m => Server m s a b -> Signal m (SamplingStats Double)
serverOutputWaitTimeChanged server =
mapSignalM (const $ serverOutputWaitTime server) (serverOutputWaitTimeChanged_ server)
serverOutputWaitTimeChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverOutputWaitTimeChanged_ server =
mapSignal (const ()) (serverOutputProvided server)
serverPreemptionTime :: MonadDES m => Server m s a b -> Event m (SamplingStats Double)
serverPreemptionTime server =
Event $ \p -> invokeEvent p $ readRef (serverPreemptionTimeRef server)
serverPreemptionTimeChanged :: MonadDES m => Server m s a b -> Signal m (SamplingStats Double)
serverPreemptionTimeChanged server =
mapSignalM (const $ serverPreemptionTime server) (serverPreemptionTimeChanged_ server)
serverPreemptionTimeChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverPreemptionTimeChanged_ server =
mapSignal (const ()) (serverTaskPreemptionEnding server)
serverInputWaitFactor :: MonadDES m => Server m s a b -> Event m Double
serverInputWaitFactor server =
Event $ \p ->
do x1 <- invokeEvent p $ readRef (serverTotalInputWaitTimeRef server)
x2 <- invokeEvent p $ readRef (serverTotalProcessingTimeRef server)
x3 <- invokeEvent p $ readRef (serverTotalOutputWaitTimeRef server)
x4 <- invokeEvent p $ readRef (serverTotalPreemptionTimeRef server)
return (x1 / (x1 + x2 + x3 + x4))
serverInputWaitFactorChanged :: MonadDES m => Server m s a b -> Signal m Double
serverInputWaitFactorChanged server =
mapSignalM (const $ serverInputWaitFactor server) (serverInputWaitFactorChanged_ server)
serverInputWaitFactorChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverInputWaitFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server) <>
mapSignal (const ()) (serverTaskPreemptionEnding server)
serverProcessingFactor :: MonadDES m => Server m s a b -> Event m Double
serverProcessingFactor server =
Event $ \p ->
do x1 <- invokeEvent p $ readRef (serverTotalInputWaitTimeRef server)
x2 <- invokeEvent p $ readRef (serverTotalProcessingTimeRef server)
x3 <- invokeEvent p $ readRef (serverTotalOutputWaitTimeRef server)
x4 <- invokeEvent p $ readRef (serverTotalPreemptionTimeRef server)
return (x2 / (x1 + x2 + x3 + x4))
serverProcessingFactorChanged :: MonadDES m => Server m s a b -> Signal m Double
serverProcessingFactorChanged server =
mapSignalM (const $ serverProcessingFactor server) (serverProcessingFactorChanged_ server)
serverProcessingFactorChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverProcessingFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server) <>
mapSignal (const ()) (serverTaskPreemptionEnding server)
serverOutputWaitFactor :: MonadDES m => Server m s a b -> Event m Double
serverOutputWaitFactor server =
Event $ \p ->
do x1 <- invokeEvent p $ readRef (serverTotalInputWaitTimeRef server)
x2 <- invokeEvent p $ readRef (serverTotalProcessingTimeRef server)
x3 <- invokeEvent p $ readRef (serverTotalOutputWaitTimeRef server)
x4 <- invokeEvent p $ readRef (serverTotalPreemptionTimeRef server)
return (x3 / (x1 + x2 + x3 + x4))
serverOutputWaitFactorChanged :: MonadDES m => Server m s a b -> Signal m Double
serverOutputWaitFactorChanged server =
mapSignalM (const $ serverOutputWaitFactor server) (serverOutputWaitFactorChanged_ server)
serverOutputWaitFactorChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverOutputWaitFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server) <>
mapSignal (const ()) (serverTaskPreemptionEnding server)
serverPreemptionFactor :: MonadDES m => Server m s a b -> Event m Double
serverPreemptionFactor server =
Event $ \p ->
do x1 <- invokeEvent p $ readRef (serverTotalInputWaitTimeRef server)
x2 <- invokeEvent p $ readRef (serverTotalProcessingTimeRef server)
x3 <- invokeEvent p $ readRef (serverTotalOutputWaitTimeRef server)
x4 <- invokeEvent p $ readRef (serverTotalPreemptionTimeRef server)
return (x4 / (x1 + x2 + x3 + x4))
serverPreemptionFactorChanged :: MonadDES m => Server m s a b -> Signal m Double
serverPreemptionFactorChanged server =
mapSignalM (const $ serverPreemptionFactor server) (serverPreemptionFactorChanged_ server)
serverPreemptionFactorChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverPreemptionFactorChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server) <>
mapSignal (const ()) (serverTaskPreemptionEnding server)
serverInputReceived :: MonadDES m => Server m s a b -> Signal m a
serverInputReceived = publishSignal . serverInputReceivedSource
serverTaskPreemptionBeginning :: MonadDES m => Server m s a b -> Signal m a
serverTaskPreemptionBeginning = publishSignal . serverTaskPreemptionBeginningSource
serverTaskPreemptionEnding :: MonadDES m => Server m s a b -> Signal m a
serverTaskPreemptionEnding = publishSignal . serverTaskPreemptionEndingSource
serverTaskProcessed :: MonadDES m => Server m s a b -> Signal m (a, b)
serverTaskProcessed = publishSignal . serverTaskProcessedSource
serverOutputProvided :: MonadDES m => Server m s a b -> Signal m (a, b)
serverOutputProvided = publishSignal . serverOutputProvidedSource
serverChanged_ :: MonadDES m => Server m s a b -> Signal m ()
serverChanged_ server =
mapSignal (const ()) (serverInputReceived server) <>
mapSignal (const ()) (serverTaskProcessed server) <>
mapSignal (const ()) (serverOutputProvided server) <>
mapSignal (const ()) (serverTaskPreemptionEnding server)
serverSummary :: MonadDES m => Server m s a b -> Int -> Event m ShowS
serverSummary server indent =
Event $ \p ->
do tx1 <- invokeEvent p $ readRef (serverTotalInputWaitTimeRef server)
tx2 <- invokeEvent p $ readRef (serverTotalProcessingTimeRef server)
tx3 <- invokeEvent p $ readRef (serverTotalOutputWaitTimeRef server)
tx4 <- invokeEvent p $ readRef (serverTotalPreemptionTimeRef server)
let xf1 = tx1 / (tx1 + tx2 + tx3 + tx4)
xf2 = tx2 / (tx1 + tx2 + tx3 + tx4)
xf3 = tx3 / (tx1 + tx2 + tx3 + tx4)
xf4 = tx4 / (tx1 + tx2 + tx3 + tx4)
xs1 <- invokeEvent p $ readRef (serverInputWaitTimeRef server)
xs2 <- invokeEvent p $ readRef (serverProcessingTimeRef server)
xs3 <- invokeEvent p $ readRef (serverOutputWaitTimeRef server)
xs4 <- invokeEvent p $ readRef (serverPreemptionTimeRef 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 "total preemption time = " . shows tx4 .
showString "\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 "output preemption factor (from 0 to 1) = " . shows xf4 .
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) .
showString "\n\n" .
showString tab .
showString "preemption time (waiting for the proceeding after preemption):\n\n" .
samplingStatsSummary xs4 (2 + indent)
resetServer :: MonadDES m => Server m s a b -> Event m ()
resetServer server =
do writeRef (serverTotalInputWaitTimeRef server) 0
writeRef (serverTotalProcessingTimeRef server) 0
writeRef (serverTotalOutputWaitTimeRef server) 0
writeRef (serverTotalPreemptionTimeRef server) 0
writeRef (serverInputWaitTimeRef server) mempty
writeRef (serverProcessingTimeRef server) mempty
writeRef (serverOutputWaitTimeRef server) mempty
writeRef (serverPreemptionTimeRef server) mempty