module Simulation.Aivika.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
import qualified Simulation.Aivika.DoubleLinkedList as DLL
data TransactQueueStrategy s = TransactQueueStrategy s
instance QueueStrategy (TransactQueueStrategy s) where
data StrategyQueue (TransactQueueStrategy s) a =
TransactStrategyQueue { transactStrategy :: TransactQueueStrategy s,
transactStrategyQueue :: IORef (M.IntMap (DLL.DoubleLinkedList a))
}
newStrategyQueue s =
liftIO $
do r <- newIORef M.empty
return $ TransactStrategyQueue s r
strategyQueueNull q =
liftIO $
do m <- readIORef (transactStrategyQueue q)
return $ M.null m
instance DequeueStrategy (TransactQueueStrategy FCFS) where
strategyDequeue q =
liftIO $
do m <- readIORef (transactStrategyQueue q)
let (k, xs) = M.findMin m
i <- DLL.listFirst xs
DLL.listRemoveFirst xs
empty <- DLL.listNull xs
when empty $
modifyIORef (transactStrategyQueue q) $
M.delete k
return i
instance DequeueStrategy (TransactQueueStrategy LCFS) where
strategyDequeue q =
liftIO $
do m <- readIORef (transactStrategyQueue q)
let (k, xs) = M.findMin m
i <- DLL.listLast xs
DLL.listRemoveLast xs
empty <- DLL.listNull xs
when empty $
modifyIORef (transactStrategyQueue q) $
M.delete k
return i
instance DequeueStrategy (TransactQueueStrategy s) => PriorityQueueStrategy (TransactQueueStrategy s) Int where
strategyEnqueueWithPriority q priority i =
liftIO $
do m <- readIORef (transactStrategyQueue q)
let k = priority
xs = M.lookup k m
case xs of
Nothing ->
do xs <- DLL.newList
DLL.listAddLast xs i
modifyIORef (transactStrategyQueue q) $
M.insert k xs
Just xs ->
DLL.listAddLast xs i
instance DeletingQueueStrategy (TransactQueueStrategy FCFS) where
strategyQueueDeleteBy q pred =
liftIO $
do m <- readIORef (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 $
modifyIORef (transactStrategyQueue q) $
M.delete k
return a
loop (M.assocs m)
strategyQueueContainsBy q pred =
liftIO $
do m <- readIORef (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 :: StrategyQueue (TransactQueueStrategy s) a
-> Int
-> (a -> Bool)
-> Event (Maybe a)
transactStrategyQueueDeleteBy q priority pred =
liftIO $
do m <- readIORef (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 $
modifyIORef (transactStrategyQueue q) $
M.delete k
return a
transactStrategyQueueContainsBy :: StrategyQueue (TransactQueueStrategy s) a
-> Int
-> (a -> Bool)
-> Event (Maybe a)
transactStrategyQueueContainsBy q priority pred =
liftIO $
do m <- readIORef (transactStrategyQueue q)
let k = priority
xs = M.lookup k m
case xs of
Nothing -> return Nothing
Just xs -> DLL.listContainsBy xs pred