module Simulation.Aivika.Trans.GPSS.TransactQueueStrategy
(TransactQueueStrategy(..),
transactStrategyQueueDeleteBy,
transactStrategyQueueContainsBy) where
import Control.Monad
import Control.Monad.Trans
import Data.IORef
import qualified Data.IntMap as M
import Simulation.Aivika.Trans
import qualified Simulation.Aivika.Trans.DoubleLinkedList as DLL
data TransactQueueStrategy s = TransactQueueStrategy s
instance MonadDES m => QueueStrategy m (TransactQueueStrategy s) where
data StrategyQueue m (TransactQueueStrategy s) a =
TransactStrategyQueue { transactStrategy :: TransactQueueStrategy s,
transactStrategyQueue :: Ref m (M.IntMap (DLL.DoubleLinkedList m a))
}
newStrategyQueue s =
do r <- newRef M.empty
return $ TransactStrategyQueue s r
strategyQueueNull q =
do m <- readRef (transactStrategyQueue q)
return $ M.null m
instance MonadDES m => DequeueStrategy m (TransactQueueStrategy FCFS) where
strategyDequeue q =
do m <- readRef (transactStrategyQueue q)
let (k, xs) = M.findMin m
i <- DLL.listFirst xs
DLL.listRemoveFirst xs
empty <- DLL.listNull xs
when empty $
modifyRef (transactStrategyQueue q) $
M.delete k
return i
instance MonadDES m => DequeueStrategy m (TransactQueueStrategy LCFS) where
strategyDequeue q =
do m <- readRef (transactStrategyQueue q)
let (k, xs) = M.findMin m
i <- DLL.listLast xs
DLL.listRemoveLast xs
empty <- DLL.listNull xs
when empty $
modifyRef (transactStrategyQueue q) $
M.delete k
return i
instance (MonadDES m, DequeueStrategy m (TransactQueueStrategy s)) => PriorityQueueStrategy m (TransactQueueStrategy s) Int where
strategyEnqueueWithPriority q priority i =
do m <- readRef (transactStrategyQueue q)
let k = priority
xs = M.lookup k m
case xs of
Nothing ->
do xs <- liftSimulation DLL.newList
DLL.listAddLast xs i
modifyRef (transactStrategyQueue q) $
M.insert k xs
Just xs ->
DLL.listAddLast xs i
instance MonadDES m => DeletingQueueStrategy m (TransactQueueStrategy FCFS) where
strategyQueueDeleteBy q pred =
do m <- readRef (transactStrategyQueue q)
let loop [] = return Nothing
loop ((k, xs): tail) =
do a <- DLL.listRemoveBy xs pred
case a of
Nothing -> loop tail
Just _ ->
do empty <- DLL.listNull xs
when empty $
modifyRef (transactStrategyQueue q) $
M.delete k
return a
loop (M.assocs m)
strategyQueueContainsBy q pred =
do m <- readRef (transactStrategyQueue q)
let loop [] = return Nothing
loop ((k, xs): tail) =
do a <- DLL.listContainsBy xs pred
case a of
Nothing -> loop tail
Just _ -> return a
loop (M.assocs m)
transactStrategyQueueDeleteBy :: MonadDES m
=> StrategyQueue m (TransactQueueStrategy s) a
-> Int
-> (a -> Bool)
-> Event m (Maybe a)
transactStrategyQueueDeleteBy q priority pred =
do m <- readRef (transactStrategyQueue q)
let k = priority
xs = M.lookup k m
case xs of
Nothing -> return Nothing
Just xs ->
do a <- DLL.listRemoveBy xs pred
empty <- DLL.listNull xs
when empty $
modifyRef (transactStrategyQueue q) $
M.delete k
return a
transactStrategyQueueContainsBy :: MonadDES m
=> StrategyQueue m (TransactQueueStrategy s) a
-> Int
-> (a -> Bool)
-> Event m (Maybe a)
transactStrategyQueueContainsBy q priority pred =
do m <- readRef (transactStrategyQueue q)
let k = priority
xs = M.lookup k m
case xs of
Nothing -> return Nothing
Just xs -> DLL.listContainsBy xs pred