{-# LANGUAGE FlexibleContexts #-}

-- |
-- Module     : Simulation.Aivika.Trans.Resource
-- Copyright  : Copyright (c) 2009-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 8.0.1
--
-- This module defines the resource which can be acquired and 
-- then released by the discontinuous process 'Process'.
-- The resource can be either limited by the upper bound
-- (run-time check), or it can have no upper bound. The latter
-- is useful for modeling the infinite queue, for example.
--
module Simulation.Aivika.Trans.Resource
       (-- * Resource Types
        FCFSResource,
        LCFSResource,
        SIROResource,
        PriorityResource,
        Resource,
        -- * Creating Resource
        newFCFSResource,
        newFCFSResourceWithMaxCount,
        newLCFSResource,
        newLCFSResourceWithMaxCount,
        newSIROResource,
        newSIROResourceWithMaxCount,
        newPriorityResource,
        newPriorityResourceWithMaxCount,
        newResource,
        newResourceWithMaxCount,
        -- * Resource Properties
        resourceStrategy,
        resourceMaxCount,
        resourceCount,
        resourceCountStats,
        resourceUtilisationCount,
        resourceUtilisationCountStats,
        resourceQueueCount,
        resourceQueueCountStats,
        resourceTotalWaitTime,
        resourceWaitTime,
        -- * Requesting for and Releasing Resource
        requestResource,
        requestResourceWithPriority,
        tryRequestResourceWithinEvent,
        releaseResource,
        releaseResourceWithinEvent,
        usingResource,
        usingResourceWithPriority,
        -- * Altering Resource
        incResourceCount,
        decResourceCount,
        -- * Statistics Reset
        resetResource,
        -- * Signals
        resourceCountChanged,
        resourceCountChanged_,
        resourceUtilisationCountChanged,
        resourceUtilisationCountChanged_,
        resourceQueueCountChanged,
        resourceQueueCountChanged_,
        resourceWaitTimeChanged,
        resourceWaitTimeChanged_,
        resourceChanged_) where

import Data.Monoid

import Control.Monad
import Control.Monad.Trans
import Control.Exception

import Simulation.Aivika.Trans.Exception
import Simulation.Aivika.Trans.Ref.Base
import Simulation.Aivika.Trans.DES
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Internal.Cont
import Simulation.Aivika.Trans.Internal.Process
import Simulation.Aivika.Trans.QueueStrategy
import Simulation.Aivika.Trans.Statistics
import Simulation.Aivika.Trans.Signal

-- | The ordinary FCFS (First Come - First Serviced) resource.
type FCFSResource m = Resource m FCFS

-- | The ordinary LCFS (Last Come - First Serviced) resource.
type LCFSResource m = Resource m LCFS

-- | The SIRO (Serviced in Random Order) resource.
type SIROResource m = Resource m SIRO

-- | The resource with static priorities.
type PriorityResource m = Resource m StaticPriorities

-- | Represents the resource with strategy @s@ applied for queuing the requests.
data Resource m s = 
  Resource { forall (m :: * -> *) s. Resource m s -> s
resourceStrategy :: s,
             -- ^ Return the strategy applied for queuing the requests.
             forall (m :: * -> *) s. Resource m s -> Maybe Int
resourceMaxCount :: Maybe Int,
             -- ^ Return the maximum count of the resource, where 'Nothing'
             -- means that the resource has no upper bound.
             forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceCountRef :: Ref m Int,
             forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceCountStatsRef :: Ref m (TimingStats Int),
             forall (m :: * -> *) s. Resource m s -> SignalSource m Int
resourceCountSource :: SignalSource m Int,
             forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceUtilisationCountRef :: Ref m Int,
             forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceUtilisationCountStatsRef :: Ref m (TimingStats Int),
             forall (m :: * -> *) s. Resource m s -> SignalSource m Int
resourceUtilisationCountSource :: SignalSource m Int,
             forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceQueueCountRef :: Ref m Int,
             forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceQueueCountStatsRef :: Ref m (TimingStats Int),
             forall (m :: * -> *) s. Resource m s -> SignalSource m Int
resourceQueueCountSource :: SignalSource m Int,
             forall (m :: * -> *) s. Resource m s -> Ref m Double
resourceTotalWaitTimeRef :: Ref m Double,
             forall (m :: * -> *) s.
Resource m s -> Ref m (SamplingStats Double)
resourceWaitTimeRef :: Ref m (SamplingStats Double),
             forall (m :: * -> *) s. Resource m s -> SignalSource m ()
resourceWaitTimeSource :: SignalSource m (),
             forall (m :: * -> *) s.
Resource m s -> StrategyQueue m s (ResourceItem m)
resourceWaitList :: StrategyQueue m s (ResourceItem m) }

data ResourceItem m =
  ResourceItem { forall (m :: * -> *). ResourceItem m -> Double
resourceItemTime :: Double,
                 forall (m :: * -> *). ResourceItem m -> FrozenCont m ()
resourceItemCont :: FrozenCont m () }

-- | Create a new FCFS resource with the specified initial count which value becomes
-- the upper bound as well.
newFCFSResource :: MonadDES m
                   => Int
                   -- ^ the initial count (and maximal count too) of the resource
                   -> Event m (FCFSResource m)
{-# INLINABLE newFCFSResource #-}
newFCFSResource :: forall (m :: * -> *). MonadDES m => Int -> Event m (FCFSResource m)
newFCFSResource = forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Event m (Resource m s)
newResource FCFS
FCFS

-- | Create a new FCFS resource with the specified initial and maximum counts,
-- where 'Nothing' means that the resource has no upper bound.
newFCFSResourceWithMaxCount :: MonadDES m
                               => Int
                               -- ^ the initial count of the resource
                               -> Maybe Int
                               -- ^ the maximum count of the resource, which can be indefinite
                               -> Event m (FCFSResource m)
{-# INLINABLE newFCFSResourceWithMaxCount #-}
newFCFSResourceWithMaxCount :: forall (m :: * -> *).
MonadDES m =>
Int -> Maybe Int -> Event m (FCFSResource m)
newFCFSResourceWithMaxCount = forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Maybe Int -> Event m (Resource m s)
newResourceWithMaxCount FCFS
FCFS

-- | Create a new LCFS resource with the specified initial count which value becomes
-- the upper bound as well.
newLCFSResource :: MonadDES m
                   => Int
                   -- ^ the initial count (and maximal count too) of the resource
                   -> Event m (LCFSResource m)
{-# INLINABLE newLCFSResource #-}
newLCFSResource :: forall (m :: * -> *). MonadDES m => Int -> Event m (LCFSResource m)
newLCFSResource = forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Event m (Resource m s)
newResource LCFS
LCFS

-- | Create a new LCFS resource with the specified initial and maximum counts,
-- where 'Nothing' means that the resource has no upper bound.
newLCFSResourceWithMaxCount :: MonadDES m
                               => Int
                               -- ^ the initial count of the resource
                               -> Maybe Int
                               -- ^ the maximum count of the resource, which can be indefinite
                               -> Event m (LCFSResource m)
{-# INLINABLE newLCFSResourceWithMaxCount #-}
newLCFSResourceWithMaxCount :: forall (m :: * -> *).
MonadDES m =>
Int -> Maybe Int -> Event m (LCFSResource m)
newLCFSResourceWithMaxCount = forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Maybe Int -> Event m (Resource m s)
newResourceWithMaxCount LCFS
LCFS

-- | Create a new SIRO resource with the specified initial count which value becomes
-- the upper bound as well.
newSIROResource :: (MonadDES m, QueueStrategy m SIRO)
                   => Int
                   -- ^ the initial count (and maximal count too) of the resource
                   -> Event m (SIROResource m)
{-# INLINABLE newSIROResource #-}
newSIROResource :: forall (m :: * -> *).
(MonadDES m, QueueStrategy m SIRO) =>
Int -> Event m (SIROResource m)
newSIROResource = forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Event m (Resource m s)
newResource SIRO
SIRO

-- | Create a new SIRO resource with the specified initial and maximum counts,
-- where 'Nothing' means that the resource has no upper bound.
newSIROResourceWithMaxCount :: (MonadDES m, QueueStrategy m SIRO)
                               => Int
                               -- ^ the initial count of the resource
                               -> Maybe Int
                               -- ^ the maximum count of the resource, which can be indefinite
                               -> Event m (SIROResource m)
{-# INLINABLE newSIROResourceWithMaxCount #-}
newSIROResourceWithMaxCount :: forall (m :: * -> *).
(MonadDES m, QueueStrategy m SIRO) =>
Int -> Maybe Int -> Event m (SIROResource m)
newSIROResourceWithMaxCount = forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Maybe Int -> Event m (Resource m s)
newResourceWithMaxCount SIRO
SIRO

-- | Create a new priority resource with the specified initial count which value becomes
-- the upper bound as well.
newPriorityResource :: (MonadDES m, QueueStrategy m StaticPriorities)
                       => Int
                       -- ^ the initial count (and maximal count too) of the resource
                       -> Event m (PriorityResource m)
{-# INLINABLE newPriorityResource #-}
newPriorityResource :: forall (m :: * -> *).
(MonadDES m, QueueStrategy m StaticPriorities) =>
Int -> Event m (PriorityResource m)
newPriorityResource = forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Event m (Resource m s)
newResource StaticPriorities
StaticPriorities

-- | Create a new priority resource with the specified initial and maximum counts,
-- where 'Nothing' means that the resource has no upper bound.
newPriorityResourceWithMaxCount :: (MonadDES m, QueueStrategy m StaticPriorities)
                                   => Int
                                   -- ^ the initial count of the resource
                                   -> Maybe Int
                                   -- ^ the maximum count of the resource, which can be indefinite
                                   -> Event m (PriorityResource m)
{-# INLINABLE newPriorityResourceWithMaxCount #-}
newPriorityResourceWithMaxCount :: forall (m :: * -> *).
(MonadDES m, QueueStrategy m StaticPriorities) =>
Int -> Maybe Int -> Event m (PriorityResource m)
newPriorityResourceWithMaxCount = forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Maybe Int -> Event m (Resource m s)
newResourceWithMaxCount StaticPriorities
StaticPriorities

-- | Create a new resource with the specified queue strategy and initial count.
-- The last value becomes the upper bound as well.
newResource :: (MonadDES m, QueueStrategy m s)
               => s
               -- ^ the strategy for managing the queuing requests
               -> Int
               -- ^ the initial count (and maximal count too) of the resource
               -> Event m (Resource m s)
{-# INLINABLE newResource #-}
newResource :: forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Event m (Resource m s)
newResource s
s Int
count =
  forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Maybe Int -> Event m (Resource m s)
newResourceWithMaxCount s
s Int
count (forall a. a -> Maybe a
Just Int
count)

-- | Create a new resource with the specified queue strategy, initial and maximum counts,
-- where 'Nothing' means that the resource has no upper bound.
newResourceWithMaxCount :: (MonadDES m, QueueStrategy m s)
                           => s
                           -- ^ the strategy for managing the queuing requests
                           -> Int
                           -- ^ the initial count of the resource
                           -> Maybe Int
                           -- ^ the maximum count of the resource, which can be indefinite
                           -> Event m (Resource m s)
{-# INLINABLE newResourceWithMaxCount #-}
newResourceWithMaxCount :: forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Maybe Int -> Event m (Resource m s)
newResourceWithMaxCount s
s Int
count Maybe Int
maxCount =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let r :: Run m
r = forall (m :: * -> *). Point m -> Run m
pointRun Point m
p
         t :: Double
t = forall (m :: * -> *). Point m -> Double
pointTime Point m
p
     forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
count forall a. Ord a => a -> a -> Bool
< Int
0) forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
e -> m a
throwComp forall a b. (a -> b) -> a -> b
$
       String -> SimulationRetry
SimulationRetry forall a b. (a -> b) -> a -> b
$
       String
"The resource count cannot be negative: " forall a. [a] -> [a] -> [a]
++
       String
"newResourceWithMaxCount."
     case Maybe Int
maxCount of
       Just Int
maxCount | Int
count forall a. Ord a => a -> a -> Bool
> Int
maxCount ->
         forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
e -> m a
throwComp forall a b. (a -> b) -> a -> b
$
         String -> SimulationRetry
SimulationRetry forall a b. (a -> b) -> a -> b
$
         String
"The resource count cannot be greater than " forall a. [a] -> [a] -> [a]
++
         String
"its maximum value: newResourceWithMaxCount."
       Maybe Int
_ ->
         forall (m :: * -> *) a. Monad m => a -> m a
return ()
     Ref m Int
countRef <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef Int
count
     Ref m (TimingStats Int)
countStatsRef <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef forall a b. (a -> b) -> a -> b
$ forall a. TimingData a => Double -> a -> TimingStats a
returnTimingStats Double
t Int
count
     SignalSource m Int
countSource <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall (m :: * -> *) a.
MonadDES m =>
Simulation m (SignalSource m a)
newSignalSource
     Ref m Int
utilCountRef <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef Int
0
     Ref m (TimingStats Int)
utilCountStatsRef <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef forall a b. (a -> b) -> a -> b
$ forall a. TimingData a => Double -> a -> TimingStats a
returnTimingStats Double
t Int
0
     SignalSource m Int
utilCountSource <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall (m :: * -> *) a.
MonadDES m =>
Simulation m (SignalSource m a)
newSignalSource
     Ref m Int
queueCountRef <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef Int
0
     Ref m (TimingStats Int)
queueCountStatsRef <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef forall a b. (a -> b) -> a -> b
$ forall a. TimingData a => Double -> a -> TimingStats a
returnTimingStats Double
t Int
0
     SignalSource m Int
queueCountSource <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall (m :: * -> *) a.
MonadDES m =>
Simulation m (SignalSource m a)
newSignalSource
     Ref m Double
totalWaitTimeRef <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef Double
0
     Ref m (SamplingStats Double)
waitTimeRef <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef forall a. SamplingData a => SamplingStats a
emptySamplingStats
     SignalSource m ()
waitTimeSource <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall (m :: * -> *) a.
MonadDES m =>
Simulation m (SignalSource m a)
newSignalSource
     StrategyQueue m s (ResourceItem m)
waitList <- forall (m :: * -> *) a. Run m -> Simulation m a -> m a
invokeSimulation Run m
r forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s a.
QueueStrategy m s =>
s -> Simulation m (StrategyQueue m s a)
newStrategyQueue s
s
     forall (m :: * -> *) a. Monad m => a -> m a
return Resource { resourceStrategy :: s
resourceStrategy = s
s,
                       resourceMaxCount :: Maybe Int
resourceMaxCount = Maybe Int
maxCount,
                       resourceCountRef :: Ref m Int
resourceCountRef = Ref m Int
countRef,
                       resourceCountStatsRef :: Ref m (TimingStats Int)
resourceCountStatsRef = Ref m (TimingStats Int)
countStatsRef,
                       resourceCountSource :: SignalSource m Int
resourceCountSource = SignalSource m Int
countSource,
                       resourceUtilisationCountRef :: Ref m Int
resourceUtilisationCountRef = Ref m Int
utilCountRef,
                       resourceUtilisationCountStatsRef :: Ref m (TimingStats Int)
resourceUtilisationCountStatsRef = Ref m (TimingStats Int)
utilCountStatsRef,
                       resourceUtilisationCountSource :: SignalSource m Int
resourceUtilisationCountSource = SignalSource m Int
utilCountSource,
                       resourceQueueCountRef :: Ref m Int
resourceQueueCountRef = Ref m Int
queueCountRef,
                       resourceQueueCountStatsRef :: Ref m (TimingStats Int)
resourceQueueCountStatsRef = Ref m (TimingStats Int)
queueCountStatsRef,
                       resourceQueueCountSource :: SignalSource m Int
resourceQueueCountSource = SignalSource m Int
queueCountSource,
                       resourceTotalWaitTimeRef :: Ref m Double
resourceTotalWaitTimeRef = Ref m Double
totalWaitTimeRef,
                       resourceWaitTimeRef :: Ref m (SamplingStats Double)
resourceWaitTimeRef = Ref m (SamplingStats Double)
waitTimeRef,
                       resourceWaitTimeSource :: SignalSource m ()
resourceWaitTimeSource = SignalSource m ()
waitTimeSource,
                       resourceWaitList :: StrategyQueue m s (ResourceItem m)
resourceWaitList = StrategyQueue m s (ResourceItem m)
waitList }

-- | Return the current available count of the resource.
resourceCount :: MonadDES m => Resource m s -> Event m Int
{-# INLINABLE resourceCount #-}
resourceCount :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Event m Int
resourceCount Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p -> forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceCountRef Resource m s
r)

-- | Return the statistics for the available count of the resource.
resourceCountStats :: MonadDES m => Resource m s -> Event m (TimingStats Int)
{-# INLINABLE resourceCountStats #-}
resourceCountStats :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Event m (TimingStats Int)
resourceCountStats Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p -> forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceCountStatsRef Resource m s
r)

-- | Signal triggered when the 'resourceCount' property changes.
resourceCountChanged :: MonadDES m => Resource m s -> Signal m Int
{-# INLINABLE resourceCountChanged #-}
resourceCountChanged :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m Int
resourceCountChanged Resource m s
r =
  forall (m :: * -> *) a. SignalSource m a -> Signal m a
publishSignal forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. Resource m s -> SignalSource m Int
resourceCountSource Resource m s
r

-- | Signal triggered when the 'resourceCount' property changes.
resourceCountChanged_ :: MonadDES m => Resource m s -> Signal m ()
{-# INLINABLE resourceCountChanged_ #-}
resourceCountChanged_ :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m ()
resourceCountChanged_ Resource m s
r =
  forall (m :: * -> *) a b.
MonadDES m =>
(a -> b) -> Signal m a -> Signal m b
mapSignal (forall a b. a -> b -> a
const ()) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m Int
resourceCountChanged Resource m s
r

-- | Return the current utilisation count of the resource.
resourceUtilisationCount :: MonadDES m => Resource m s -> Event m Int
{-# INLINABLE resourceUtilisationCount #-}
resourceUtilisationCount :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Event m Int
resourceUtilisationCount Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p -> forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceUtilisationCountRef Resource m s
r)

-- | Return the statistics for the utilisation count of the resource.
resourceUtilisationCountStats :: MonadDES m => Resource m s -> Event m (TimingStats Int)
{-# INLINABLE resourceUtilisationCountStats #-}
resourceUtilisationCountStats :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Event m (TimingStats Int)
resourceUtilisationCountStats Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p -> forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceUtilisationCountStatsRef Resource m s
r)

-- | Signal triggered when the 'resourceUtilisationCount' property changes.
resourceUtilisationCountChanged :: MonadDES m => Resource m s -> Signal m Int
{-# INLINABLE resourceUtilisationCountChanged #-}
resourceUtilisationCountChanged :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m Int
resourceUtilisationCountChanged Resource m s
r =
  forall (m :: * -> *) a. SignalSource m a -> Signal m a
publishSignal forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. Resource m s -> SignalSource m Int
resourceUtilisationCountSource Resource m s
r

-- | Signal triggered when the 'resourceUtilisationCount' property changes.
resourceUtilisationCountChanged_ :: MonadDES m => Resource m s -> Signal m ()
{-# INLINABLE resourceUtilisationCountChanged_ #-}
resourceUtilisationCountChanged_ :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m ()
resourceUtilisationCountChanged_ Resource m s
r =
  forall (m :: * -> *) a b.
MonadDES m =>
(a -> b) -> Signal m a -> Signal m b
mapSignal (forall a b. a -> b -> a
const ()) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m Int
resourceUtilisationCountChanged Resource m s
r

-- | Return the current queue length of the resource.
resourceQueueCount :: MonadDES m => Resource m s -> Event m Int
{-# INLINABLE resourceQueueCount #-}
resourceQueueCount :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Event m Int
resourceQueueCount Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p -> forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceQueueCountRef Resource m s
r)

-- | Return the statistics for the queue length of the resource.
resourceQueueCountStats :: MonadDES m => Resource m s -> Event m (TimingStats Int)
{-# INLINABLE resourceQueueCountStats #-}
resourceQueueCountStats :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Event m (TimingStats Int)
resourceQueueCountStats Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p -> forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceQueueCountStatsRef Resource m s
r)

-- | Signal triggered when the 'resourceQueueCount' property changes.
resourceQueueCountChanged :: MonadDES m => Resource m s -> Signal m Int
{-# INLINABLE resourceQueueCountChanged #-}
resourceQueueCountChanged :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m Int
resourceQueueCountChanged Resource m s
r =
  forall (m :: * -> *) a. SignalSource m a -> Signal m a
publishSignal forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. Resource m s -> SignalSource m Int
resourceQueueCountSource Resource m s
r

-- | Signal triggered when the 'resourceQueueCount' property changes.
resourceQueueCountChanged_ :: MonadDES m => Resource m s -> Signal m ()
{-# INLINABLE resourceQueueCountChanged_ #-}
resourceQueueCountChanged_ :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m ()
resourceQueueCountChanged_ Resource m s
r =
  forall (m :: * -> *) a b.
MonadDES m =>
(a -> b) -> Signal m a -> Signal m b
mapSignal (forall a b. a -> b -> a
const ()) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m Int
resourceQueueCountChanged Resource m s
r

-- | Return the total wait time of the resource.
resourceTotalWaitTime :: MonadDES m => Resource m s -> Event m Double
{-# INLINABLE resourceTotalWaitTime #-}
resourceTotalWaitTime :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Event m Double
resourceTotalWaitTime Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p -> forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Double
resourceTotalWaitTimeRef Resource m s
r)

-- | Return the statistics for the wait time of the resource.
resourceWaitTime :: MonadDES m => Resource m s -> Event m (SamplingStats Double)
{-# INLINABLE resourceWaitTime #-}
resourceWaitTime :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Event m (SamplingStats Double)
resourceWaitTime Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p -> forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s.
Resource m s -> Ref m (SamplingStats Double)
resourceWaitTimeRef Resource m s
r)

-- | Signal triggered when the 'resourceTotalWaitTime' and 'resourceWaitTime' properties change.
resourceWaitTimeChanged :: MonadDES m => Resource m s -> Signal m (SamplingStats Double)
{-# INLINABLE resourceWaitTimeChanged #-}
resourceWaitTimeChanged :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Signal m (SamplingStats Double)
resourceWaitTimeChanged Resource m s
r =
  forall (m :: * -> *) a b.
MonadDES m =>
(a -> Event m b) -> Signal m a -> Signal m b
mapSignalM (\() -> forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Event m (SamplingStats Double)
resourceWaitTime Resource m s
r) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m ()
resourceWaitTimeChanged_ Resource m s
r

-- | Signal triggered when the 'resourceTotalWaitTime' and 'resourceWaitTime' properties change.
resourceWaitTimeChanged_ :: MonadDES m => Resource m s -> Signal m ()
{-# INLINABLE resourceWaitTimeChanged_ #-}
resourceWaitTimeChanged_ :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m ()
resourceWaitTimeChanged_ Resource m s
r =
  forall (m :: * -> *) a. SignalSource m a -> Signal m a
publishSignal forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s. Resource m s -> SignalSource m ()
resourceWaitTimeSource Resource m s
r

-- | Request for the resource decreasing its count in case of success,
-- otherwise suspending the discontinuous process until some other 
-- process releases the resource.
requestResource :: (MonadDES m, EnqueueStrategy m s)
                   => Resource m s
                   -- ^ the requested resource
                   -> Process m ()
{-# INLINABLE requestResource #-}
requestResource :: forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Process m ()
requestResource Resource m s
r =
  forall (m :: * -> *) a. (ProcessId m -> Cont m a) -> Process m a
Process forall a b. (a -> b) -> a -> b
$ \ProcessId m
pid ->
  forall (m :: * -> *) a. (ContParams m a -> Event m ()) -> Cont m a
Cont forall a b. (a -> b) -> a -> b
$ \ContParams m ()
c ->
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
a <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceCountRef Resource m s
r)
     if Int
a forall a. Eq a => a -> a -> Bool
== Int
0 
       then do FrozenCont m ()
c <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
                    forall (m :: * -> *) a.
MonadDES m =>
ContParams m a -> a -> Event m () -> Event m (FrozenCont m a)
freezeContReentering ContParams m ()
c () forall a b. (a -> b) -> a -> b
$
                    forall (m :: * -> *) a. ContParams m a -> Cont m a -> Event m ()
invokeCont ContParams m ()
c forall a b. (a -> b) -> a -> b
$
                    forall (m :: * -> *) a. ProcessId m -> Process m a -> Cont m a
invokeProcess ProcessId m
pid forall a b. (a -> b) -> a -> b
$
                    forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Process m ()
requestResource Resource m s
r
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
                 forall (m :: * -> *) s a.
EnqueueStrategy m s =>
StrategyQueue m s a -> a -> Event m ()
strategyEnqueue (forall (m :: * -> *) s.
Resource m s -> StrategyQueue m s (ResourceItem m)
resourceWaitList Resource m s
r) forall a b. (a -> b) -> a -> b
$
                 forall (m :: * -> *). Double -> FrozenCont m () -> ResourceItem m
ResourceItem (forall (m :: * -> *). Point m -> Double
pointTime Point m
p) FrozenCont m ()
c
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceQueueCount Resource m s
r Int
1
       else do forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Double -> Event m ()
updateResourceWaitTime Resource m s
r Double
0
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceCount Resource m s
r (-Int
1)
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceUtilisationCount Resource m s
r Int
1
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
MonadDES m =>
ContParams m a -> a -> Event m ()
resumeCont ContParams m ()
c ()

-- | Request with the priority for the resource decreasing its count
-- in case of success, otherwise suspending the discontinuous process
-- until some other process releases the resource.
requestResourceWithPriority :: (MonadDES m, PriorityQueueStrategy m s p)
                               => Resource m s
                               -- ^ the requested resource
                               -> p
                               -- ^ the priority
                               -> Process m ()
{-# INLINABLE requestResourceWithPriority #-}
requestResourceWithPriority :: forall (m :: * -> *) s p.
(MonadDES m, PriorityQueueStrategy m s p) =>
Resource m s -> p -> Process m ()
requestResourceWithPriority Resource m s
r p
priority =
  forall (m :: * -> *) a. (ProcessId m -> Cont m a) -> Process m a
Process forall a b. (a -> b) -> a -> b
$ \ProcessId m
pid ->
  forall (m :: * -> *) a. (ContParams m a -> Event m ()) -> Cont m a
Cont forall a b. (a -> b) -> a -> b
$ \ContParams m ()
c ->
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
a <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceCountRef Resource m s
r)
     if Int
a forall a. Eq a => a -> a -> Bool
== Int
0 
       then do FrozenCont m ()
c <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
                    forall (m :: * -> *) a.
MonadDES m =>
ContParams m a -> a -> Event m () -> Event m (FrozenCont m a)
freezeContReentering ContParams m ()
c () forall a b. (a -> b) -> a -> b
$
                    forall (m :: * -> *) a. ContParams m a -> Cont m a -> Event m ()
invokeCont ContParams m ()
c forall a b. (a -> b) -> a -> b
$
                    forall (m :: * -> *) a. ProcessId m -> Process m a -> Cont m a
invokeProcess ProcessId m
pid forall a b. (a -> b) -> a -> b
$
                    forall (m :: * -> *) s p.
(MonadDES m, PriorityQueueStrategy m s p) =>
Resource m s -> p -> Process m ()
requestResourceWithPriority Resource m s
r p
priority
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
                 forall (m :: * -> *) s p a.
PriorityQueueStrategy m s p =>
StrategyQueue m s a -> p -> a -> Event m ()
strategyEnqueueWithPriority (forall (m :: * -> *) s.
Resource m s -> StrategyQueue m s (ResourceItem m)
resourceWaitList Resource m s
r) p
priority forall a b. (a -> b) -> a -> b
$
                 forall (m :: * -> *). Double -> FrozenCont m () -> ResourceItem m
ResourceItem (forall (m :: * -> *). Point m -> Double
pointTime Point m
p) FrozenCont m ()
c
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceQueueCount Resource m s
r Int
1
       else do forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Double -> Event m ()
updateResourceWaitTime Resource m s
r Double
0
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceCount Resource m s
r (-Int
1)
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceUtilisationCount Resource m s
r Int
1
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
MonadDES m =>
ContParams m a -> a -> Event m ()
resumeCont ContParams m ()
c ()

-- | Release the resource increasing its count and resuming one of the
-- previously suspended processes as possible.
releaseResource :: (MonadDES m, DequeueStrategy m s)
                   => Resource m s
                   -- ^ the resource to release
                   -> Process m ()
{-# INLINABLE releaseResource #-}
releaseResource :: forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Process m ()
releaseResource Resource m s
r = 
  forall (m :: * -> *) a. (ProcessId m -> Cont m a) -> Process m a
Process forall a b. (a -> b) -> a -> b
$ \ProcessId m
_ ->
  forall (m :: * -> *) a. (ContParams m a -> Event m ()) -> Cont m a
Cont forall a b. (a -> b) -> a -> b
$ \ContParams m ()
c ->
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResourceWithinEvent Resource m s
r
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
MonadDES m =>
ContParams m a -> a -> Event m ()
resumeCont ContParams m ()
c ()

-- | Release the resource increasing its count and resuming one of the
-- previously suspended processes as possible.
releaseResourceWithinEvent :: (MonadDES m, DequeueStrategy m s)
                              => Resource m s
                              -- ^ the resource to release
                              -> Event m ()
{-# INLINABLE releaseResourceWithinEvent #-}
releaseResourceWithinEvent :: forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResourceWithinEvent Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceUtilisationCount Resource m s
r (-Int
1)
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResource' Resource m s
r
  
-- | Release the resource without affecting its utilisation.
releaseResource' :: (MonadDES m, DequeueStrategy m s)
                    => Resource m s
                    -- ^ the resource to release
                    -> Event m ()
{-# INLINABLE releaseResource' #-}
releaseResource' :: forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResource' Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
a <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceCountRef Resource m s
r)
     let a' :: Int
a' = Int
a forall a. Num a => a -> a -> a
+ Int
1
     case forall (m :: * -> *) s. Resource m s -> Maybe Int
resourceMaxCount Resource m s
r of
       Just Int
maxCount | Int
a' forall a. Ord a => a -> a -> Bool
> Int
maxCount ->
         forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
e -> m a
throwComp forall a b. (a -> b) -> a -> b
$
         String -> SimulationRetry
SimulationRetry forall a b. (a -> b) -> a -> b
$
         String
"The resource count cannot be greater than " forall a. [a] -> [a] -> [a]
++
         String
"its maximum value: releaseResource'."
       Maybe Int
_ ->
         forall (m :: * -> *) a. Monad m => a -> m a
return ()
     Bool
f <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
          forall (m :: * -> *) s a.
QueueStrategy m s =>
StrategyQueue m s a -> Event m Bool
strategyQueueNull (forall (m :: * -> *) s.
Resource m s -> StrategyQueue m s (ResourceItem m)
resourceWaitList Resource m s
r)
     if Bool
f 
       then forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceCount Resource m s
r Int
1
       else do ResourceItem m
x <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
                    forall (m :: * -> *) s a.
DequeueStrategy m s =>
StrategyQueue m s a -> Event m a
strategyDequeue (forall (m :: * -> *) s.
Resource m s -> StrategyQueue m s (ResourceItem m)
resourceWaitList Resource m s
r)
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceQueueCount Resource m s
r (-Int
1)
               Maybe (ContParams m ())
c <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
FrozenCont m a -> Event m (Maybe (ContParams m a))
unfreezeCont (forall (m :: * -> *). ResourceItem m -> FrozenCont m ()
resourceItemCont ResourceItem m
x)
               case Maybe (ContParams m ())
c of
                 Maybe (ContParams m ())
Nothing ->
                   forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResource' Resource m s
r
                 Just ContParams m ()
c  ->
                   do forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Double -> Event m ()
updateResourceWaitTime Resource m s
r (forall (m :: * -> *). Point m -> Double
pointTime Point m
p forall a. Num a => a -> a -> a
- forall (m :: * -> *). ResourceItem m -> Double
resourceItemTime ResourceItem m
x)
                      forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceUtilisationCount Resource m s
r Int
1
                      forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
EventQueueing m =>
Double -> Event m () -> Event m ()
enqueueEvent (forall (m :: * -> *). Point m -> Double
pointTime Point m
p) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
MonadDES m =>
ContParams m a -> a -> Event m ()
resumeCont ContParams m ()
c ()

-- | Try to request for the resource decreasing its count in case of success
-- and returning 'True' in the 'Event' monad; otherwise, returning 'False'.
tryRequestResourceWithinEvent :: MonadDES m
                                 => Resource m s
                                 -- ^ the resource which we try to request for
                                 -> Event m Bool
{-# INLINABLE tryRequestResourceWithinEvent #-}
tryRequestResourceWithinEvent :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Event m Bool
tryRequestResourceWithinEvent Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
a <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceCountRef Resource m s
r)
     if Int
a forall a. Eq a => a -> a -> Bool
== Int
0 
       then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
       else do forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Double -> Event m ()
updateResourceWaitTime Resource m s
r Double
0
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceCount Resource m s
r (-Int
1)
               forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceUtilisationCount Resource m s
r Int
1
               forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
               
-- | Acquire the resource, perform some action and safely release the resource               
-- in the end, even if the 'IOException' was raised within the action. 
usingResource :: (MonadDES m, EnqueueStrategy m s)
                 => Resource m s
                 -- ^ the resource we are going to request for and then release in the end
                 -> Process m a
                 -- ^ the action we are going to apply having the resource
                 -> Process m a
                 -- ^ the result of the action
{-# INLINABLE usingResource #-}
usingResource :: forall (m :: * -> *) s a.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Process m a -> Process m a
usingResource Resource m s
r Process m a
m =
  do forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Process m ()
requestResource Resource m s
r
     forall (m :: * -> *) a b.
MonadDES m =>
Process m a -> Process m b -> Process m a
finallyProcess Process m a
m forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Process m ()
releaseResource Resource m s
r

-- | Acquire the resource with the specified priority, perform some action and
-- safely release the resource in the end, even if the 'IOException' was raised
-- within the action.
usingResourceWithPriority :: (MonadDES m, PriorityQueueStrategy m s p)
                             => Resource m s
                             -- ^ the resource we are going to request for and then
                             -- release in the end
                             -> p
                             -- ^ the priority
                             -> Process m a
                             -- ^ the action we are going to apply having the resource
                             -> Process m a
                             -- ^ the result of the action
{-# INLINABLE usingResourceWithPriority #-}
usingResourceWithPriority :: forall (m :: * -> *) s p a.
(MonadDES m, PriorityQueueStrategy m s p) =>
Resource m s -> p -> Process m a -> Process m a
usingResourceWithPriority Resource m s
r p
priority Process m a
m =
  do forall (m :: * -> *) s p.
(MonadDES m, PriorityQueueStrategy m s p) =>
Resource m s -> p -> Process m ()
requestResourceWithPriority Resource m s
r p
priority
     forall (m :: * -> *) a b.
MonadDES m =>
Process m a -> Process m b -> Process m a
finallyProcess Process m a
m forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Process m ()
releaseResource Resource m s
r

-- | Decrease the count of available resource.
decResourceCount' :: (MonadDES m, EnqueueStrategy m s)
                     => Resource m s
                     -- ^ the resource for which to decrease the count
                     -> Process m ()
{-# INLINABLE decResourceCount' #-}
decResourceCount' :: forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Process m ()
decResourceCount' Resource m s
r =
  do forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
EventLift t m =>
Event m a -> t m a
liftEvent forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceUtilisationCount Resource m s
r (-Int
1)
     forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Process m ()
requestResource Resource m s
r
                   
-- | Increase the count of available resource by the specified number,
-- invoking the awaiting processes as needed.
incResourceCount :: (MonadDES m, DequeueStrategy m s)
                    => Resource m s
                    -- ^ the resource
                    -> Int
                    -- ^ the increment for the resource count
                    -> Event m ()
{-# INLINABLE incResourceCount #-}
incResourceCount :: forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Int -> Event m ()
incResourceCount Resource m s
r Int
n
  | Int
n forall a. Ord a => a -> a -> Bool
< Int
0     = forall (m :: * -> *) e a.
(MonadException m, Exception e) =>
e -> Event m a
throwEvent forall a b. (a -> b) -> a -> b
$ String -> SimulationRetry
SimulationRetry String
"The increment cannot be negative: incResourceCount"
  | Int
n forall a. Eq a => a -> a -> Bool
== Int
0    = forall (m :: * -> *) a. Monad m => a -> m a
return ()
  | Bool
otherwise =
    do forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResource' Resource m s
r
       forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Int -> Event m ()
incResourceCount Resource m s
r (Int
n forall a. Num a => a -> a -> a
- Int
1)

-- | Decrease the count of available resource by the specified number,
-- waiting for the processes capturing the resource as needed.
decResourceCount :: (MonadDES m, EnqueueStrategy m s)
                    => Resource m s
                    -- ^ the resource
                    -> Int
                    -- ^ the decrement for the resource count
                    -> Process m ()
{-# INLINABLE decResourceCount #-}
decResourceCount :: forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Int -> Process m ()
decResourceCount Resource m s
r Int
n
  | Int
n forall a. Ord a => a -> a -> Bool
< Int
0     = forall (m :: * -> *) e a.
(MonadDES m, Exception e) =>
e -> Process m a
throwProcess forall a b. (a -> b) -> a -> b
$ String -> SimulationRetry
SimulationRetry String
"The decrement cannot be negative: decResourceCount"
  | Int
n forall a. Eq a => a -> a -> Bool
== Int
0    = forall (m :: * -> *) a. Monad m => a -> m a
return ()
  | Bool
otherwise =
    do forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Process m ()
decResourceCount' Resource m s
r
       forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Int -> Process m ()
decResourceCount Resource m s
r (Int
n forall a. Num a => a -> a -> a
- Int
1)

-- | Signal triggered when one of the resource counters changes.
resourceChanged_ :: MonadDES m => Resource m s -> Signal m ()
{-# INLINABLE resourceChanged_ #-}
resourceChanged_ :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m ()
resourceChanged_ Resource m s
r =
  forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m ()
resourceCountChanged_ Resource m s
r forall a. Semigroup a => a -> a -> a
<>
  forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m ()
resourceUtilisationCountChanged_ Resource m s
r forall a. Semigroup a => a -> a -> a
<>
  forall (m :: * -> *) s. MonadDES m => Resource m s -> Signal m ()
resourceQueueCountChanged_ Resource m s
r

-- | Update the resource count and its statistics.
updateResourceCount :: MonadDES m => Resource m s -> Int -> Event m ()
{-# INLINABLE updateResourceCount #-}
updateResourceCount :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceCount Resource m s
r Int
delta =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
a <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceCountRef Resource m s
r)
     let a' :: Int
a' = Int
a forall a. Num a => a -> a -> a
+ Int
delta
     Int
a' seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceCountRef Resource m s
r) Int
a'
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a.
MonadRef m =>
Ref m a -> (a -> a) -> Event m ()
modifyRef (forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceCountStatsRef Resource m s
r) forall a b. (a -> b) -> a -> b
$
       forall a.
TimingData a =>
Double -> a -> TimingStats a -> TimingStats a
addTimingStats (forall (m :: * -> *). Point m -> Double
pointTime Point m
p) Int
a'
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a. SignalSource m a -> a -> Event m ()
triggerSignal (forall (m :: * -> *) s. Resource m s -> SignalSource m Int
resourceCountSource Resource m s
r) Int
a'

-- | Update the resource utilisation count and its statistics.
updateResourceUtilisationCount :: MonadDES m => Resource m s -> Int -> Event m ()
{-# INLINABLE updateResourceUtilisationCount #-}
updateResourceUtilisationCount :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceUtilisationCount Resource m s
r Int
delta =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
a <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceUtilisationCountRef Resource m s
r)
     let a' :: Int
a' = Int
a forall a. Num a => a -> a -> a
+ Int
delta
     Int
a' seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceUtilisationCountRef Resource m s
r) Int
a'
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a.
MonadRef m =>
Ref m a -> (a -> a) -> Event m ()
modifyRef (forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceUtilisationCountStatsRef Resource m s
r) forall a b. (a -> b) -> a -> b
$
       forall a.
TimingData a =>
Double -> a -> TimingStats a -> TimingStats a
addTimingStats (forall (m :: * -> *). Point m -> Double
pointTime Point m
p) Int
a'
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a. SignalSource m a -> a -> Event m ()
triggerSignal (forall (m :: * -> *) s. Resource m s -> SignalSource m Int
resourceUtilisationCountSource Resource m s
r) Int
a'

-- | Update the resource queue length and its statistics.
updateResourceQueueCount :: MonadDES m => Resource m s -> Int -> Event m ()
{-# INLINABLE updateResourceQueueCount #-}
updateResourceQueueCount :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Int -> Event m ()
updateResourceQueueCount Resource m s
r Int
delta =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
a <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceQueueCountRef Resource m s
r)
     let a' :: Int
a' = Int
a forall a. Num a => a -> a -> a
+ Int
delta
     Int
a' seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceQueueCountRef Resource m s
r) Int
a'
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a.
MonadRef m =>
Ref m a -> (a -> a) -> Event m ()
modifyRef (forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceQueueCountStatsRef Resource m s
r) forall a b. (a -> b) -> a -> b
$
       forall a.
TimingData a =>
Double -> a -> TimingStats a -> TimingStats a
addTimingStats (forall (m :: * -> *). Point m -> Double
pointTime Point m
p) Int
a'
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a. SignalSource m a -> a -> Event m ()
triggerSignal (forall (m :: * -> *) s. Resource m s -> SignalSource m Int
resourceQueueCountSource Resource m s
r) Int
a'

-- | Update the resource wait time and its statistics.
updateResourceWaitTime :: MonadDES m => Resource m s -> Double -> Event m ()
{-# INLINABLE updateResourceWaitTime #-}
updateResourceWaitTime :: forall (m :: * -> *) s.
MonadDES m =>
Resource m s -> Double -> Event m ()
updateResourceWaitTime Resource m s
r Double
delta =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Double
a <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Double
resourceTotalWaitTimeRef Resource m s
r)
     let a' :: Double
a' = Double
a forall a. Num a => a -> a -> a
+ Double
delta
     Double
a' seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) s. Resource m s -> Ref m Double
resourceTotalWaitTimeRef Resource m s
r) Double
a'
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a.
MonadRef m =>
Ref m a -> (a -> a) -> Event m ()
modifyRef (forall (m :: * -> *) s.
Resource m s -> Ref m (SamplingStats Double)
resourceWaitTimeRef Resource m s
r) forall a b. (a -> b) -> a -> b
$
       forall a. SamplingData a => a -> SamplingStats a -> SamplingStats a
addSamplingStats Double
delta
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a. SignalSource m a -> a -> Event m ()
triggerSignal (forall (m :: * -> *) s. Resource m s -> SignalSource m ()
resourceWaitTimeSource Resource m s
r) ()

-- | Reset the statistics.
resetResource :: MonadDES m => Resource m s -> Event m ()
{-# INLINABLE resetResource #-}
resetResource :: forall (m :: * -> *) s. MonadDES m => Resource m s -> Event m ()
resetResource Resource m s
r =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do let t :: Double
t = forall (m :: * -> *). Point m -> Double
pointTime Point m
p
     Int
count <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceCountRef Resource m s
r)
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceCountStatsRef Resource m s
r) forall a b. (a -> b) -> a -> b
$
       forall a. TimingData a => Double -> a -> TimingStats a
returnTimingStats Double
t Int
count
     Int
utilCount <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceUtilisationCountRef Resource m s
r)
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceUtilisationCountStatsRef Resource m s
r) forall a b. (a -> b) -> a -> b
$
       forall a. TimingData a => Double -> a -> TimingStats a
returnTimingStats Double
t Int
utilCount
     Int
queueCount <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) s. Resource m s -> Ref m Int
resourceQueueCountRef Resource m s
r)
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) s. Resource m s -> Ref m (TimingStats Int)
resourceQueueCountStatsRef Resource m s
r) forall a b. (a -> b) -> a -> b
$
       forall a. TimingData a => Double -> a -> TimingStats a
returnTimingStats Double
t Int
queueCount
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) s. Resource m s -> Ref m Double
resourceTotalWaitTimeRef Resource m s
r) Double
0
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) s.
Resource m s -> Ref m (SamplingStats Double)
resourceWaitTimeRef Resource m s
r) forall a. SamplingData a => SamplingStats a
emptySamplingStats
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a. SignalSource m a -> a -> Event m ()
triggerSignal (forall (m :: * -> *) s. Resource m s -> SignalSource m ()
resourceWaitTimeSource Resource m s
r) ()