module Simulation.Aivika.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.IORef
import Data.Monoid
import Data.Maybe
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Internal.Specs
import Simulation.Aivika.Internal.Simulation
import Simulation.Aivika.Internal.Dynamics
import Simulation.Aivika.Internal.Event
import Simulation.Aivika.Internal.Process
import Simulation.Aivika.Resource.Base
import Simulation.Aivika.QueueStrategy
import qualified Simulation.Aivika.DoubleLinkedList as DLL
import qualified Simulation.Aivika.Vector as V
import qualified Simulation.Aivika.PriorityQueue as PQ
type FCFSQueue a = Queue FCFS FCFS FCFS a
type LCFSQueue a = Queue FCFS LCFS FCFS a
type SIROQueue a = Queue FCFS SIRO FCFS a
type PriorityQueue a = Queue FCFS StaticPriorities FCFS a
data Queue si sm so a =
Queue { queueMaxCount :: Int,
enqueueStrategy :: si,
enqueueStoringStrategy :: sm,
dequeueStrategy :: so,
enqueueRes :: Resource si,
queueStore :: StrategyQueue sm a,
dequeueRes :: Resource so,
queueCountRef :: IORef Int
}
newFCFSQueue :: Int -> Simulation (FCFSQueue a)
newFCFSQueue = newQueue FCFS FCFS FCFS
newLCFSQueue :: Int -> Simulation (LCFSQueue a)
newLCFSQueue = newQueue FCFS LCFS FCFS
newSIROQueue :: Int -> Simulation (SIROQueue a)
newSIROQueue = newQueue FCFS SIRO FCFS
newPriorityQueue :: Int -> Simulation (PriorityQueue a)
newPriorityQueue = newQueue FCFS StaticPriorities FCFS
newQueue :: (QueueStrategy si,
QueueStrategy sm,
QueueStrategy so) =>
si
-> sm
-> so
-> Int
-> Simulation (Queue si sm so a)
newQueue si sm so count =
do i <- liftIO $ newIORef 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 :: Queue si sm so a -> Event Bool
queueNull q =
Event $ \p ->
do n <- readIORef (queueCountRef q)
return (n == 0)
queueFull :: Queue si sm so a -> Event Bool
queueFull q =
Event $ \p ->
do n <- readIORef (queueCountRef q)
return (n == queueMaxCount q)
queueCount :: Queue si sm so a -> Event Int
queueCount q =
Event $ \p -> readIORef (queueCountRef q)
dequeue :: (DequeueStrategy si,
DequeueStrategy sm,
EnqueueStrategy so)
=> Queue si sm so a
-> Process a
dequeue q =
do requestResource (dequeueRes q)
liftEvent $ dequeueExtract q
dequeueWithOutputPriority :: (DequeueStrategy si,
DequeueStrategy sm,
PriorityQueueStrategy so po)
=> Queue si sm so a
-> po
-> Process a
dequeueWithOutputPriority q po =
do requestResourceWithPriority (dequeueRes q) po
liftEvent $ dequeueExtract q
tryDequeue :: (DequeueStrategy si,
DequeueStrategy sm)
=> Queue si sm so a
-> Event (Maybe a)
tryDequeue q =
do x <- tryRequestResourceWithinEvent (dequeueRes q)
if x
then fmap Just $ dequeueExtract q
else return Nothing
queueDelete :: (Eq a,
DequeueStrategy si,
DeletingQueueStrategy sm,
DequeueStrategy so)
=> Queue si sm so a
-> a
-> Event Bool
queueDelete q a = fmap isJust $ queueDeleteBy q (== a)
queueDelete_ :: (Eq a,
DequeueStrategy si,
DeletingQueueStrategy sm,
DequeueStrategy so)
=> Queue si sm so a
-> a
-> Event ()
queueDelete_ q a = fmap (const ()) $ queueDeleteBy q (== a)
queueDeleteBy :: (DequeueStrategy si,
DeletingQueueStrategy sm,
DequeueStrategy so)
=> Queue si sm so a
-> (a -> Bool)
-> Event (Maybe a)
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_ :: (DequeueStrategy si,
DeletingQueueStrategy sm,
DequeueStrategy so)
=> Queue si sm so a
-> (a -> Bool)
-> Event ()
queueDeleteBy_ q pred = fmap (const ()) $ queueDeleteBy q pred
queueContains :: (Eq a,
DeletingQueueStrategy sm)
=> Queue si sm so a
-> a
-> Event Bool
queueContains q a = fmap isJust $ queueContainsBy q (== a)
queueContainsBy :: DeletingQueueStrategy sm
=> Queue si sm so a
-> (a -> Bool)
-> Event (Maybe a)
queueContainsBy q pred =
strategyQueueContainsBy (queueStore q) pred
clearQueue :: (DequeueStrategy si,
DequeueStrategy sm)
=> Queue si sm so a
-> Event ()
clearQueue q =
do x <- tryDequeue q
case x of
Nothing -> return ()
Just a -> clearQueue q
enqueue :: (EnqueueStrategy si,
EnqueueStrategy sm,
DequeueStrategy so)
=> Queue si sm so a
-> a
-> Process ()
enqueue q a =
do requestResource (enqueueRes q)
liftEvent $ enqueueStore q a
enqueueWithInputPriority :: (PriorityQueueStrategy si pi,
EnqueueStrategy sm,
DequeueStrategy so)
=> Queue si sm so a
-> pi
-> a
-> Process ()
enqueueWithInputPriority q pi a =
do requestResourceWithPriority (enqueueRes q) pi
liftEvent $ enqueueStore q a
enqueueWithStoringPriority :: (EnqueueStrategy si,
PriorityQueueStrategy sm pm,
DequeueStrategy so)
=> Queue si sm so a
-> pm
-> a
-> Process ()
enqueueWithStoringPriority q pm a =
do requestResource (enqueueRes q)
liftEvent $ enqueueStoreWithPriority q pm a
enqueueWithInputStoringPriorities :: (PriorityQueueStrategy si pi,
PriorityQueueStrategy sm pm,
DequeueStrategy so)
=> Queue si sm so a
-> pi
-> pm
-> a
-> Process ()
enqueueWithInputStoringPriorities q pi pm a =
do requestResourceWithPriority (enqueueRes q) pi
liftEvent $ enqueueStoreWithPriority q pm a
tryEnqueue :: (EnqueueStrategy sm,
DequeueStrategy so)
=> Queue si sm so a
-> a
-> Event Bool
tryEnqueue q a =
do x <- tryRequestResourceWithinEvent (enqueueRes q)
if x
then do enqueueStore q a
return True
else return False
tryEnqueueWithStoringPriority :: (PriorityQueueStrategy sm pm,
DequeueStrategy so)
=> Queue si sm so a
-> pm
-> a
-> Event Bool
tryEnqueueWithStoringPriority q pm a =
do x <- tryRequestResourceWithinEvent (enqueueRes q)
if x
then do enqueueStoreWithPriority q pm a
return True
else return False
enqueueStore :: (EnqueueStrategy sm,
DequeueStrategy so)
=> Queue si sm so a
-> a
-> Event ()
enqueueStore q a =
Event $ \p ->
do invokeEvent p $
strategyEnqueue (queueStore q) a
c <- readIORef (queueCountRef q)
let c' = c + 1
c' `seq` writeIORef (queueCountRef q) c'
invokeEvent p $
releaseResourceWithinEvent (dequeueRes q)
enqueueStoreWithPriority :: (PriorityQueueStrategy sm pm,
DequeueStrategy so)
=> Queue si sm so a
-> pm
-> a
-> Event ()
enqueueStoreWithPriority q pm a =
Event $ \p ->
do invokeEvent p $
strategyEnqueueWithPriority (queueStore q) pm a
c <- readIORef (queueCountRef q)
let c' = c + 1
c' `seq` writeIORef (queueCountRef q) c'
invokeEvent p $
releaseResourceWithinEvent (dequeueRes q)
dequeueExtract :: (DequeueStrategy si,
DequeueStrategy sm)
=> Queue si sm so a
-> Event a
dequeueExtract q =
Event $ \p ->
do a <- invokeEvent p $
strategyDequeue (queueStore q)
invokeEvent p $
dequeuePostExtract q a
dequeuePostExtract :: (DequeueStrategy si,
DequeueStrategy sm)
=> Queue si sm so a
-> a
-> Event a
dequeuePostExtract q a =
Event $ \p ->
do c <- readIORef (queueCountRef q)
let c' = c - 1
c' `seq` writeIORef (queueCountRef q) c'
invokeEvent p $
releaseResourceWithinEvent (enqueueRes q)
return a