module Simulation.Aivika.GPSS.Facility
(
Facility,
FacilityPreemptMode(..),
FacilityPreemptTransfer,
newFacility,
facilityCount,
facilityCountStats,
facilityCaptureCount,
facilityUtilisationCount,
facilityUtilisationCountStats,
facilityQueueCount,
facilityQueueCountStats,
facilityTotalWaitTime,
facilityWaitTime,
facilityTotalHoldingTime,
facilityHoldingTime,
facilityInterrupted,
seizeFacility,
releaseFacility,
preemptFacility,
returnFacility,
resetFacility,
facilityCountChanged,
facilityCountChanged_,
facilityCaptureCountChanged,
facilityCaptureCountChanged_,
facilityUtilisationCountChanged,
facilityUtilisationCountChanged_,
facilityQueueCountChanged,
facilityQueueCountChanged_,
facilityWaitTimeChanged,
facilityWaitTimeChanged_,
facilityHoldingTimeChanged,
facilityHoldingTimeChanged_,
facilityChanged_) where
import Data.IORef
import Data.Monoid
import Data.Maybe
import Control.Monad
import Control.Monad.Trans
import Control.Exception
import Simulation.Aivika.Internal.Specs
import Simulation.Aivika.Internal.Simulation
import Simulation.Aivika.Internal.Event
import Simulation.Aivika.Internal.Cont
import Simulation.Aivika.Internal.Process
import Simulation.Aivika.QueueStrategy
import Simulation.Aivika.Statistics
import Simulation.Aivika.Signal
import Simulation.Aivika.GPSS.Transact
import Simulation.Aivika.GPSS.TransactQueueStrategy
data Facility a =
Facility { facilityCountRef :: IORef Int,
facilityCountStatsRef :: IORef (TimingStats Int),
facilityCountSource :: SignalSource Int,
facilityCaptureCountRef :: IORef Int,
facilityCaptureCountSource :: SignalSource Int,
facilityUtilisationCountRef :: IORef Int,
facilityUtilisationCountStatsRef :: IORef (TimingStats Int),
facilityUtilisationCountSource :: SignalSource Int,
facilityQueueCountRef :: IORef Int,
facilityQueueCountStatsRef :: IORef (TimingStats Int),
facilityQueueCountSource :: SignalSource Int,
facilityTotalWaitTimeRef :: IORef Double,
facilityWaitTimeRef :: IORef (SamplingStats Double),
facilityWaitTimeSource :: SignalSource (),
facilityTotalHoldingTimeRef :: IORef Double,
facilityHoldingTimeRef :: IORef (SamplingStats Double),
facilityHoldingTimeSource :: SignalSource (),
facilityOwnerRef :: IORef (Maybe (FacilityOwnerItem a)),
facilityDelayChain :: StrategyQueue (TransactQueueStrategy FCFS) (FacilityDelayedItem a),
facilityInterruptChain :: StrategyQueue (TransactQueueStrategy LCFS) (FacilityInterruptedItem a),
facilityPendingChain :: StrategyQueue (TransactQueueStrategy FCFS) (FacilityPendingItem a) }
data FacilityOwnerItem a =
FacilityOwnerItem { ownerItemTransact :: Transact a,
ownerItemTime :: Double,
ownerItemPreempting :: Bool,
ownerItemInterrupting :: Bool,
ownerItemAccHoldingTime :: Double }
data FacilityDelayedItem a =
FacilityDelayedItem { delayedItemTransact :: Transact a,
delayedItemTime :: Double,
delayedItemPreempting :: Bool,
delayedItemInterrupting :: Bool,
delayedItemCont :: FrozenCont () }
data FacilityInterruptedItem a =
FacilityInterruptedItem { interruptedItemTransact :: Transact a,
interruptedItemTime :: Double,
interruptedItemPreempting :: Bool,
interruptedItemInterrupting :: Bool,
interruptedItemRemainingTime :: Maybe Double,
interruptedItemTransfer :: Maybe (FacilityPreemptTransfer a),
interruptedItemAccHoldingTime :: Double }
data FacilityPendingItem a =
FacilityPendingItem { pendingItemTransact :: Transact a,
pendingItemTime :: Double,
pendingItemPreempting :: Bool,
pendingItemInterrupting :: Bool,
pendingItemCont :: FrozenCont () }
instance Eq (Facility a) where
x == y = facilityCountRef x == facilityCountRef y
data FacilityPreemptMode a =
FacilityPreemptMode { facilityPriorityMode :: Bool,
facilityTransfer :: Maybe (FacilityPreemptTransfer a),
facilityRemoveMode :: Bool
}
type FacilityPreemptTransfer a = Transact a -> Maybe Double -> Process ()
defaultFacilityPreemptMode :: FacilityPreemptMode a
defaultFacilityPreemptMode =
FacilityPreemptMode { facilityPriorityMode = False,
facilityTransfer = Nothing,
facilityRemoveMode = False
}
newFacility :: Event (Facility a)
newFacility =
Event $ \p ->
do let r = pointRun p
t = pointTime p
countRef <- newIORef 1
countStatsRef <- newIORef $ returnTimingStats t 1
countSource <- invokeSimulation r newSignalSource
captureCountRef <- newIORef 0
captureCountSource <- invokeSimulation r newSignalSource
utilCountRef <- newIORef 0
utilCountStatsRef <- newIORef $ returnTimingStats t 0
utilCountSource <- invokeSimulation r newSignalSource
queueCountRef <- newIORef 0
queueCountStatsRef <- newIORef $ returnTimingStats t 0
queueCountSource <- invokeSimulation r newSignalSource
totalWaitTimeRef <- newIORef 0
waitTimeRef <- newIORef emptySamplingStats
waitTimeSource <- invokeSimulation r newSignalSource
totalHoldingTimeRef <- newIORef 0
holdingTimeRef <- newIORef emptySamplingStats
holdingTimeSource <- invokeSimulation r newSignalSource
ownerRef <- newIORef Nothing
delayChain <- invokeSimulation r $ newStrategyQueue (TransactQueueStrategy FCFS)
interruptChain <- invokeSimulation r $ newStrategyQueue (TransactQueueStrategy LCFS)
pendingChain <- invokeSimulation r $ newStrategyQueue (TransactQueueStrategy FCFS)
return Facility { facilityCountRef = countRef,
facilityCountStatsRef = countStatsRef,
facilityCountSource = countSource,
facilityCaptureCountRef = captureCountRef,
facilityCaptureCountSource = captureCountSource,
facilityUtilisationCountRef = utilCountRef,
facilityUtilisationCountStatsRef = utilCountStatsRef,
facilityUtilisationCountSource = utilCountSource,
facilityQueueCountRef = queueCountRef,
facilityQueueCountStatsRef = queueCountStatsRef,
facilityQueueCountSource = queueCountSource,
facilityTotalWaitTimeRef = totalWaitTimeRef,
facilityWaitTimeRef = waitTimeRef,
facilityWaitTimeSource = waitTimeSource,
facilityTotalHoldingTimeRef = totalHoldingTimeRef,
facilityHoldingTimeRef = holdingTimeRef,
facilityHoldingTimeSource = holdingTimeSource,
facilityOwnerRef = ownerRef,
facilityDelayChain = delayChain,
facilityInterruptChain = interruptChain,
facilityPendingChain = pendingChain }
facilityCount :: Facility a -> Event Int
facilityCount r =
Event $ \p -> readIORef (facilityCountRef r)
facilityCountStats :: Facility a -> Event (TimingStats Int)
facilityCountStats r =
Event $ \p -> readIORef (facilityCountStatsRef r)
facilityCountChanged :: Facility a -> Signal Int
facilityCountChanged r =
publishSignal $ facilityCountSource r
facilityCountChanged_ :: Facility a -> Signal ()
facilityCountChanged_ r =
mapSignal (const ()) $ facilityCountChanged r
facilityCaptureCount :: Facility a -> Event Int
facilityCaptureCount r =
Event $ \p -> readIORef (facilityCaptureCountRef r)
facilityCaptureCountChanged :: Facility a -> Signal Int
facilityCaptureCountChanged r =
publishSignal $ facilityCaptureCountSource r
facilityCaptureCountChanged_ :: Facility a -> Signal ()
facilityCaptureCountChanged_ r =
mapSignal (const ()) $ facilityCaptureCountChanged r
facilityUtilisationCount :: Facility a -> Event Int
facilityUtilisationCount r =
Event $ \p -> readIORef (facilityUtilisationCountRef r)
facilityUtilisationCountStats :: Facility a -> Event (TimingStats Int)
facilityUtilisationCountStats r =
Event $ \p -> readIORef (facilityUtilisationCountStatsRef r)
facilityUtilisationCountChanged :: Facility a -> Signal Int
facilityUtilisationCountChanged r =
publishSignal $ facilityUtilisationCountSource r
facilityUtilisationCountChanged_ :: Facility a -> Signal ()
facilityUtilisationCountChanged_ r =
mapSignal (const ()) $ facilityUtilisationCountChanged r
facilityQueueCount :: Facility a -> Event Int
facilityQueueCount r =
Event $ \p -> readIORef (facilityQueueCountRef r)
facilityQueueCountStats :: Facility a -> Event (TimingStats Int)
facilityQueueCountStats r =
Event $ \p -> readIORef (facilityQueueCountStatsRef r)
facilityQueueCountChanged :: Facility a -> Signal Int
facilityQueueCountChanged r =
publishSignal $ facilityQueueCountSource r
facilityQueueCountChanged_ :: Facility a -> Signal ()
facilityQueueCountChanged_ r =
mapSignal (const ()) $ facilityQueueCountChanged r
facilityTotalWaitTime :: Facility a -> Event Double
facilityTotalWaitTime r =
Event $ \p -> readIORef (facilityTotalWaitTimeRef r)
facilityWaitTime :: Facility a -> Event (SamplingStats Double)
facilityWaitTime r =
Event $ \p -> readIORef (facilityWaitTimeRef r)
facilityWaitTimeChanged :: Facility a -> Signal (SamplingStats Double)
facilityWaitTimeChanged r =
mapSignalM (\() -> facilityWaitTime r) $ facilityWaitTimeChanged_ r
facilityWaitTimeChanged_ :: Facility a -> Signal ()
facilityWaitTimeChanged_ r =
publishSignal $ facilityWaitTimeSource r
facilityTotalHoldingTime :: Facility a -> Event Double
facilityTotalHoldingTime r =
Event $ \p -> readIORef (facilityTotalHoldingTimeRef r)
facilityHoldingTime :: Facility a -> Event (SamplingStats Double)
facilityHoldingTime r =
Event $ \p -> readIORef (facilityHoldingTimeRef r)
facilityHoldingTimeChanged :: Facility a -> Signal (SamplingStats Double)
facilityHoldingTimeChanged r =
mapSignalM (\() -> facilityHoldingTime r) $ facilityHoldingTimeChanged_ r
facilityHoldingTimeChanged_ :: Facility a -> Signal ()
facilityHoldingTimeChanged_ r =
publishSignal $ facilityHoldingTimeSource r
facilityInterrupted :: Facility a -> Event Bool
facilityInterrupted r =
Event $ \p ->
do x <- readIORef (facilityOwnerRef r)
case x of
Nothing -> return False
Just a -> return (ownerItemPreempting a)
seizeFacility :: Facility a
-> Transact a
-> Process ()
seizeFacility r transact =
Process $ \pid ->
Cont $ \c ->
Event $ \p ->
do let t = pointTime p
f <- do f1 <- invokeEvent p $ strategyQueueNull (facilityDelayChain r)
if f1
then do f2 <- invokeEvent p $ strategyQueueNull (facilityInterruptChain r)
if f2
then invokeEvent p $ strategyQueueNull (facilityPendingChain r)
else return False
else return False
if f
then invokeEvent p $
invokeCont c $
invokeProcess pid $
seizeFacility' r transact
else do c <- invokeEvent p $
freezeContReentering c () $
invokeCont c $
invokeProcess pid $
seizeFacility r transact
invokeEvent p $
strategyEnqueueWithPriority
(facilityDelayChain r)
(transactPriority transact)
(FacilityDelayedItem transact t False False c)
invokeEvent p $ updateFacilityQueueCount r 1
seizeFacility' :: Facility a
-> Transact a
-> Process ()
seizeFacility' r transact =
Process $ \pid ->
Cont $ \c ->
Event $ \p ->
do let t = pointTime p
a <- readIORef (facilityOwnerRef r)
case a of
Nothing ->
do writeIORef (facilityOwnerRef r) $ Just (FacilityOwnerItem transact t False False 0)
invokeEvent p $ updateFacilityWaitTime r 0
invokeEvent p $ updateFacilityCount r (1)
invokeEvent p $ updateFacilityCaptureCount r 1
invokeEvent p $ updateFacilityUtilisationCount r 1
invokeEvent p $ resumeCont c ()
Just owner ->
do c <- invokeEvent p $
freezeContReentering c () $
invokeCont c $
invokeProcess pid $
seizeFacility r transact
invokeEvent p $
strategyEnqueueWithPriority
(facilityDelayChain r)
(transactPriority transact)
(FacilityDelayedItem transact t False False c)
invokeEvent p $ updateFacilityQueueCount r 1
preemptFacility :: Facility a
-> Transact a
-> FacilityPreemptMode a
-> Process ()
preemptFacility r transact mode =
Process $ \pid ->
Cont $ \c ->
Event $ \p ->
do let t = pointTime p
a <- readIORef (facilityOwnerRef r)
case a of
Nothing ->
do writeIORef (facilityOwnerRef r) $ Just (FacilityOwnerItem transact t True False 0)
invokeEvent p $ updateFacilityWaitTime r 0
invokeEvent p $ updateFacilityCount r (1)
invokeEvent p $ updateFacilityCaptureCount r 1
invokeEvent p $ updateFacilityUtilisationCount r 1
invokeEvent p $ resumeCont c ()
Just owner@(FacilityOwnerItem transact0 t0 preempting0 interrupting0 acc0)
| (not $ facilityPriorityMode mode) && interrupting0 ->
do c <- invokeEvent p $
freezeContReentering c () $
invokeCont c $
invokeProcess pid $
preemptFacility r transact mode
invokeEvent p $
strategyEnqueueWithPriority
(facilityPendingChain r)
(transactPriority transact)
(FacilityPendingItem transact t True True c)
invokeEvent p $ updateFacilityQueueCount r 1
Just owner@(FacilityOwnerItem transact0 t0 preempting0 interrupting0 acc0)
| facilityPriorityMode mode && (transactPriority transact <= transactPriority transact0) ->
do c <- invokeEvent p $
freezeContReentering c () $
invokeCont c $
invokeProcess pid $
preemptFacility r transact mode
invokeEvent p $
strategyEnqueueWithPriority
(facilityDelayChain r)
(transactPriority transact)
(FacilityDelayedItem transact t True True c)
invokeEvent p $ updateFacilityQueueCount r 1
Just owner@(FacilityOwnerItem transact0 t0 preempting0 interrupting0 acc0)
| (not $ facilityRemoveMode mode) ->
do writeIORef (facilityOwnerRef r) $ Just (FacilityOwnerItem transact t True True 0)
pid0 <- invokeEvent p $ requireTransactProcessId transact0
t2 <- invokeEvent p $ processInterruptionTime pid0
let dt0 = fmap (\x -> x t) t2
invokeEvent p $
strategyEnqueueWithPriority
(facilityInterruptChain r)
(transactPriority transact0)
(FacilityInterruptedItem transact0 t preempting0 interrupting0 dt0 (facilityTransfer mode) (acc0 + (t t0)))
invokeEvent p $ updateFacilityQueueCount r 1
invokeEvent p $ updateFacilityWaitTime r 0
invokeEvent p $ updateFacilityCaptureCount r 1
invokeEvent p $ transactPreemptionBegin transact0
invokeEvent p $ resumeCont c ()
Just owner@(FacilityOwnerItem transact0 t0 preempting0 interrupting0 acc0)
| facilityRemoveMode mode ->
do writeIORef (facilityOwnerRef r) $ Just (FacilityOwnerItem transact t True True 0)
pid0 <- invokeEvent p $ requireTransactProcessId transact0
t2 <- invokeEvent p $ processInterruptionTime pid0
let dt0 = fmap (\x -> x t) t2
invokeEvent p $ updateFacilityWaitTime r 0
invokeEvent p $ updateFacilityCaptureCount r 1
invokeEvent p $ updateFacilityHoldingTime r (acc0 + (t t0))
case facilityTransfer mode of
Nothing ->
throwIO $
SimulationRetry
"The transfer destination is not specified for the removed preempted transact: preemptFacility"
Just transfer ->
invokeEvent p $ transferTransact transact0 (transfer transact0 dt0)
invokeEvent p $ resumeCont c ()
returnFacility :: Facility a
-> Transact a
-> Process ()
returnFacility r transact = releaseFacility' r transact True
releaseFacility :: Facility a
-> Transact a
-> Process ()
releaseFacility r transact = releaseFacility' r transact False
releaseFacility' :: Facility a
-> Transact a
-> Bool
-> Process ()
releaseFacility' r transact preempting =
Process $ \pid ->
Cont $ \c ->
Event $ \p ->
do let t = pointTime p
a <- readIORef (facilityOwnerRef r)
case a of
Nothing ->
throwIO $
SimulationRetry
"There is no owner of the facility: releaseFacility'"
Just owner@(FacilityOwnerItem transact0 t0 preempting0 interrupting0 acc0) | transact0 == transact && preempting0 /= preempting ->
throwIO $
SimulationRetry
"The mismatch use of releaseFacility and returnFacility: releaseFacility'"
Just owner@(FacilityOwnerItem transact0 t0 preempting0 interrupting0 acc0) | transact0 == transact ->
do writeIORef (facilityOwnerRef r) Nothing
invokeEvent p $ updateFacilityUtilisationCount r (1)
invokeEvent p $ updateFacilityHoldingTime r (acc0 + (t t0))
invokeEvent p $ updateFacilityCount r 1
invokeEvent p $ enqueueEvent t $ tryCaptureFacility r
invokeEvent p $ resumeCont c ()
Just owner ->
throwIO $
SimulationRetry
"The facility has another owner: releaseFacility'"
tryCaptureFacility :: Facility a -> Event ()
tryCaptureFacility r =
Event $ \p ->
do let t = pointTime p
a <- readIORef (facilityOwnerRef r)
case a of
Nothing ->
invokeEvent p $ captureFacility r
Just owner -> return ()
captureFacility :: Facility a -> Event ()
captureFacility r =
Event $ \p ->
do let t = pointTime p
f <- invokeEvent p $ strategyQueueNull (facilityPendingChain r)
if not f
then do FacilityPendingItem transact t0 preempting interrupting c0 <- invokeEvent p $ strategyDequeue (facilityPendingChain r)
invokeEvent p $ updateFacilityQueueCount r (1)
c <- invokeEvent p $ unfreezeCont c0
case c of
Nothing ->
invokeEvent p $ captureFacility r
Just c ->
do writeIORef (facilityOwnerRef r) $ Just (FacilityOwnerItem transact t preempting interrupting 0)
invokeEvent p $ updateFacilityWaitTime r (t t0)
invokeEvent p $ updateFacilityUtilisationCount r 1
invokeEvent p $ updateFacilityCaptureCount r 1
invokeEvent p $ updateFacilityCount r (1)
invokeEvent p $ enqueueEvent t $ reenterCont c ()
else do f <- invokeEvent p $ strategyQueueNull (facilityInterruptChain r)
if not f
then do FacilityInterruptedItem transact t0 preempting interrupting dt0 transfer0 acc0 <- invokeEvent p $ strategyDequeue (facilityInterruptChain r)
pid <- invokeEvent p $ requireTransactProcessId transact
invokeEvent p $ updateFacilityQueueCount r (1)
f <- invokeEvent p $ processCancelled pid
case f of
True ->
invokeEvent p $ captureFacility r
False ->
do writeIORef (facilityOwnerRef r) $ Just (FacilityOwnerItem transact t preempting interrupting acc0)
invokeEvent p $ updateFacilityWaitTime r (t t0)
invokeEvent p $ updateFacilityUtilisationCount r 1
invokeEvent p $ updateFacilityCount r (1)
case transfer0 of
Nothing -> return ()
Just transfer ->
invokeEvent p $ transferTransact transact (transfer transact dt0)
invokeEvent p $ transactPreemptionEnd transact
else do f <- invokeEvent p $ strategyQueueNull (facilityDelayChain r)
if not f
then do FacilityDelayedItem transact t0 preempting interrupting c0 <- invokeEvent p $ strategyDequeue (facilityDelayChain r)
invokeEvent p $ updateFacilityQueueCount r (1)
c <- invokeEvent p $ unfreezeCont c0
case c of
Nothing ->
invokeEvent p $ captureFacility r
Just c ->
do writeIORef (facilityOwnerRef r) $ Just (FacilityOwnerItem transact t preempting interrupting 0)
invokeEvent p $ updateFacilityWaitTime r (t t0)
invokeEvent p $ updateFacilityUtilisationCount r 1
invokeEvent p $ updateFacilityCaptureCount r 1
invokeEvent p $ updateFacilityCount r (1)
invokeEvent p $ enqueueEvent t $ reenterCont c ()
else return ()
facilityChanged_ :: Facility a -> Signal ()
facilityChanged_ r =
facilityCountChanged_ r <>
facilityCaptureCountChanged_ r <>
facilityUtilisationCountChanged_ r <>
facilityQueueCountChanged_ r
updateFacilityCount :: Facility a -> Int -> Event ()
updateFacilityCount r delta =
Event $ \p ->
do a <- readIORef (facilityCountRef r)
let a' = a + delta
a' `seq` writeIORef (facilityCountRef r) a'
modifyIORef' (facilityCountStatsRef r) $
addTimingStats (pointTime p) a'
invokeEvent p $
triggerSignal (facilityCountSource r) a'
updateFacilityCaptureCount :: Facility a -> Int -> Event ()
updateFacilityCaptureCount r delta =
Event $ \p ->
do a <- readIORef (facilityCaptureCountRef r)
let a' = a + delta
a' `seq` writeIORef (facilityCaptureCountRef r) a'
invokeEvent p $
triggerSignal (facilityCaptureCountSource r) a'
updateFacilityQueueCount :: Facility a -> Int -> Event ()
updateFacilityQueueCount r delta =
Event $ \p ->
do a <- readIORef (facilityQueueCountRef r)
let a' = a + delta
a' `seq` writeIORef (facilityQueueCountRef r) a'
modifyIORef' (facilityQueueCountStatsRef r) $
addTimingStats (pointTime p) a'
invokeEvent p $
triggerSignal (facilityQueueCountSource r) a'
updateFacilityUtilisationCount :: Facility a -> Int -> Event ()
updateFacilityUtilisationCount r delta =
Event $ \p ->
do a <- readIORef (facilityUtilisationCountRef r)
let a' = a + delta
a' `seq` writeIORef (facilityUtilisationCountRef r) a'
modifyIORef' (facilityUtilisationCountStatsRef r) $
addTimingStats (pointTime p) a'
invokeEvent p $
triggerSignal (facilityUtilisationCountSource r) a'
updateFacilityWaitTime :: Facility a -> Double -> Event ()
updateFacilityWaitTime r delta =
Event $ \p ->
do a <- readIORef (facilityTotalWaitTimeRef r)
let a' = a + delta
a' `seq` writeIORef (facilityTotalWaitTimeRef r) a'
modifyIORef' (facilityWaitTimeRef r) $
addSamplingStats delta
invokeEvent p $
triggerSignal (facilityWaitTimeSource r) ()
updateFacilityHoldingTime :: Facility a -> Double -> Event ()
updateFacilityHoldingTime r delta =
Event $ \p ->
do a <- readIORef (facilityTotalHoldingTimeRef r)
let a' = a + delta
a' `seq` writeIORef (facilityTotalHoldingTimeRef r) a'
modifyIORef' (facilityHoldingTimeRef r) $
addSamplingStats delta
invokeEvent p $
triggerSignal (facilityHoldingTimeSource r) ()
resetFacility :: Facility a -> Event ()
resetFacility r =
Event $ \p ->
do let t = pointTime p
count <- readIORef (facilityCountRef r)
writeIORef (facilityCountStatsRef r) $
returnTimingStats t count
writeIORef (facilityCaptureCountRef r) 0
utilCount <- readIORef (facilityUtilisationCountRef r)
writeIORef (facilityUtilisationCountStatsRef r) $
returnTimingStats t utilCount
queueCount <- readIORef (facilityQueueCountRef r)
writeIORef (facilityQueueCountStatsRef r) $
returnTimingStats t queueCount
writeIORef (facilityTotalWaitTimeRef r) 0
writeIORef (facilityWaitTimeRef r) emptySamplingStats
writeIORef (facilityTotalHoldingTimeRef r) 0
writeIORef (facilityHoldingTimeRef r) emptySamplingStats
invokeEvent p $
triggerSignal (facilityCaptureCountSource r) 0
invokeEvent p $
triggerSignal (facilityWaitTimeSource r) ()
invokeEvent p $
triggerSignal (facilityHoldingTimeSource r) ()