module Simulation.Aivika.Trans.GPSS.Queue
(
Queue,
QueueEntry(..),
newQueue,
queueNull,
queueContent,
queueContentStats,
enqueueCount,
enqueueZeroEntryCount,
queueWaitTime,
queueNonZeroEntryWaitTime,
queueRate,
enqueue,
dequeue,
resetQueue,
queueNullChanged,
queueNullChanged_,
queueContentChanged,
queueContentChanged_,
enqueueCountChanged,
enqueueCountChanged_,
enqueueZeroEntryCountChanged,
enqueueZeroEntryCountChanged_,
queueWaitTimeChanged,
queueWaitTimeChanged_,
queueNonZeroEntryWaitTimeChanged,
queueNonZeroEntryWaitTimeChanged_,
queueRateChanged,
queueRateChanged_,
enqueued,
dequeued,
queueChanged_) where
import Data.Monoid
import Data.Maybe
import Data.Hashable
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Trans
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Dynamics
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Internal.Process
import Simulation.Aivika.Trans.Signal
import Simulation.Aivika.Trans.Statistics
import Simulation.Aivika.Trans.GPSS.Transact
data Queue m =
Queue { queueSequenceNo :: Int,
queueContentRef :: Ref m Int,
queueContentStatsRef :: Ref m (TimingStats Int),
enqueueCountRef :: Ref m Int,
enqueueZeroEntryCountRef :: Ref m Int,
queueWaitTimeRef :: Ref m (SamplingStats Double),
queueNonZeroEntryWaitTimeRef :: Ref m (SamplingStats Double),
enqueuedSource :: SignalSource m (),
dequeuedSource :: SignalSource m ()
}
data QueueEntry m =
QueueEntry { entryQueue :: Queue m,
entryEnqueueTime :: Double
} deriving Eq
instance MonadDES m => Eq (Queue m) where
x == y = (queueContentRef x) == (queueContentRef y)
instance Hashable (Queue m) where
hashWithSalt salt x = hashWithSalt salt (queueSequenceNo x)
newQueue :: MonadDES m => Event m (Queue m)
newQueue =
do t <- liftDynamics time
g <- liftParameter generatorParameter
no <- liftComp $ generateSequenceNo g
i <- liftSimulation $ newRef 0
is <- liftSimulation $ newRef $ returnTimingStats t 0
e <- liftSimulation $ newRef 0
z <- liftSimulation $ newRef 0
w <- liftSimulation $ newRef mempty
w2 <- liftSimulation $ newRef mempty
s1 <- liftSimulation $ newSignalSource
s2 <- liftSimulation $ newSignalSource
return Queue { queueSequenceNo = no,
queueContentRef = i,
queueContentStatsRef = is,
enqueueCountRef = e,
enqueueZeroEntryCountRef = z,
queueWaitTimeRef = w,
queueNonZeroEntryWaitTimeRef = w2,
enqueuedSource = s1,
dequeuedSource = s2 }
queueNull :: MonadDES m => Queue m -> Event m Bool
queueNull q =
Event $ \p ->
do n <- invokeEvent p $ readRef (queueContentRef q)
return (n == 0)
queueNullChanged :: MonadDES m => Queue m -> Signal m Bool
queueNullChanged q =
mapSignalM (const $ queueNull q) (queueNullChanged_ q)
queueNullChanged_ :: MonadDES m => Queue m -> Signal m ()
queueNullChanged_ = queueContentChanged_
queueContent :: MonadDES m => Queue m -> Event m Int
queueContent q =
Event $ \p -> invokeEvent p $ readRef (queueContentRef q)
queueContentStats :: MonadDES m => Queue m -> Event m (TimingStats Int)
queueContentStats q =
Event $ \p -> invokeEvent p $ readRef (queueContentStatsRef q)
queueContentChanged :: MonadDES m => Queue m -> Signal m Int
queueContentChanged q =
mapSignalM (const $ queueContent q) (queueContentChanged_ q)
queueContentChanged_ :: MonadDES m => Queue m -> Signal m ()
queueContentChanged_ q =
mapSignal (const ()) (enqueued q) <>
mapSignal (const ()) (dequeued q)
enqueueCount :: MonadDES m => Queue m -> Event m Int
enqueueCount q =
Event $ \p -> invokeEvent p $ readRef (enqueueCountRef q)
enqueueCountChanged :: MonadDES m => Queue m -> Signal m Int
enqueueCountChanged q =
mapSignalM (const $ enqueueCount q) (enqueueCountChanged_ q)
enqueueCountChanged_ :: MonadDES m => Queue m -> Signal m ()
enqueueCountChanged_ q =
mapSignal (const ()) (enqueued q)
enqueueZeroEntryCount :: MonadDES m => Queue m -> Event m Int
enqueueZeroEntryCount q =
Event $ \p -> invokeEvent p $ readRef (enqueueZeroEntryCountRef q)
enqueueZeroEntryCountChanged :: MonadDES m => Queue m -> Signal m Int
enqueueZeroEntryCountChanged q =
mapSignalM (const $ enqueueZeroEntryCount q) (enqueueZeroEntryCountChanged_ q)
enqueueZeroEntryCountChanged_ :: MonadDES m => Queue m -> Signal m ()
enqueueZeroEntryCountChanged_ q =
mapSignal (const ()) (dequeued q)
queueWaitTime :: MonadDES m => Queue m -> Event m (SamplingStats Double)
queueWaitTime q =
Event $ \p -> invokeEvent p $ readRef (queueWaitTimeRef q)
queueWaitTimeChanged :: MonadDES m => Queue m -> Signal m (SamplingStats Double)
queueWaitTimeChanged q =
mapSignalM (const $ queueWaitTime q) (queueWaitTimeChanged_ q)
queueWaitTimeChanged_ :: MonadDES m => Queue m -> Signal m ()
queueWaitTimeChanged_ q =
mapSignal (const ()) (dequeued q)
queueNonZeroEntryWaitTime :: MonadDES m => Queue m -> Event m (SamplingStats Double)
queueNonZeroEntryWaitTime q =
Event $ \p -> invokeEvent p $ readRef (queueNonZeroEntryWaitTimeRef q)
queueNonZeroEntryWaitTimeChanged :: MonadDES m => Queue m -> Signal m (SamplingStats Double)
queueNonZeroEntryWaitTimeChanged q =
mapSignalM (const $ queueNonZeroEntryWaitTime q) (queueNonZeroEntryWaitTimeChanged_ q)
queueNonZeroEntryWaitTimeChanged_ :: MonadDES m => Queue m -> Signal m ()
queueNonZeroEntryWaitTimeChanged_ q =
mapSignal (const ()) (dequeued q)
queueRate :: MonadDES m => Queue m -> Event m Double
queueRate q =
Event $ \p ->
do x <- invokeEvent p $ readRef (queueContentStatsRef q)
y <- invokeEvent p $ readRef (queueWaitTimeRef q)
return (timingStatsMean x / samplingStatsMean y)
queueRateChanged :: MonadDES m => Queue m -> Signal m Double
queueRateChanged q =
mapSignalM (const $ queueRate q) (queueRateChanged_ q)
queueRateChanged_ :: MonadDES m => Queue m -> Signal m ()
queueRateChanged_ q =
mapSignal (const ()) (enqueued q) <>
mapSignal (const ()) (dequeued q)
enqueued:: MonadDES m => Queue m -> Signal m ()
enqueued q = publishSignal (enqueuedSource q)
dequeued :: MonadDES m => Queue m -> Signal m ()
dequeued q = publishSignal (dequeuedSource q)
enqueue :: MonadDES m
=> Queue m
-> Transact m a
-> Int
-> Event m ()
enqueue q transact increment =
Event $ \p ->
do let t = pointTime p
e = QueueEntry { entryQueue = q,
entryEnqueueTime = t }
n <- invokeEvent p $ readRef (enqueueCountRef q)
let n' = n + 1
invokeEvent p $
writeRef (enqueueCountRef q) n'
c <- invokeEvent p $ readRef (queueContentRef q)
let c' = c + increment
invokeEvent p $
writeRef (queueContentRef q) c'
invokeEvent p $
modifyRef (queueContentStatsRef q) (addTimingStats t c')
invokeEvent p $
registerTransactQueueEntry transact e
invokeEvent p $
triggerSignal (enqueuedSource q) ()
dequeue :: MonadDES m
=> Queue m
-> Transact m a
-> Int
-> Event m ()
dequeue q transact decrement =
Event $ \p ->
do e <- invokeEvent p $
unregisterTransactQueueEntry transact q
let t = pointTime p
t0 = entryEnqueueTime e
dt = t t0
c <- invokeEvent p $ readRef (queueContentRef q)
let c' = c decrement
invokeEvent p $
writeRef (queueContentRef q) c'
invokeEvent p $
modifyRef (queueContentStatsRef q) (addTimingStats t c')
invokeEvent p $
modifyRef (queueWaitTimeRef q) $
addSamplingStats dt
if t == t0
then invokeEvent p $
modifyRef (enqueueZeroEntryCountRef q) (+ 1)
else invokeEvent p $
modifyRef (queueNonZeroEntryWaitTimeRef q) $
addSamplingStats dt
invokeEvent p $
triggerSignal (dequeuedSource q) ()
queueChanged_ :: MonadDES m => Queue m -> Signal m ()
queueChanged_ q =
mapSignal (const ()) (enqueued q) <>
mapSignal (const ()) (dequeued q)
resetQueue :: MonadDES m => Queue m -> Event m ()
resetQueue q =
do t <- liftDynamics time
content <- readRef (queueContentRef q)
writeRef (queueContentStatsRef q) $
returnTimingStats t content
writeRef (enqueueCountRef q) 0
writeRef (enqueueZeroEntryCountRef q) 0
writeRef (queueWaitTimeRef q) mempty
writeRef (queueNonZeroEntryWaitTimeRef q) mempty