{-# LANGUAGE FlexibleContexts #-}
module Simulation.Aivika.Trans.Queue.Base
(
FCFSQueue,
LCFSQueue,
SIROQueue,
PriorityQueue,
Queue,
newFCFSQueue,
newLCFSQueue,
newSIROQueue,
newPriorityQueue,
newQueue,
enqueueStrategy,
enqueueStoringStrategy,
dequeueStrategy,
queueNull,
queueFull,
queueMaxCount,
queueCount,
dequeue,
dequeueWithOutputPriority,
tryDequeue,
enqueue,
enqueueWithInputPriority,
enqueueWithStoringPriority,
enqueueWithInputStoringPriorities,
tryEnqueue,
tryEnqueueWithStoringPriority,
queueDelete,
queueDelete_,
queueDeleteBy,
queueDeleteBy_,
queueContains,
queueContainsBy,
clearQueue) where
import Data.Monoid
import Data.Maybe
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Trans.Ref.Base
import Simulation.Aivika.Trans.DES
import Simulation.Aivika.Trans.Internal.Specs
import Simulation.Aivika.Trans.Internal.Parameter
import Simulation.Aivika.Trans.Internal.Simulation
import Simulation.Aivika.Trans.Internal.Dynamics
import Simulation.Aivika.Trans.Internal.Event
import Simulation.Aivika.Trans.Internal.Process
import Simulation.Aivika.Trans.Resource.Base
import Simulation.Aivika.Trans.QueueStrategy
type FCFSQueue m a = Queue m FCFS FCFS FCFS a
type LCFSQueue m a = Queue m FCFS LCFS FCFS a
type SIROQueue m a = Queue m FCFS SIRO FCFS a
type PriorityQueue m a = Queue m FCFS StaticPriorities FCFS a
data Queue m si sm so a =
Queue { queueMaxCount :: Int,
enqueueStrategy :: si,
enqueueStoringStrategy :: sm,
dequeueStrategy :: so,
enqueueRes :: Resource m si,
queueStore :: StrategyQueue m sm a,
dequeueRes :: Resource m so,
queueCountRef :: Ref m Int
}
newFCFSQueue :: MonadDES m => Int -> Simulation m (FCFSQueue m a)
{-# INLINABLE newFCFSQueue #-}
newFCFSQueue = newQueue FCFS FCFS FCFS
newLCFSQueue :: MonadDES m => Int -> Simulation m (LCFSQueue m a)
{-# INLINABLE newLCFSQueue #-}
newLCFSQueue = newQueue FCFS LCFS FCFS
newSIROQueue :: (MonadDES m, QueueStrategy m SIRO) => Int -> Simulation m (SIROQueue m a)
{-# INLINABLE newSIROQueue #-}
newSIROQueue = newQueue FCFS SIRO FCFS
newPriorityQueue :: (MonadDES m, QueueStrategy m StaticPriorities) => Int -> Simulation m (PriorityQueue m a)
{-# INLINABLE newPriorityQueue #-}
newPriorityQueue = newQueue FCFS StaticPriorities FCFS
newQueue :: (MonadDES m,
QueueStrategy m si,
QueueStrategy m sm,
QueueStrategy m so) =>
si
-> sm
-> so
-> Int
-> Simulation m (Queue m si sm so a)
{-# INLINABLE newQueue #-}
newQueue si sm so count =
do i <- newRef 0
ri <- newResourceWithMaxCount si count (Just count)
qm <- newStrategyQueue sm
ro <- newResourceWithMaxCount so 0 (Just count)
return Queue { queueMaxCount = count,
enqueueStrategy = si,
enqueueStoringStrategy = sm,
dequeueStrategy = so,
enqueueRes = ri,
queueStore = qm,
dequeueRes = ro,
queueCountRef = i }
queueNull :: MonadDES m => Queue m si sm so a -> Event m Bool
{-# INLINABLE queueNull #-}
queueNull q =
Event $ \p ->
do n <- invokeEvent p $ readRef (queueCountRef q)
return (n == 0)
queueFull :: MonadDES m => Queue m si sm so a -> Event m Bool
{-# INLINABLE queueFull #-}
queueFull q =
Event $ \p ->
do n <- invokeEvent p $ readRef (queueCountRef q)
return (n == queueMaxCount q)
queueCount :: MonadDES m => Queue m si sm so a -> Event m Int
{-# INLINABLE queueCount #-}
queueCount q =
Event $ \p -> invokeEvent p $ readRef (queueCountRef q)
dequeue :: (MonadDES m,
DequeueStrategy m si,
DequeueStrategy m sm,
EnqueueStrategy m so)
=> Queue m si sm so a
-> Process m a
{-# INLINABLE dequeue #-}
dequeue q =
do requestResource (dequeueRes q)
liftEvent $ dequeueExtract q
dequeueWithOutputPriority :: (MonadDES m,
DequeueStrategy m si,
DequeueStrategy m sm,
PriorityQueueStrategy m so po)
=> Queue m si sm so a
-> po
-> Process m a
{-# INLINABLE dequeueWithOutputPriority #-}
dequeueWithOutputPriority q po =
do requestResourceWithPriority (dequeueRes q) po
liftEvent $ dequeueExtract q
tryDequeue :: (MonadDES m,
DequeueStrategy m si,
DequeueStrategy m sm)
=> Queue m si sm so a
-> Event m (Maybe a)
{-# INLINABLE tryDequeue #-}
tryDequeue q =
do x <- tryRequestResourceWithinEvent (dequeueRes q)
if x
then fmap Just $ dequeueExtract q
else return Nothing
queueDelete :: (MonadDES m,
Eq a,
DequeueStrategy m si,
DeletingQueueStrategy m sm,
DequeueStrategy m so)
=> Queue m si sm so a
-> a
-> Event m Bool
{-# INLINABLE queueDelete #-}
queueDelete q a = fmap isJust $ queueDeleteBy q (== a)
queueDelete_ :: (MonadDES m,
Eq a,
DequeueStrategy m si,
DeletingQueueStrategy m sm,
DequeueStrategy m so)
=> Queue m si sm so a
-> a
-> Event m ()
{-# INLINABLE queueDelete_ #-}
queueDelete_ q a = fmap (const ()) $ queueDeleteBy q (== a)
queueDeleteBy :: (MonadDES m,
DequeueStrategy m si,
DeletingQueueStrategy m sm,
DequeueStrategy m so)
=> Queue m si sm so a
-> (a -> Bool)
-> Event m (Maybe a)
{-# INLINABLE queueDeleteBy #-}
queueDeleteBy q pred =
do x <- tryRequestResourceWithinEvent (dequeueRes q)
if x
then do i <- strategyQueueDeleteBy (queueStore q) pred
case i of
Nothing ->
do releaseResourceWithinEvent (dequeueRes q)
return Nothing
Just i ->
fmap Just $ dequeuePostExtract q i
else return Nothing
queueDeleteBy_ :: (MonadDES m,
DequeueStrategy m si,
DeletingQueueStrategy m sm,
DequeueStrategy m so)
=> Queue m si sm so a
-> (a -> Bool)
-> Event m ()
{-# INLINABLE queueDeleteBy_ #-}
queueDeleteBy_ q pred = fmap (const ()) $ queueDeleteBy q pred
queueContains :: (MonadDES m,
Eq a,
DeletingQueueStrategy m sm)
=> Queue m si sm so a
-> a
-> Event m Bool
{-# INLINABLE queueContains #-}
queueContains q a = fmap isJust $ queueContainsBy q (== a)
queueContainsBy :: (MonadDES m,
DeletingQueueStrategy m sm)
=> Queue m si sm so a
-> (a -> Bool)
-> Event m (Maybe a)
{-# INLINABLE queueContainsBy #-}
queueContainsBy q pred =
strategyQueueContainsBy (queueStore q) pred
clearQueue :: (MonadDES m,
DequeueStrategy m si,
DequeueStrategy m sm)
=> Queue m si sm so a
-> Event m ()
{-# INLINABLE clearQueue #-}
clearQueue q =
do x <- tryDequeue q
case x of
Nothing -> return ()
Just a -> clearQueue q
enqueue :: (MonadDES m,
EnqueueStrategy m si,
EnqueueStrategy m sm,
DequeueStrategy m so)
=> Queue m si sm so a
-> a
-> Process m ()
{-# INLINABLE enqueue #-}
enqueue q a =
do requestResource (enqueueRes q)
liftEvent $ enqueueStore q a
enqueueWithInputPriority :: (MonadDES m,
PriorityQueueStrategy m si pi,
EnqueueStrategy m sm,
DequeueStrategy m so)
=> Queue m si sm so a
-> pi
-> a
-> Process m ()
{-# INLINABLE enqueueWithInputPriority #-}
enqueueWithInputPriority q pi a =
do requestResourceWithPriority (enqueueRes q) pi
liftEvent $ enqueueStore q a
enqueueWithStoringPriority :: (MonadDES m,
EnqueueStrategy m si,
PriorityQueueStrategy m sm pm,
DequeueStrategy m so)
=> Queue m si sm so a
-> pm
-> a
-> Process m ()
{-# INLINABLE enqueueWithStoringPriority #-}
enqueueWithStoringPriority q pm a =
do requestResource (enqueueRes q)
liftEvent $ enqueueStoreWithPriority q pm a
enqueueWithInputStoringPriorities :: (MonadDES m,
PriorityQueueStrategy m si pi,
PriorityQueueStrategy m sm pm,
DequeueStrategy m so)
=> Queue m si sm so a
-> pi
-> pm
-> a
-> Process m ()
{-# INLINABLE enqueueWithInputStoringPriorities #-}
enqueueWithInputStoringPriorities q pi pm a =
do requestResourceWithPriority (enqueueRes q) pi
liftEvent $ enqueueStoreWithPriority q pm a
tryEnqueue :: (MonadDES m,
EnqueueStrategy m sm,
DequeueStrategy m so)
=> Queue m si sm so a
-> a
-> Event m Bool
{-# INLINABLE tryEnqueue #-}
tryEnqueue q a =
do x <- tryRequestResourceWithinEvent (enqueueRes q)
if x
then do enqueueStore q a
return True
else return False
tryEnqueueWithStoringPriority :: (MonadDES m,
PriorityQueueStrategy m sm pm,
DequeueStrategy m so)
=> Queue m si sm so a
-> pm
-> a
-> Event m Bool
{-# INLINABLE tryEnqueueWithStoringPriority #-}
tryEnqueueWithStoringPriority q pm a =
do x <- tryRequestResourceWithinEvent (enqueueRes q)
if x
then do enqueueStoreWithPriority q pm a
return True
else return False
enqueueStore :: (MonadDES m,
EnqueueStrategy m sm,
DequeueStrategy m so)
=> Queue m si sm so a
-> a
-> Event m ()
{-# INLINE enqueueStore #-}
enqueueStore q a =
Event $ \p ->
do invokeEvent p $
strategyEnqueue (queueStore q) a
c <- invokeEvent p $
readRef (queueCountRef q)
let c' = c + 1
c' `seq` invokeEvent p $
writeRef (queueCountRef q) c'
invokeEvent p $
releaseResourceWithinEvent (dequeueRes q)
enqueueStoreWithPriority :: (MonadDES m,
PriorityQueueStrategy m sm pm,
DequeueStrategy m so)
=> Queue m si sm so a
-> pm
-> a
-> Event m ()
{-# INLINE enqueueStoreWithPriority #-}
enqueueStoreWithPriority q pm a =
Event $ \p ->
do invokeEvent p $
strategyEnqueueWithPriority (queueStore q) pm a
c <- invokeEvent p $
readRef (queueCountRef q)
let c' = c + 1
c' `seq` invokeEvent p $
writeRef (queueCountRef q) c'
invokeEvent p $
releaseResourceWithinEvent (dequeueRes q)
dequeueExtract :: (MonadDES m,
DequeueStrategy m si,
DequeueStrategy m sm)
=> Queue m si sm so a
-> Event m a
{-# INLINE dequeueExtract #-}
dequeueExtract q =
Event $ \p ->
do a <- invokeEvent p $
strategyDequeue (queueStore q)
invokeEvent p $
dequeuePostExtract q a
dequeuePostExtract :: (MonadDES m,
DequeueStrategy m si,
DequeueStrategy m sm)
=> Queue m si sm so a
-> a
-> Event m a
{-# INLINE dequeuePostExtract #-}
dequeuePostExtract q a =
Event $ \p ->
do c <- invokeEvent p $
readRef (queueCountRef q)
let c' = c - 1
c' `seq` invokeEvent p $
writeRef (queueCountRef q) c'
invokeEvent p $
releaseResourceWithinEvent (enqueueRes q)
return a