module Simulation.Aivika.Resource.Preemption.Base
(
Resource,
newResource,
newResourceWithMaxCount,
resourceMaxCount,
resourceCount,
requestResourceWithPriority,
releaseResource,
usingResourceWithPriority,
incResourceCount,
decResourceCount,
alterResourceCount) where
import Data.IORef
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 qualified Simulation.Aivika.PriorityQueue as PQ
data Resource =
Resource { Resource -> Maybe Int
resourceMaxCount :: Maybe Int,
Resource -> IORef Int
resourceCountRef :: IORef Int,
Resource -> PriorityQueue ResourceActingItem
resourceActingQueue :: PQ.PriorityQueue ResourceActingItem,
Resource -> PriorityQueue ResourceAwaitingItem
resourceWaitQueue :: PQ.PriorityQueue ResourceAwaitingItem }
data ResourceActingItem =
ResourceActingItem { ResourceActingItem -> Double
actingItemPriority :: Double,
ResourceActingItem -> ProcessId
actingItemId :: ProcessId }
type ResourceAwaitingItem = Either ResourceRequestingItem ResourcePreemptedItem
data ResourceRequestingItem =
ResourceRequestingItem { ResourceRequestingItem -> Double
requestingItemPriority :: Double,
ResourceRequestingItem -> ProcessId
requestingItemId :: ProcessId,
ResourceRequestingItem -> FrozenCont ()
requestingItemCont :: FrozenCont () }
data ResourcePreemptedItem =
ResourcePreemptedItem { ResourcePreemptedItem -> Double
preemptedItemPriority :: Double,
ResourcePreemptedItem -> ProcessId
preemptedItemId :: ProcessId }
instance Eq Resource where
Resource
x == :: Resource -> Resource -> Bool
== Resource
y = Resource -> IORef Int
resourceCountRef Resource
x IORef Int -> IORef Int -> Bool
forall a. Eq a => a -> a -> Bool
== Resource -> IORef Int
resourceCountRef Resource
y
instance Eq ResourceActingItem where
ResourceActingItem
x == :: ResourceActingItem -> ResourceActingItem -> Bool
== ResourceActingItem
y = ResourceActingItem -> ProcessId
actingItemId ResourceActingItem
x ProcessId -> ProcessId -> Bool
forall a. Eq a => a -> a -> Bool
== ResourceActingItem -> ProcessId
actingItemId ResourceActingItem
y
newResource :: Int
-> Simulation Resource
newResource :: Int -> Simulation Resource
newResource Int
count =
(Run -> IO Resource) -> Simulation Resource
forall a. (Run -> IO a) -> Simulation a
Simulation ((Run -> IO Resource) -> Simulation Resource)
-> (Run -> IO Resource) -> Simulation Resource
forall a b. (a -> b) -> a -> b
$ \Run
r ->
do Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
count Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
SimulationRetry -> IO ()
forall e a. Exception e => e -> IO a
throwIO (SimulationRetry -> IO ()) -> SimulationRetry -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SimulationRetry
SimulationRetry (String -> SimulationRetry) -> String -> SimulationRetry
forall a b. (a -> b) -> a -> b
$
String
"The resource count cannot be negative: " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"newResource."
IORef Int
countRef <- Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
count
PriorityQueue ResourceActingItem
actingQueue <- IO (PriorityQueue ResourceActingItem)
forall a. IO (PriorityQueue a)
PQ.newQueue
PriorityQueue ResourceAwaitingItem
waitQueue <- IO (PriorityQueue ResourceAwaitingItem)
forall a. IO (PriorityQueue a)
PQ.newQueue
Resource -> IO Resource
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Resource { resourceMaxCount :: Maybe Int
resourceMaxCount = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
count,
resourceCountRef :: IORef Int
resourceCountRef = IORef Int
countRef,
resourceActingQueue :: PriorityQueue ResourceActingItem
resourceActingQueue = PriorityQueue ResourceActingItem
actingQueue,
resourceWaitQueue :: PriorityQueue ResourceAwaitingItem
resourceWaitQueue = PriorityQueue ResourceAwaitingItem
waitQueue }
newResourceWithMaxCount :: Int
-> Maybe Int
-> Simulation Resource
newResourceWithMaxCount :: Int -> Maybe Int -> Simulation Resource
newResourceWithMaxCount Int
count Maybe Int
maxCount =
(Run -> IO Resource) -> Simulation Resource
forall a. (Run -> IO a) -> Simulation a
Simulation ((Run -> IO Resource) -> Simulation Resource)
-> (Run -> IO Resource) -> Simulation Resource
forall a b. (a -> b) -> a -> b
$ \Run
r ->
do Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
count Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
SimulationRetry -> IO ()
forall e a. Exception e => e -> IO a
throwIO (SimulationRetry -> IO ()) -> SimulationRetry -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SimulationRetry
SimulationRetry (String -> SimulationRetry) -> String -> SimulationRetry
forall a b. (a -> b) -> a -> b
$
String
"The resource count cannot be negative: " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"newResourceWithMaxCount."
case Maybe Int
maxCount of
Just Int
maxCount | Int
count Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
maxCount ->
SimulationRetry -> IO ()
forall e a. Exception e => e -> IO a
throwIO (SimulationRetry -> IO ()) -> SimulationRetry -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SimulationRetry
SimulationRetry (String -> SimulationRetry) -> String -> SimulationRetry
forall a b. (a -> b) -> a -> b
$
String
"The resource count cannot be greater than " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"its maximum value: newResourceWithMaxCount."
Maybe Int
_ ->
() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
IORef Int
countRef <- Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
count
PriorityQueue ResourceActingItem
actingQueue <- IO (PriorityQueue ResourceActingItem)
forall a. IO (PriorityQueue a)
PQ.newQueue
PriorityQueue ResourceAwaitingItem
waitQueue <- IO (PriorityQueue ResourceAwaitingItem)
forall a. IO (PriorityQueue a)
PQ.newQueue
Resource -> IO Resource
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Resource { resourceMaxCount :: Maybe Int
resourceMaxCount = Maybe Int
maxCount,
resourceCountRef :: IORef Int
resourceCountRef = IORef Int
countRef,
resourceActingQueue :: PriorityQueue ResourceActingItem
resourceActingQueue = PriorityQueue ResourceActingItem
actingQueue,
resourceWaitQueue :: PriorityQueue ResourceAwaitingItem
resourceWaitQueue = PriorityQueue ResourceAwaitingItem
waitQueue }
resourceCount :: Resource -> Event Int
resourceCount :: Resource -> Event Int
resourceCount Resource
r =
(Point -> IO Int) -> Event Int
forall a. (Point -> IO a) -> Event a
Event ((Point -> IO Int) -> Event Int) -> (Point -> IO Int) -> Event Int
forall a b. (a -> b) -> a -> b
$ \Point
p -> IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef (Resource -> IORef Int
resourceCountRef Resource
r)
requestResourceWithPriority :: Resource
-> Double
-> Process ()
requestResourceWithPriority :: Resource -> Double -> Process ()
requestResourceWithPriority Resource
r Double
priority =
(ProcessId -> Cont ()) -> Process ()
forall a. (ProcessId -> Cont a) -> Process a
Process ((ProcessId -> Cont ()) -> Process ())
-> (ProcessId -> Cont ()) -> Process ()
forall a b. (a -> b) -> a -> b
$ \ProcessId
pid ->
(ContParams () -> Event ()) -> Cont ()
forall a. (ContParams a -> Event ()) -> Cont a
Cont ((ContParams () -> Event ()) -> Cont ())
-> (ContParams () -> Event ()) -> Cont ()
forall a b. (a -> b) -> a -> b
$ \ContParams ()
c ->
(Point -> IO ()) -> Event ()
forall a. (Point -> IO a) -> Event a
Event ((Point -> IO ()) -> Event ()) -> (Point -> IO ()) -> Event ()
forall a b. (a -> b) -> a -> b
$ \Point
p ->
do Int
a <- IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef (Resource -> IORef Int
resourceCountRef Resource
r)
if Int
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
then do Bool
f <- PriorityQueue ResourceActingItem -> IO Bool
forall a. PriorityQueue a -> IO Bool
PQ.queueNull (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r)
if Bool
f
then do FrozenCont ()
c <- Point -> Event (FrozenCont ()) -> IO (FrozenCont ())
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event (FrozenCont ()) -> IO (FrozenCont ()))
-> Event (FrozenCont ()) -> IO (FrozenCont ())
forall a b. (a -> b) -> a -> b
$
ContParams () -> () -> Event () -> Event (FrozenCont ())
forall a. ContParams a -> a -> Event () -> Event (FrozenCont a)
freezeContReentering ContParams ()
c () (Event () -> Event (FrozenCont ()))
-> Event () -> Event (FrozenCont ())
forall a b. (a -> b) -> a -> b
$
ContParams () -> Cont () -> Event ()
forall a. ContParams a -> Cont a -> Event ()
invokeCont ContParams ()
c (Cont () -> Event ()) -> Cont () -> Event ()
forall a b. (a -> b) -> a -> b
$
ProcessId -> Process () -> Cont ()
forall a. ProcessId -> Process a -> Cont a
invokeProcess ProcessId
pid (Process () -> Cont ()) -> Process () -> Cont ()
forall a b. (a -> b) -> a -> b
$
Resource -> Double -> Process ()
requestResourceWithPriority Resource
r Double
priority
PriorityQueue ResourceAwaitingItem
-> Double -> ResourceAwaitingItem -> IO ()
forall a. PriorityQueue a -> Double -> a -> IO ()
PQ.enqueue (Resource -> PriorityQueue ResourceAwaitingItem
resourceWaitQueue Resource
r) Double
priority (ResourceRequestingItem -> ResourceAwaitingItem
forall a b. a -> Either a b
Left (ResourceRequestingItem -> ResourceAwaitingItem)
-> ResourceRequestingItem -> ResourceAwaitingItem
forall a b. (a -> b) -> a -> b
$ Double -> ProcessId -> FrozenCont () -> ResourceRequestingItem
ResourceRequestingItem Double
priority ProcessId
pid FrozenCont ()
c)
else do (Double
p0', ResourceActingItem
item0) <- PriorityQueue ResourceActingItem -> IO (Double, ResourceActingItem)
forall a. PriorityQueue a -> IO (Double, a)
PQ.queueFront (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r)
let p0 :: Double
p0 = - Double
p0'
pid0 :: ProcessId
pid0 = ResourceActingItem -> ProcessId
actingItemId ResourceActingItem
item0
if Double
priority Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
p0
then do PriorityQueue ResourceActingItem -> IO ()
forall a. PriorityQueue a -> IO ()
PQ.dequeue (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r)
PriorityQueue ResourceActingItem
-> Double -> ResourceActingItem -> IO ()
forall a. PriorityQueue a -> Double -> a -> IO ()
PQ.enqueue (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r) (- Double
priority) (ResourceActingItem -> IO ()) -> ResourceActingItem -> IO ()
forall a b. (a -> b) -> a -> b
$ Double -> ProcessId -> ResourceActingItem
ResourceActingItem Double
priority ProcessId
pid
PriorityQueue ResourceAwaitingItem
-> Double -> ResourceAwaitingItem -> IO ()
forall a. PriorityQueue a -> Double -> a -> IO ()
PQ.enqueue (Resource -> PriorityQueue ResourceAwaitingItem
resourceWaitQueue Resource
r) Double
p0 (ResourcePreemptedItem -> ResourceAwaitingItem
forall a b. b -> Either a b
Right (ResourcePreemptedItem -> ResourceAwaitingItem)
-> ResourcePreemptedItem -> ResourceAwaitingItem
forall a b. (a -> b) -> a -> b
$ Double -> ProcessId -> ResourcePreemptedItem
ResourcePreemptedItem Double
p0 ProcessId
pid0)
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ ProcessId -> Event ()
processPreemptionBegin ProcessId
pid0
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ ContParams () -> () -> Event ()
forall a. ContParams a -> a -> Event ()
resumeCont ContParams ()
c ()
else do FrozenCont ()
c <- Point -> Event (FrozenCont ()) -> IO (FrozenCont ())
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event (FrozenCont ()) -> IO (FrozenCont ()))
-> Event (FrozenCont ()) -> IO (FrozenCont ())
forall a b. (a -> b) -> a -> b
$
ContParams () -> () -> Event () -> Event (FrozenCont ())
forall a. ContParams a -> a -> Event () -> Event (FrozenCont a)
freezeContReentering ContParams ()
c () (Event () -> Event (FrozenCont ()))
-> Event () -> Event (FrozenCont ())
forall a b. (a -> b) -> a -> b
$
ContParams () -> Cont () -> Event ()
forall a. ContParams a -> Cont a -> Event ()
invokeCont ContParams ()
c (Cont () -> Event ()) -> Cont () -> Event ()
forall a b. (a -> b) -> a -> b
$
ProcessId -> Process () -> Cont ()
forall a. ProcessId -> Process a -> Cont a
invokeProcess ProcessId
pid (Process () -> Cont ()) -> Process () -> Cont ()
forall a b. (a -> b) -> a -> b
$
Resource -> Double -> Process ()
requestResourceWithPriority Resource
r Double
priority
PriorityQueue ResourceAwaitingItem
-> Double -> ResourceAwaitingItem -> IO ()
forall a. PriorityQueue a -> Double -> a -> IO ()
PQ.enqueue (Resource -> PriorityQueue ResourceAwaitingItem
resourceWaitQueue Resource
r) Double
priority (ResourceRequestingItem -> ResourceAwaitingItem
forall a b. a -> Either a b
Left (ResourceRequestingItem -> ResourceAwaitingItem)
-> ResourceRequestingItem -> ResourceAwaitingItem
forall a b. (a -> b) -> a -> b
$ Double -> ProcessId -> FrozenCont () -> ResourceRequestingItem
ResourceRequestingItem Double
priority ProcessId
pid FrozenCont ()
c)
else do let a' :: Int
a' = Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
Int
a' Int -> IO () -> IO ()
forall a b. a -> b -> b
`seq` IORef Int -> Int -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Resource -> IORef Int
resourceCountRef Resource
r) Int
a'
PriorityQueue ResourceActingItem
-> Double -> ResourceActingItem -> IO ()
forall a. PriorityQueue a -> Double -> a -> IO ()
PQ.enqueue (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r) (- Double
priority) (ResourceActingItem -> IO ()) -> ResourceActingItem -> IO ()
forall a b. (a -> b) -> a -> b
$ Double -> ProcessId -> ResourceActingItem
ResourceActingItem Double
priority ProcessId
pid
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ ContParams () -> () -> Event ()
forall a. ContParams a -> a -> Event ()
resumeCont ContParams ()
c ()
releaseResource :: Resource
-> Process ()
releaseResource :: Resource -> Process ()
releaseResource Resource
r =
(ProcessId -> Cont ()) -> Process ()
forall a. (ProcessId -> Cont a) -> Process a
Process ((ProcessId -> Cont ()) -> Process ())
-> (ProcessId -> Cont ()) -> Process ()
forall a b. (a -> b) -> a -> b
$ \ProcessId
pid ->
(ContParams () -> Event ()) -> Cont ()
forall a. (ContParams a -> Event ()) -> Cont a
Cont ((ContParams () -> Event ()) -> Cont ())
-> (ContParams () -> Event ()) -> Cont ()
forall a b. (a -> b) -> a -> b
$ \ContParams ()
c ->
(Point -> IO ()) -> Event ()
forall a. (Point -> IO a) -> Event a
Event ((Point -> IO ()) -> Event ()) -> (Point -> IO ()) -> Event ()
forall a b. (a -> b) -> a -> b
$ \Point
p ->
do Bool
f <- (Maybe ResourceActingItem -> Bool)
-> IO (Maybe ResourceActingItem) -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe ResourceActingItem -> Bool
forall a. Maybe a -> Bool
isJust (IO (Maybe ResourceActingItem) -> IO Bool)
-> IO (Maybe ResourceActingItem) -> IO Bool
forall a b. (a -> b) -> a -> b
$ PriorityQueue ResourceActingItem
-> (ResourceActingItem -> Bool) -> IO (Maybe ResourceActingItem)
forall a. PriorityQueue a -> (a -> Bool) -> IO (Maybe a)
PQ.queueDeleteBy (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r) (\ResourceActingItem
item -> ResourceActingItem -> ProcessId
actingItemId ResourceActingItem
item ProcessId -> ProcessId -> Bool
forall a. Eq a => a -> a -> Bool
== ProcessId
pid)
if Bool
f
then do Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ Resource -> Event ()
releaseResource' Resource
r
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ ContParams () -> () -> Event ()
forall a. ContParams a -> a -> Event ()
resumeCont ContParams ()
c ()
else SimulationRetry -> IO ()
forall e a. Exception e => e -> IO a
throwIO (SimulationRetry -> IO ()) -> SimulationRetry -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SimulationRetry
SimulationRetry
String
"The resource was not acquired by this process: releaseResource"
releaseResource' :: Resource
-> Event ()
releaseResource' :: Resource -> Event ()
releaseResource' Resource
r =
(Point -> IO ()) -> Event ()
forall a. (Point -> IO a) -> Event a
Event ((Point -> IO ()) -> Event ()) -> (Point -> IO ()) -> Event ()
forall a b. (a -> b) -> a -> b
$ \Point
p ->
do Int
a <- IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef (Resource -> IORef Int
resourceCountRef Resource
r)
let a' :: Int
a' = Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
case Resource -> Maybe Int
resourceMaxCount Resource
r of
Just Int
maxCount | Int
a' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
maxCount ->
SimulationRetry -> IO ()
forall e a. Exception e => e -> IO a
throwIO (SimulationRetry -> IO ()) -> SimulationRetry -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SimulationRetry
SimulationRetry (String -> SimulationRetry) -> String -> SimulationRetry
forall a b. (a -> b) -> a -> b
$
String
"The resource count cannot be greater than " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"its maximum value: releaseResource'."
Maybe Int
_ ->
() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Bool
f <- PriorityQueue ResourceAwaitingItem -> IO Bool
forall a. PriorityQueue a -> IO Bool
PQ.queueNull (Resource -> PriorityQueue ResourceAwaitingItem
resourceWaitQueue Resource
r)
if Bool
f
then Int
a' Int -> IO () -> IO ()
forall a b. a -> b -> b
`seq` IORef Int -> Int -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Resource -> IORef Int
resourceCountRef Resource
r) Int
a'
else do (Double
priority', ResourceAwaitingItem
item) <- PriorityQueue ResourceAwaitingItem
-> IO (Double, ResourceAwaitingItem)
forall a. PriorityQueue a -> IO (Double, a)
PQ.queueFront (Resource -> PriorityQueue ResourceAwaitingItem
resourceWaitQueue Resource
r)
PriorityQueue ResourceAwaitingItem -> IO ()
forall a. PriorityQueue a -> IO ()
PQ.dequeue (Resource -> PriorityQueue ResourceAwaitingItem
resourceWaitQueue Resource
r)
case ResourceAwaitingItem
item of
Left (ResourceRequestingItem Double
priority ProcessId
pid FrozenCont ()
c) ->
do Maybe (ContParams ())
c <- Point
-> Event (Maybe (ContParams ())) -> IO (Maybe (ContParams ()))
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event (Maybe (ContParams ())) -> IO (Maybe (ContParams ())))
-> Event (Maybe (ContParams ())) -> IO (Maybe (ContParams ()))
forall a b. (a -> b) -> a -> b
$ FrozenCont () -> Event (Maybe (ContParams ()))
forall a. FrozenCont a -> Event (Maybe (ContParams a))
unfreezeCont FrozenCont ()
c
case Maybe (ContParams ())
c of
Maybe (ContParams ())
Nothing ->
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ Resource -> Event ()
releaseResource' Resource
r
Just ContParams ()
c ->
do PriorityQueue ResourceActingItem
-> Double -> ResourceActingItem -> IO ()
forall a. PriorityQueue a -> Double -> a -> IO ()
PQ.enqueue (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r) (- Double
priority) (ResourceActingItem -> IO ()) -> ResourceActingItem -> IO ()
forall a b. (a -> b) -> a -> b
$ Double -> ProcessId -> ResourceActingItem
ResourceActingItem Double
priority ProcessId
pid
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ Double -> Event () -> Event ()
enqueueEvent (Point -> Double
pointTime Point
p) (Event () -> Event ()) -> Event () -> Event ()
forall a b. (a -> b) -> a -> b
$ ContParams () -> () -> Event ()
forall a. ContParams a -> a -> Event ()
reenterCont ContParams ()
c ()
Right (ResourcePreemptedItem Double
priority ProcessId
pid) ->
do Bool
f <- Point -> Event Bool -> IO Bool
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event Bool -> IO Bool) -> Event Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ ProcessId -> Event Bool
processCancelled ProcessId
pid
case Bool
f of
Bool
True ->
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ Resource -> Event ()
releaseResource' Resource
r
Bool
False ->
do PriorityQueue ResourceActingItem
-> Double -> ResourceActingItem -> IO ()
forall a. PriorityQueue a -> Double -> a -> IO ()
PQ.enqueue (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r) (- Double
priority) (ResourceActingItem -> IO ()) -> ResourceActingItem -> IO ()
forall a b. (a -> b) -> a -> b
$ Double -> ProcessId -> ResourceActingItem
ResourceActingItem Double
priority ProcessId
pid
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ ProcessId -> Event ()
processPreemptionEnd ProcessId
pid
usingResourceWithPriority :: Resource
-> Double
-> Process a
-> Process a
usingResourceWithPriority :: forall a. Resource -> Double -> Process a -> Process a
usingResourceWithPriority Resource
r Double
priority Process a
m =
do Resource -> Double -> Process ()
requestResourceWithPriority Resource
r Double
priority
Process a -> Process () -> Process a
forall a b. Process a -> Process b -> Process a
finallyProcess Process a
m (Process () -> Process a) -> Process () -> Process a
forall a b. (a -> b) -> a -> b
$ Resource -> Process ()
releaseResource Resource
r
decResourceCount' :: Resource -> Event ()
decResourceCount' :: Resource -> Event ()
decResourceCount' Resource
r =
(Point -> IO ()) -> Event ()
forall a. (Point -> IO a) -> Event a
Event ((Point -> IO ()) -> Event ()) -> (Point -> IO ()) -> Event ()
forall a b. (a -> b) -> a -> b
$ \Point
p ->
do Int
a <- IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef (Resource -> IORef Int
resourceCountRef Resource
r)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
SimulationRetry -> IO ()
forall e a. Exception e => e -> IO a
throwIO (SimulationRetry -> IO ()) -> SimulationRetry -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> SimulationRetry
SimulationRetry
String
"The resource exceeded and its count is zero: decResourceCount'"
Bool
f <- PriorityQueue ResourceActingItem -> IO Bool
forall a. PriorityQueue a -> IO Bool
PQ.queueNull (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
f (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
do (Double
p0', ResourceActingItem
item0) <- PriorityQueue ResourceActingItem -> IO (Double, ResourceActingItem)
forall a. PriorityQueue a -> IO (Double, a)
PQ.queueFront (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r)
let p0 :: Double
p0 = - Double
p0'
pid0 :: ProcessId
pid0 = ResourceActingItem -> ProcessId
actingItemId ResourceActingItem
item0
PriorityQueue ResourceActingItem -> IO ()
forall a. PriorityQueue a -> IO ()
PQ.dequeue (Resource -> PriorityQueue ResourceActingItem
resourceActingQueue Resource
r)
PriorityQueue ResourceAwaitingItem
-> Double -> ResourceAwaitingItem -> IO ()
forall a. PriorityQueue a -> Double -> a -> IO ()
PQ.enqueue (Resource -> PriorityQueue ResourceAwaitingItem
resourceWaitQueue Resource
r) Double
p0 (ResourcePreemptedItem -> ResourceAwaitingItem
forall a b. b -> Either a b
Right (ResourcePreemptedItem -> ResourceAwaitingItem)
-> ResourcePreemptedItem -> ResourceAwaitingItem
forall a b. (a -> b) -> a -> b
$ Double -> ProcessId -> ResourcePreemptedItem
ResourcePreemptedItem Double
p0 ProcessId
pid0)
Point -> Event () -> IO ()
forall a. Point -> Event a -> IO a
invokeEvent Point
p (Event () -> IO ()) -> Event () -> IO ()
forall a b. (a -> b) -> a -> b
$ ProcessId -> Event ()
processPreemptionBegin ProcessId
pid0
let a' :: Int
a' = Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
Int
a' Int -> IO () -> IO ()
forall a b. a -> b -> b
`seq` IORef Int -> Int -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Resource -> IORef Int
resourceCountRef Resource
r) Int
a'
incResourceCount :: Resource
-> Int
-> Event ()
incResourceCount :: Resource -> Int -> Event ()
incResourceCount Resource
r Int
n
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = SimulationRetry -> Event ()
forall e a. Exception e => e -> Event a
throwEvent (SimulationRetry -> Event ()) -> SimulationRetry -> Event ()
forall a b. (a -> b) -> a -> b
$ String -> SimulationRetry
SimulationRetry String
"The increment cannot be negative: incResourceCount"
| Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = () -> Event ()
forall a. a -> Event a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise =
do Resource -> Event ()
releaseResource' Resource
r
Resource -> Int -> Event ()
incResourceCount Resource
r (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
decResourceCount :: Resource
-> Int
-> Event ()
decResourceCount :: Resource -> Int -> Event ()
decResourceCount Resource
r Int
n
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = SimulationRetry -> Event ()
forall e a. Exception e => e -> Event a
throwEvent (SimulationRetry -> Event ()) -> SimulationRetry -> Event ()
forall a b. (a -> b) -> a -> b
$ String -> SimulationRetry
SimulationRetry String
"The decrement cannot be negative: decResourceCount"
| Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = () -> Event ()
forall a. a -> Event a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise =
do Resource -> Event ()
decResourceCount' Resource
r
Resource -> Int -> Event ()
decResourceCount Resource
r (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
alterResourceCount :: Resource
-> Int
-> Event ()
alterResourceCount :: Resource -> Int -> Event ()
alterResourceCount Resource
r Int
n
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Resource -> Int -> Event ()
decResourceCount Resource
r (- Int
n)
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = Resource -> Int -> Event ()
incResourceCount Resource
r Int
n
| Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = () -> Event ()
forall a. a -> Event a
forall (m :: * -> *) a. Monad m => a -> m a
return ()