-- It corresponds to model TimeOut described in document -- Advanced Features of the SimPy Language -- [http://heather.cs.ucdavis.edu/~matloff/156/PLN/AdvancedSimPy.pdf]. -- SimPy is available on [http://simpy.sourceforge.net/]. -- -- The model description is as follows. -- -- Introductory example to illustrate the modeling of "competing -- events" such as timeouts, especially using the timeoutProcess -- function. A network node starts a process within the specified -- timeout and receives a signal that notifies whether the process -- has finished successfully within the timeout; if the node -- times out, it assumes the message it had sent was lost, and it -- will send again. The time to get an acknowledgement for a message is -- exponentially distributed with mean 1.0, and the timeout period is -- 0.5. Immediately after receiving an acknowledgement, the node sends -- out a new message. -- -- We find the proportion of messages which timeout. The output should -- be about 0.61. import Control.Monad import Control.Monad.Trans import Data.Maybe import Simulation.Aivika ackRate = 1.0 / 1.0 -- reciprocal of the acknowledge mean time toPeriod = 0.5 -- timeout period specs = Specs { spcStartTime = 0.0, spcStopTime = 10000.0, spcDT = 1.0, spcMethod = RungeKutta4, spcGeneratorType = SimpleGenerator } model :: Simulation Double model = do -- number of messages sent nMsgs <- newRef 0 -- number of timeouts which have occured nTimeOuts <- newRef 0 let node :: Process () node = do liftEvent $ modifyRef nMsgs $ (+) 1 result <- timeoutProcess toPeriod $ do ackTime <- liftParameter $ randomExponential (1 / ackRate) holdProcess ackTime liftEvent $ when (isNothing result) $ modifyRef nTimeOuts $ (+) 1 node runProcessInStartTime node runEventInStopTime $ do x <- readRef nTimeOuts y <- readRef nMsgs return $ x / y main = do putStr "The percentage of timeout was " runSimulation model specs >>= print