{-# LANGUAGE TypeFamilies #-} -- | -- Module : Simulation.Aivika.Trans.Resource.Preemption.Base -- 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 preemptible resource. -- -- The module is optimised in the sense that this kind of the resource -- has neither additional signals, nor counters that would may slow -- down the simulation. -- module Simulation.Aivika.Trans.Resource.Preemption.Base (MonadResource(..)) where import Control.Monad import Control.Monad.Trans import Simulation.Aivika.Trans.DES import Simulation.Aivika.Trans.Internal.Simulation import Simulation.Aivika.Trans.Internal.Event import Simulation.Aivika.Trans.Internal.Process -- | A type class of monads whithin which we can create preemptible resources. class MonadDES m => MonadResource m where -- | Represents a preemptible resource. data Resource m -- | Create a new resource with the specified initial count that becomes the upper bound as well. newResource :: Int -- ^ the initial count (and maximal count too) of the resource -> Simulation m (Resource m) -- | Create a new resource with the specified initial and maximum counts, -- where 'Nothing' means that the resource has no upper bound. newResourceWithMaxCount :: Int -- ^ the initial count of the resource -> Maybe Int -- ^ the maximum count of the resource, which can be indefinite -> Simulation m (Resource m) -- | Return the current count of the resource. resourceCount :: Resource m -> Event m Int -- | Return the maximum count of the resource, where 'Nothing' -- means that the resource has no upper bound. resourceMaxCount :: Resource m -> Maybe Int -- | 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. -- -- It may preempt another process if the latter aquired the resource before -- but had a lower priority. Then the current process takes an ownership of -- the resource. requestResourceWithPriority :: Resource m -- ^ the requested resource -> Double -- ^ the priority (the less value has a higher priority) -> Process m () -- | Release the resource increasing its count and resuming one of the -- previously suspended or preempted processes as possible. releaseResource :: Resource m -- ^ the resource to release -> Process m () -- | 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 :: Resource m -- ^ the resource we are going to request for and then -- release in the end -> Double -- ^ the priority (the less value has a higher priority) -> Process m a -- ^ the action we are going to apply having the resource -> Process m a -- ^ the result of the action -- | Increase the count of available resource by the specified number, -- invoking the awaiting and preempted processes according to their priorities -- as needed. incResourceCount :: Resource m -- ^ the resource -> Int -- ^ the increment for the resource count -> Event m () -- | Decrease the count of available resource by the specified number, -- preempting the processes according to their priorities as needed. decResourceCount :: Resource m -- ^ the resource -> Int -- ^ the decrement for the resource count -> Event m () -- | Alter the resource count either increasing or decreasing it by calling -- 'incResourceCount' or 'decResourceCount' respectively. alterResourceCount :: Resource m -- ^ the resource -> Int -- ^ a change of the resource count -> Event m ()