{-# LANGUAGE FlexibleContexts #-}

-- |
-- Module     : Simulation.Aivika.Trans.Queue.Infinite.Base
-- Copyright  : Copyright (c) 2009-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 8.0.1
--
-- This module defines an infinite optimised queue, which has no counters nor signals.
--
module Simulation.Aivika.Trans.Queue.Infinite.Base
       (-- * Queue Types
        FCFSQueue,
        LCFSQueue,
        SIROQueue,
        PriorityQueue,
        Queue,
        -- * Creating Queue
        newFCFSQueue,
        newLCFSQueue,
        newSIROQueue,
        newPriorityQueue,
        newQueue,
        -- * Queue Properties and Activities
        enqueueStoringStrategy,
        dequeueStrategy,
        queueNull,
        queueCount,
        -- * Dequeuing and Enqueuing
        dequeue,
        dequeueWithOutputPriority,
        tryDequeue,
        enqueue,
        enqueueWithStoringPriority,
        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

-- | A type synonym for the ordinary FIFO queue also known as the FCFS
-- (First Come - First Serviced) queue.
type FCFSQueue m a = Queue m FCFS FCFS a

-- | A type synonym for the ordinary LIFO queue also known as the LCFS
-- (Last Come - First Serviced) queue.
type LCFSQueue m a = Queue m LCFS FCFS a

-- | A type synonym for the SIRO (Serviced in Random Order) queue.
type SIROQueue m a = Queue m SIRO FCFS a

-- | A type synonym for the queue with static priorities applied when
-- storing the elements in the queue.
type PriorityQueue m a = Queue m StaticPriorities FCFS a

-- | Represents an infinite queue using the specified strategies for
-- internal storing (in memory), @sm@, and dequeueing (output), @so@, where @a@ denotes
-- the type of items stored in the queue. Type @m@ denotes the underlying monad within
-- which the simulation executes.
data Queue m sm so a =
  Queue { forall (m :: * -> *) sm so a. Queue m sm so a -> sm
enqueueStoringStrategy :: sm,
          -- ^ The strategy applied when storing (in memory) items in the queue.
          forall (m :: * -> *) sm so a. Queue m sm so a -> so
dequeueStrategy :: so,
          -- ^ The strategy applied to the dequeueing (output) processes.
          forall (m :: * -> *) sm so a.
Queue m sm so a -> StrategyQueue m sm a
queueStore :: StrategyQueue m sm a,
          forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes :: Resource m so,
          forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef :: Ref m Int }
  
-- | Create a new infinite FCFS queue.  
newFCFSQueue :: MonadDES m => Simulation m (FCFSQueue m a)
{-# INLINABLE newFCFSQueue #-}
newFCFSQueue :: forall (m :: * -> *) a. MonadDES m => Simulation m (FCFSQueue m a)
newFCFSQueue = FCFS -> FCFS -> Simulation m (Queue m FCFS FCFS a)
forall (m :: * -> *) sm so a.
(MonadDES m, QueueStrategy m sm, QueueStrategy m so) =>
sm -> so -> Simulation m (Queue m sm so a)
newQueue FCFS
FCFS FCFS
FCFS
  
-- | Create a new infinite LCFS queue.  
newLCFSQueue :: MonadDES m => Simulation m (LCFSQueue m a)
{-# INLINABLE newLCFSQueue #-}
newLCFSQueue :: forall (m :: * -> *) a. MonadDES m => Simulation m (LCFSQueue m a)
newLCFSQueue = LCFS -> FCFS -> Simulation m (Queue m LCFS FCFS a)
forall (m :: * -> *) sm so a.
(MonadDES m, QueueStrategy m sm, QueueStrategy m so) =>
sm -> so -> Simulation m (Queue m sm so a)
newQueue LCFS
LCFS FCFS
FCFS
  
-- | Create a new infinite SIRO queue.  
newSIROQueue :: (MonadDES m, QueueStrategy m SIRO) => Simulation m (SIROQueue m a)
{-# INLINABLE newSIROQueue #-}
newSIROQueue :: forall (m :: * -> *) a.
(MonadDES m, QueueStrategy m SIRO) =>
Simulation m (SIROQueue m a)
newSIROQueue = SIRO -> FCFS -> Simulation m (Queue m SIRO FCFS a)
forall (m :: * -> *) sm so a.
(MonadDES m, QueueStrategy m sm, QueueStrategy m so) =>
sm -> so -> Simulation m (Queue m sm so a)
newQueue SIRO
SIRO FCFS
FCFS
  
-- | Create a new infinite priority queue.  
newPriorityQueue :: (MonadDES m, QueueStrategy m StaticPriorities) => Simulation m (PriorityQueue m a)
{-# INLINABLE newPriorityQueue #-}
newPriorityQueue :: forall (m :: * -> *) a.
(MonadDES m, QueueStrategy m StaticPriorities) =>
Simulation m (PriorityQueue m a)
newPriorityQueue = StaticPriorities
-> FCFS -> Simulation m (Queue m StaticPriorities FCFS a)
forall (m :: * -> *) sm so a.
(MonadDES m, QueueStrategy m sm, QueueStrategy m so) =>
sm -> so -> Simulation m (Queue m sm so a)
newQueue StaticPriorities
StaticPriorities FCFS
FCFS
  
-- | Create a new infinite queue with the specified strategies.  
newQueue :: (MonadDES m,
             QueueStrategy m sm,
             QueueStrategy m so) =>
            sm
            -- ^ the strategy applied when storing items in the queue
            -> so
            -- ^ the strategy applied to the dequeueing (output) processes when the queue is empty
            -> Simulation m (Queue m sm so a)
{-# INLINABLE newQueue #-}
newQueue :: forall (m :: * -> *) sm so a.
(MonadDES m, QueueStrategy m sm, QueueStrategy m so) =>
sm -> so -> Simulation m (Queue m sm so a)
newQueue sm
sm so
so =
  do Ref m Int
i  <- Int -> Simulation m (Ref m Int)
forall a. a -> Simulation m (Ref m a)
forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef Int
0
     StrategyQueue m sm a
qm <- sm -> Simulation m (StrategyQueue m sm a)
forall a. sm -> Simulation m (StrategyQueue m sm a)
forall (m :: * -> *) s a.
QueueStrategy m s =>
s -> Simulation m (StrategyQueue m s a)
newStrategyQueue sm
sm
     Resource m so
ro <- so -> Int -> Maybe Int -> Simulation m (Resource m so)
forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Maybe Int -> Simulation m (Resource m s)
newResourceWithMaxCount so
so Int
0 Maybe Int
forall a. Maybe a
Nothing
     Queue m sm so a -> Simulation m (Queue m sm so a)
forall a. a -> Simulation m a
forall (m :: * -> *) a. Monad m => a -> m a
return Queue { enqueueStoringStrategy :: sm
enqueueStoringStrategy = sm
sm,
                    dequeueStrategy :: so
dequeueStrategy = so
so,
                    queueStore :: StrategyQueue m sm a
queueStore = StrategyQueue m sm a
qm,
                    dequeueRes :: Resource m so
dequeueRes = Resource m so
ro,
                    queueCountRef :: Ref m Int
queueCountRef = Ref m Int
i }

-- | Test whether the queue is empty.
--
-- See also 'queueNullChanged' and 'queueNullChanged_'.
queueNull :: MonadDES m => Queue m sm so a -> Event m Bool
{-# INLINABLE queueNull #-}
queueNull :: forall (m :: * -> *) sm so a.
MonadDES m =>
Queue m sm so a -> Event m Bool
queueNull Queue m sm so a
q =
  (Point m -> m Bool) -> Event m Bool
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m Bool) -> Event m Bool)
-> (Point m -> m Bool) -> Event m Bool
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
n <- Point m -> Event m Int -> m Int
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m Int -> m Int) -> Event m Int -> m Int
forall a b. (a -> b) -> a -> b
$ Ref m Int -> Event m Int
forall a. Ref m a -> Event m a
forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (Queue m sm so a -> Ref m Int
forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q)
     Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0)
  
-- | Return the current queue size.
--
-- See also 'queueCountStats', 'queueCountChanged' and 'queueCountChanged_'.
queueCount :: MonadDES m => Queue m sm so a -> Event m Int
{-# INLINABLE queueCount #-}
queueCount :: forall (m :: * -> *) sm so a.
MonadDES m =>
Queue m sm so a -> Event m Int
queueCount Queue m sm so a
q =
  (Point m -> m Int) -> Event m Int
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m Int) -> Event m Int)
-> (Point m -> m Int) -> Event m Int
forall a b. (a -> b) -> a -> b
$ \Point m
p -> Point m -> Event m Int -> m Int
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m Int -> m Int) -> Event m Int -> m Int
forall a b. (a -> b) -> a -> b
$ Ref m Int -> Event m Int
forall a. Ref m a -> Event m a
forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (Queue m sm so a -> Ref m Int
forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q)

-- | Dequeue suspending the process if the queue is empty.
dequeue :: (MonadDES m,
            DequeueStrategy m sm,
            EnqueueStrategy m so)
           => Queue m sm so a
           -- ^ the queue
           -> Process m a
           -- ^ the dequeued value
{-# INLINABLE dequeue #-}
dequeue :: forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm, EnqueueStrategy m so) =>
Queue m sm so a -> Process m a
dequeue Queue m sm so a
q =
  do Resource m so -> Process m ()
forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Process m ()
requestResource (Queue m sm so a -> Resource m so
forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q)
     Event m a -> Process m a
forall a. Event m a -> Process m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
EventLift t m =>
Event m a -> t m a
liftEvent (Event m a -> Process m a) -> Event m a -> Process m a
forall a b. (a -> b) -> a -> b
$ Queue m sm so a -> Event m a
forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> Event m a
dequeueExtract Queue m sm so a
q
  
-- | Dequeue with the output priority suspending the process if the queue is empty.
dequeueWithOutputPriority :: (MonadDES m,
                              DequeueStrategy m sm,
                              PriorityQueueStrategy m so po)
                             => Queue m sm so a
                             -- ^ the queue
                             -> po
                             -- ^ the priority for output
                             -> Process m a
                             -- ^ the dequeued value
{-# INLINABLE dequeueWithOutputPriority #-}
dequeueWithOutputPriority :: forall (m :: * -> *) sm so po a.
(MonadDES m, DequeueStrategy m sm,
 PriorityQueueStrategy m so po) =>
Queue m sm so a -> po -> Process m a
dequeueWithOutputPriority Queue m sm so a
q po
po =
  do Resource m so -> po -> Process m ()
forall (m :: * -> *) s p.
(MonadDES m, PriorityQueueStrategy m s p) =>
Resource m s -> p -> Process m ()
requestResourceWithPriority (Queue m sm so a -> Resource m so
forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q) po
po
     Event m a -> Process m a
forall a. Event m a -> Process m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
EventLift t m =>
Event m a -> t m a
liftEvent (Event m a -> Process m a) -> Event m a -> Process m a
forall a b. (a -> b) -> a -> b
$ Queue m sm so a -> Event m a
forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> Event m a
dequeueExtract Queue m sm so a
q
  
-- | Try to dequeue immediately.
tryDequeue :: (MonadDES m,
               DequeueStrategy m sm)
              => Queue m sm so a
              -- ^ the queue
              -> Event m (Maybe a)
              -- ^ the dequeued value of 'Nothing'
{-# INLINABLE tryDequeue #-}
tryDequeue :: forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> Event m (Maybe a)
tryDequeue Queue m sm so a
q =
  do Bool
x <- Resource m so -> Event m Bool
forall (m :: * -> *) s. MonadDES m => Resource m s -> Event m Bool
tryRequestResourceWithinEvent (Queue m sm so a -> Resource m so
forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q)
     if Bool
x 
       then (a -> Maybe a) -> Event m a -> Event m (Maybe a)
forall a b. (a -> b) -> Event m a -> Event m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Maybe a
forall a. a -> Maybe a
Just (Event m a -> Event m (Maybe a)) -> Event m a -> Event m (Maybe a)
forall a b. (a -> b) -> a -> b
$ Queue m sm so a -> Event m a
forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> Event m a
dequeueExtract Queue m sm so a
q
       else Maybe a -> Event m (Maybe a)
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing

-- | Remove the item from the queue and return a flag indicating
-- whether the item was found and actually removed.
queueDelete :: (MonadDES m,
                Eq a,
                DeletingQueueStrategy m sm,
                DequeueStrategy m so)
               => Queue m sm so a
               -- ^ the queue
               -> a
               -- ^ the item to remove from the queue
               -> Event m Bool
               -- ^ whether the item was found and removed
{-# INLINABLE queueDelete #-}
queueDelete :: forall (m :: * -> *) a sm so.
(MonadDES m, Eq a, DeletingQueueStrategy m sm,
 DequeueStrategy m so) =>
Queue m sm so a -> a -> Event m Bool
queueDelete Queue m sm so a
q a
a = (Maybe a -> Bool) -> Event m (Maybe a) -> Event m Bool
forall a b. (a -> b) -> Event m a -> Event m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe a -> Bool
forall a. Maybe a -> Bool
isJust (Event m (Maybe a) -> Event m Bool)
-> Event m (Maybe a) -> Event m Bool
forall a b. (a -> b) -> a -> b
$ Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
forall (m :: * -> *) sm so a.
(MonadDES m, DeletingQueueStrategy m sm, DequeueStrategy m so) =>
Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
queueDeleteBy Queue m sm so a
q (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a)

-- | Remove the specified item from the queue.
queueDelete_ :: (MonadDES m,
                 Eq a,
                 DeletingQueueStrategy m sm,
                 DequeueStrategy m so)
                => Queue m sm so a
                -- ^ the queue
                -> a
                -- ^ the item to remove from the queue
                -> Event m ()
{-# INLINABLE queueDelete_ #-}
queueDelete_ :: forall (m :: * -> *) a sm so.
(MonadDES m, Eq a, DeletingQueueStrategy m sm,
 DequeueStrategy m so) =>
Queue m sm so a -> a -> Event m ()
queueDelete_ Queue m sm so a
q a
a = (Maybe a -> ()) -> Event m (Maybe a) -> Event m ()
forall a b. (a -> b) -> Event m a -> Event m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (() -> Maybe a -> ()
forall a b. a -> b -> a
const ()) (Event m (Maybe a) -> Event m ())
-> Event m (Maybe a) -> Event m ()
forall a b. (a -> b) -> a -> b
$ Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
forall (m :: * -> *) sm so a.
(MonadDES m, DeletingQueueStrategy m sm, DequeueStrategy m so) =>
Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
queueDeleteBy Queue m sm so a
q (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a)

-- | Remove an item satisfying the specified predicate and return the item if found.
queueDeleteBy :: (MonadDES m,
                  DeletingQueueStrategy m sm,
                  DequeueStrategy m so)
                 => Queue m sm so a
                 -- ^ the queue
                 -> (a -> Bool)
                 -- ^ the predicate
                 -> Event m (Maybe a)
{-# INLINABLE queueDeleteBy #-}
queueDeleteBy :: forall (m :: * -> *) sm so a.
(MonadDES m, DeletingQueueStrategy m sm, DequeueStrategy m so) =>
Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
queueDeleteBy Queue m sm so a
q a -> Bool
pred =
  do Bool
x <- Resource m so -> Event m Bool
forall (m :: * -> *) s. MonadDES m => Resource m s -> Event m Bool
tryRequestResourceWithinEvent (Queue m sm so a -> Resource m so
forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q)
     if Bool
x
       then do Maybe a
i <- StrategyQueue m sm a -> (a -> Bool) -> Event m (Maybe a)
forall a. StrategyQueue m sm a -> (a -> Bool) -> Event m (Maybe a)
forall (m :: * -> *) s a.
DeletingQueueStrategy m s =>
StrategyQueue m s a -> (a -> Bool) -> Event m (Maybe a)
strategyQueueDeleteBy (Queue m sm so a -> StrategyQueue m sm a
forall (m :: * -> *) sm so a.
Queue m sm so a -> StrategyQueue m sm a
queueStore Queue m sm so a
q) a -> Bool
pred
               case Maybe a
i of
                 Maybe a
Nothing ->
                   do Resource m so -> Event m ()
forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResourceWithinEvent (Queue m sm so a -> Resource m so
forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q)
                      Maybe a -> Event m (Maybe a)
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
                 Just a
i ->
                   (a -> Maybe a) -> Event m a -> Event m (Maybe a)
forall a b. (a -> b) -> Event m a -> Event m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Maybe a
forall a. a -> Maybe a
Just (Event m a -> Event m (Maybe a)) -> Event m a -> Event m (Maybe a)
forall a b. (a -> b) -> a -> b
$ Queue m sm so a -> a -> Event m a
forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> a -> Event m a
dequeuePostExtract Queue m sm so a
q a
i
       else Maybe a -> Event m (Maybe a)
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
               
-- | Remove an item satisfying the specified predicate.
queueDeleteBy_ :: (MonadDES m,
                   DeletingQueueStrategy m sm,
                   DequeueStrategy m so)
                  => Queue m sm so a
                  -- ^ the queue
                  -> (a -> Bool)
                  -- ^ the predicate
                  -> Event m ()
{-# INLINABLE queueDeleteBy_ #-}
queueDeleteBy_ :: forall (m :: * -> *) sm so a.
(MonadDES m, DeletingQueueStrategy m sm, DequeueStrategy m so) =>
Queue m sm so a -> (a -> Bool) -> Event m ()
queueDeleteBy_ Queue m sm so a
q a -> Bool
pred = (Maybe a -> ()) -> Event m (Maybe a) -> Event m ()
forall a b. (a -> b) -> Event m a -> Event m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (() -> Maybe a -> ()
forall a b. a -> b -> a
const ()) (Event m (Maybe a) -> Event m ())
-> Event m (Maybe a) -> Event m ()
forall a b. (a -> b) -> a -> b
$ Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
forall (m :: * -> *) sm so a.
(MonadDES m, DeletingQueueStrategy m sm, DequeueStrategy m so) =>
Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
queueDeleteBy Queue m sm so a
q a -> Bool
pred

-- | Detect whether the item is contained in the queue.
queueContains :: (MonadDES m,
                  Eq a,
                  DeletingQueueStrategy m sm)
                 => Queue m sm so a
                 -- ^ the queue
                 -> a
                 -- ^ the item to search the queue for
                 -> Event m Bool
                 -- ^ whether the item was found
{-# INLINABLE queueContains #-}
queueContains :: forall (m :: * -> *) a sm so.
(MonadDES m, Eq a, DeletingQueueStrategy m sm) =>
Queue m sm so a -> a -> Event m Bool
queueContains Queue m sm so a
q a
a = (Maybe a -> Bool) -> Event m (Maybe a) -> Event m Bool
forall a b. (a -> b) -> Event m a -> Event m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe a -> Bool
forall a. Maybe a -> Bool
isJust (Event m (Maybe a) -> Event m Bool)
-> Event m (Maybe a) -> Event m Bool
forall a b. (a -> b) -> a -> b
$ Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
forall (m :: * -> *) sm so a.
(MonadDES m, DeletingQueueStrategy m sm) =>
Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
queueContainsBy Queue m sm so a
q (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a)

-- | Detect whether an item satisfying the specified predicate is contained in the queue.
queueContainsBy :: (MonadDES m,
                    DeletingQueueStrategy m sm)
                   => Queue m sm so a
                   -- ^ the queue
                   -> (a -> Bool)
                   -- ^ the predicate
                   -> Event m (Maybe a)
                   -- ^ the item if it was found
{-# INLINABLE queueContainsBy #-}
queueContainsBy :: forall (m :: * -> *) sm so a.
(MonadDES m, DeletingQueueStrategy m sm) =>
Queue m sm so a -> (a -> Bool) -> Event m (Maybe a)
queueContainsBy Queue m sm so a
q a -> Bool
pred =
  StrategyQueue m sm a -> (a -> Bool) -> Event m (Maybe a)
forall a. StrategyQueue m sm a -> (a -> Bool) -> Event m (Maybe a)
forall (m :: * -> *) s a.
DeletingQueueStrategy m s =>
StrategyQueue m s a -> (a -> Bool) -> Event m (Maybe a)
strategyQueueContainsBy (Queue m sm so a -> StrategyQueue m sm a
forall (m :: * -> *) sm so a.
Queue m sm so a -> StrategyQueue m sm a
queueStore Queue m sm so a
q) a -> Bool
pred

-- | Clear the queue immediately.
clearQueue :: (MonadDES m,
               DequeueStrategy m sm)
              => Queue m sm so a
              -- ^ the queue
              -> Event m ()
{-# INLINABLE clearQueue #-}
clearQueue :: forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> Event m ()
clearQueue Queue m sm so a
q =
  do Maybe a
x <- Queue m sm so a -> Event m (Maybe a)
forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> Event m (Maybe a)
tryDequeue Queue m sm so a
q
     case Maybe a
x of
       Maybe a
Nothing -> () -> Event m ()
forall a. a -> Event m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
       Just a
a  -> Queue m sm so a -> Event m ()
forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> Event m ()
clearQueue Queue m sm so a
q

-- | Enqueue the item.  
enqueue :: (MonadDES m,
            EnqueueStrategy m sm,
            DequeueStrategy m so)
           => Queue m sm so a
           -- ^ the queue
           -> a
           -- ^ the item to enqueue
           -> Event m ()
{-# INLINABLE enqueue #-}
enqueue :: forall (m :: * -> *) sm so a.
(MonadDES m, EnqueueStrategy m sm, DequeueStrategy m so) =>
Queue m sm so a -> a -> Event m ()
enqueue = Queue m sm so a -> a -> Event m ()
forall (m :: * -> *) sm so a.
(MonadDES m, EnqueueStrategy m sm, DequeueStrategy m so) =>
Queue m sm so a -> a -> Event m ()
enqueueStore
     
-- | Enqueue with the storing priority the item.  
enqueueWithStoringPriority :: (MonadDES m,
                               PriorityQueueStrategy m sm pm,
                               DequeueStrategy m so)
                              => Queue m sm so a
                              -- ^ the queue
                              -> pm
                              -- ^ the priority for storing
                              -> a
                              -- ^ the item to enqueue
                              -> Event m ()
{-# INLINABLE enqueueWithStoringPriority #-}
enqueueWithStoringPriority :: forall (m :: * -> *) sm pm so a.
(MonadDES m, PriorityQueueStrategy m sm pm,
 DequeueStrategy m so) =>
Queue m sm so a -> pm -> a -> Event m ()
enqueueWithStoringPriority = Queue m sm so a -> pm -> a -> Event m ()
forall (m :: * -> *) sm pm so a.
(MonadDES m, PriorityQueueStrategy m sm pm,
 DequeueStrategy m so) =>
Queue m sm so a -> pm -> a -> Event m ()
enqueueStoreWithPriority

-- | Store the item.
enqueueStore :: (MonadDES m,
                 EnqueueStrategy m sm,
                 DequeueStrategy m so)
                => Queue m sm so a
                -- ^ the queue
                -> a
                -- ^ the item to be stored
                -> Event m ()
{-# INLINE enqueueStore #-}
enqueueStore :: forall (m :: * -> *) sm so a.
(MonadDES m, EnqueueStrategy m sm, DequeueStrategy m so) =>
Queue m sm so a -> a -> Event m ()
enqueueStore Queue m sm so a
q a
a =
  (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$
       StrategyQueue m sm a -> a -> Event m ()
forall a. StrategyQueue m sm a -> a -> Event m ()
forall (m :: * -> *) s a.
EnqueueStrategy m s =>
StrategyQueue m s a -> a -> Event m ()
strategyEnqueue (Queue m sm so a -> StrategyQueue m sm a
forall (m :: * -> *) sm so a.
Queue m sm so a -> StrategyQueue m sm a
queueStore Queue m sm so a
q) a
a
     Int
c <- Point m -> Event m Int -> m Int
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m Int -> m Int) -> Event m Int -> m Int
forall a b. (a -> b) -> a -> b
$
          Ref m Int -> Event m Int
forall a. Ref m a -> Event m a
forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (Queue m sm so a -> Ref m Int
forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q)
     let c' :: Int
c' = Int
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
     Int
c' Int -> m () -> m ()
forall a b. a -> b -> b
`seq` Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$
       Ref m Int -> Int -> Event m ()
forall a. Ref m a -> a -> Event m ()
forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (Queue m sm so a -> Ref m Int
forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q) Int
c'
     Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$
       Resource m so -> Event m ()
forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResourceWithinEvent (Queue m sm so a -> Resource m so
forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q)

-- | Store with the priority the item.
enqueueStoreWithPriority :: (MonadDES m,
                             PriorityQueueStrategy m sm pm,
                             DequeueStrategy m so)
                            => Queue m sm so a
                            -- ^ the queue
                            -> pm
                            -- ^ the priority for storing
                            -> a
                            -- ^ the item to be enqueued
                            -> Event m ()
{-# INLINE enqueueStoreWithPriority #-}
enqueueStoreWithPriority :: forall (m :: * -> *) sm pm so a.
(MonadDES m, PriorityQueueStrategy m sm pm,
 DequeueStrategy m so) =>
Queue m sm so a -> pm -> a -> Event m ()
enqueueStoreWithPriority Queue m sm so a
q pm
pm a
a =
  (Point m -> m ()) -> Event m ()
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m ()) -> Event m ())
-> (Point m -> m ()) -> Event m ()
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$
       StrategyQueue m sm a -> pm -> a -> Event m ()
forall a. StrategyQueue m sm a -> pm -> a -> Event m ()
forall (m :: * -> *) s p a.
PriorityQueueStrategy m s p =>
StrategyQueue m s a -> p -> a -> Event m ()
strategyEnqueueWithPriority (Queue m sm so a -> StrategyQueue m sm a
forall (m :: * -> *) sm so a.
Queue m sm so a -> StrategyQueue m sm a
queueStore Queue m sm so a
q) pm
pm a
a
     Int
c <- Point m -> Event m Int -> m Int
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m Int -> m Int) -> Event m Int -> m Int
forall a b. (a -> b) -> a -> b
$
          Ref m Int -> Event m Int
forall a. Ref m a -> Event m a
forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (Queue m sm so a -> Ref m Int
forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q)
     let c' :: Int
c' = Int
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
     Int
c' Int -> m () -> m ()
forall a b. a -> b -> b
`seq` Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$
       Ref m Int -> Int -> Event m ()
forall a. Ref m a -> a -> Event m ()
forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (Queue m sm so a -> Ref m Int
forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q) Int
c'
     Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$
       Resource m so -> Event m ()
forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResourceWithinEvent (Queue m sm so a -> Resource m so
forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q)

-- | Extract an item for the dequeuing request.  
dequeueExtract :: (MonadDES m,
                   DequeueStrategy m sm)
                  => Queue m sm so a
                  -- ^ the queue
                  -> Event m a
                  -- ^ the dequeued value
{-# INLINE dequeueExtract #-}
dequeueExtract :: forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> Event m a
dequeueExtract Queue m sm so a
q =
  (Point m -> m a) -> Event m a
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m a) -> Event m a) -> (Point m -> m a) -> Event m a
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do a
a <- Point m -> Event m a -> m a
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m a -> m a) -> Event m a -> m a
forall a b. (a -> b) -> a -> b
$
          StrategyQueue m sm a -> Event m a
forall a. StrategyQueue m sm a -> Event m a
forall (m :: * -> *) s a.
DequeueStrategy m s =>
StrategyQueue m s a -> Event m a
strategyDequeue (Queue m sm so a -> StrategyQueue m sm a
forall (m :: * -> *) sm so a.
Queue m sm so a -> StrategyQueue m sm a
queueStore Queue m sm so a
q)
     Point m -> Event m a -> m a
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m a -> m a) -> Event m a -> m a
forall a b. (a -> b) -> a -> b
$
       Queue m sm so a -> a -> Event m a
forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> a -> Event m a
dequeuePostExtract Queue m sm so a
q a
a

-- | A post action after extracting the item by the dequeuing request.  
dequeuePostExtract :: (MonadDES m,
                       DequeueStrategy m sm)
                      => Queue m sm so a
                      -- ^ the queue
                      -> a
                      -- ^ the item to dequeue
                      -> Event m a
                      -- ^ the dequeued value
{-# INLINE dequeuePostExtract #-}
dequeuePostExtract :: forall (m :: * -> *) sm so a.
(MonadDES m, DequeueStrategy m sm) =>
Queue m sm so a -> a -> Event m a
dequeuePostExtract Queue m sm so a
q a
a =
  (Point m -> m a) -> Event m a
forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event ((Point m -> m a) -> Event m a) -> (Point m -> m a) -> Event m a
forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
c <- Point m -> Event m Int -> m Int
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m Int -> m Int) -> Event m Int -> m Int
forall a b. (a -> b) -> a -> b
$
          Ref m Int -> Event m Int
forall a. Ref m a -> Event m a
forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (Queue m sm so a -> Ref m Int
forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q)
     let c' :: Int
c' = Int
c Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
     Int
c' Int -> m () -> m ()
forall a b. a -> b -> b
`seq` Point m -> Event m () -> m ()
forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p (Event m () -> m ()) -> Event m () -> m ()
forall a b. (a -> b) -> a -> b
$
       Ref m Int -> Int -> Event m ()
forall a. Ref m a -> a -> Event m ()
forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (Queue m sm so a -> Ref m Int
forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q) Int
c'
     a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a