module Simulation.Aivika.Queue.Infinite.Base
(
FCFSQueue,
LCFSQueue,
SIROQueue,
PriorityQueue,
Queue,
newFCFSQueue,
newLCFSQueue,
newSIROQueue,
newPriorityQueue,
newQueue,
enqueueStoringStrategy,
dequeueStrategy,
queueNull,
queueCount,
dequeue,
dequeueWithOutputPriority,
tryDequeue,
enqueue,
enqueueWithStoringPriority,
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 a
type LCFSQueue a = Queue LCFS FCFS a
type SIROQueue a = Queue SIRO FCFS a
type PriorityQueue a = Queue StaticPriorities FCFS a
data Queue sm so a =
Queue { enqueueStoringStrategy :: sm,
dequeueStrategy :: so,
queueStore :: StrategyQueue sm a,
dequeueRes :: Resource so,
queueCountRef :: IORef Int }
newFCFSQueue :: Simulation (FCFSQueue a)
newFCFSQueue = newQueue FCFS FCFS
newLCFSQueue :: Simulation (LCFSQueue a)
newLCFSQueue = newQueue LCFS FCFS
newSIROQueue :: Simulation (SIROQueue a)
newSIROQueue = newQueue SIRO FCFS
newPriorityQueue :: Simulation (PriorityQueue a)
newPriorityQueue = newQueue StaticPriorities FCFS
newQueue :: (QueueStrategy sm,
QueueStrategy so) =>
sm
-> so
-> Simulation (Queue sm so a)
newQueue sm so =
do i <- liftIO $ newIORef 0
qm <- newStrategyQueue sm
ro <- newResourceWithMaxCount so 0 Nothing
return Queue { enqueueStoringStrategy = sm,
dequeueStrategy = so,
queueStore = qm,
dequeueRes = ro,
queueCountRef = i }
queueNull :: Queue sm so a -> Event Bool
queueNull q =
Event $ \p ->
do n <- readIORef (queueCountRef q)
return (n == 0)
queueCount :: Queue sm so a -> Event Int
queueCount q =
Event $ \p -> readIORef (queueCountRef q)
dequeue :: (DequeueStrategy sm,
EnqueueStrategy so)
=> Queue sm so a
-> Process a
dequeue q =
do requestResource (dequeueRes q)
liftEvent $ dequeueExtract q
dequeueWithOutputPriority :: (DequeueStrategy sm,
PriorityQueueStrategy so po)
=> Queue sm so a
-> po
-> Process a
dequeueWithOutputPriority q po =
do requestResourceWithPriority (dequeueRes q) po
liftEvent $ dequeueExtract q
tryDequeue :: DequeueStrategy sm
=> Queue 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,
DeletingQueueStrategy sm,
DequeueStrategy so)
=> Queue sm so a
-> a
-> Event Bool
queueDelete q a = fmap isJust $ queueDeleteBy q (== a)
queueDelete_ :: (Eq a,
DeletingQueueStrategy sm,
DequeueStrategy so)
=> Queue sm so a
-> a
-> Event ()
queueDelete_ q a = fmap (const ()) $ queueDeleteBy q (== a)
queueDeleteBy :: (DeletingQueueStrategy sm,
DequeueStrategy so)
=> Queue 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_ :: (DeletingQueueStrategy sm,
DequeueStrategy so)
=> Queue sm so a
-> (a -> Bool)
-> Event ()
queueDeleteBy_ q pred = fmap (const ()) $ queueDeleteBy q pred
queueContains :: (Eq a,
DeletingQueueStrategy sm)
=> Queue sm so a
-> a
-> Event Bool
queueContains q a = fmap isJust $ queueContainsBy q (== a)
queueContainsBy :: DeletingQueueStrategy sm
=> Queue sm so a
-> (a -> Bool)
-> Event (Maybe a)
queueContainsBy q pred =
strategyQueueContainsBy (queueStore q) pred
clearQueue :: DequeueStrategy sm
=> Queue sm so a
-> Event ()
clearQueue q =
do x <- tryDequeue q
case x of
Nothing -> return ()
Just a -> clearQueue q
enqueue :: (EnqueueStrategy sm,
DequeueStrategy so)
=> Queue sm so a
-> a
-> Event ()
enqueue = enqueueStore
enqueueWithStoringPriority :: (PriorityQueueStrategy sm pm,
DequeueStrategy so)
=> Queue sm so a
-> pm
-> a
-> Event ()
enqueueWithStoringPriority = enqueueStoreWithPriority
enqueueStore :: (EnqueueStrategy sm,
DequeueStrategy so)
=> Queue 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 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 sm
=> Queue sm so a
-> Event a
dequeueExtract q =
Event $ \p ->
do a <- invokeEvent p $
strategyDequeue (queueStore q)
invokeEvent p $
dequeuePostExtract q a
dequeuePostExtract :: DequeueStrategy sm
=> Queue 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'
return a