{-# 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 = 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 = 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 = 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 = 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  <- forall (m :: * -> *) a. MonadRef m => a -> Simulation m (Ref m a)
newRef Int
0
     StrategyQueue m sm a
qm <- forall (m :: * -> *) s a.
QueueStrategy m s =>
s -> Simulation m (StrategyQueue m s a)
newStrategyQueue sm
sm
     Resource m so
ro <- forall (m :: * -> *) s.
(MonadDES m, QueueStrategy m s) =>
s -> Int -> Maybe Int -> Simulation m (Resource m s)
newResourceWithMaxCount so
so Int
0 forall a. Maybe a
Nothing
     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 =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
n <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q)
     forall (m :: * -> *) a. Monad m => a -> m a
return (Int
n 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 =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p -> forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (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 forall (m :: * -> *) s.
(MonadDES m, EnqueueStrategy m s) =>
Resource m s -> Process m ()
requestResource (forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q)
     forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
EventLift t m =>
Event m a -> t m a
liftEvent forall a b. (a -> b) -> a -> b
$ 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 forall (m :: * -> *) s p.
(MonadDES m, PriorityQueueStrategy m s p) =>
Resource m s -> p -> Process m ()
requestResourceWithPriority (forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q) po
po
     forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
EventLift t m =>
Event m a -> t m a
liftEvent forall a b. (a -> b) -> a -> b
$ 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 <- forall (m :: * -> *) s. MonadDES m => Resource m s -> Event m Bool
tryRequestResourceWithinEvent (forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q)
     if Bool
x 
       then forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ 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 forall (m :: * -> *) a. Monad m => a -> m a
return 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 = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Maybe a -> Bool
isJust forall a b. (a -> b) -> a -> b
$ 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 (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 = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. a -> b -> a
const ()) forall a b. (a -> b) -> a -> b
$ 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 (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 <- forall (m :: * -> *) s. MonadDES m => Resource m s -> Event m Bool
tryRequestResourceWithinEvent (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 <- forall (m :: * -> *) s a.
DeletingQueueStrategy m s =>
StrategyQueue m s a -> (a -> Bool) -> Event m (Maybe a)
strategyQueueDeleteBy (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 forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResourceWithinEvent (forall (m :: * -> *) sm so a. Queue m sm so a -> Resource m so
dequeueRes Queue m sm so a
q)
                      forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
                 Just a
i ->
                   forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ 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 forall (m :: * -> *) a. Monad m => a -> m a
return 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 = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. a -> b -> a
const ()) forall a b. (a -> b) -> a -> b
$ 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 = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Maybe a -> Bool
isJust forall a b. (a -> b) -> a -> b
$ 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 (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 =
  forall (m :: * -> *) s a.
DeletingQueueStrategy m s =>
StrategyQueue m s a -> (a -> Bool) -> Event m (Maybe a)
strategyQueueContainsBy (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 <- 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 -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
       Just a
a  -> 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 = 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 = 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 =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) s a.
EnqueueStrategy m s =>
StrategyQueue m s a -> a -> Event m ()
strategyEnqueue (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 <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
          forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (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 forall a. Num a => a -> a -> a
+ Int
1
     Int
c' seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q) Int
c'
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResourceWithinEvent (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 =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) s p a.
PriorityQueueStrategy m s p =>
StrategyQueue m s a -> p -> a -> Event m ()
strategyEnqueueWithPriority (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 <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
          forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (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 forall a. Num a => a -> a -> a
+ Int
1
     Int
c' seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q) Int
c'
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) s.
(MonadDES m, DequeueStrategy m s) =>
Resource m s -> Event m ()
releaseResourceWithinEvent (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 =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do a
a <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
          forall (m :: * -> *) s a.
DequeueStrategy m s =>
StrategyQueue m s a -> Event m a
strategyDequeue (forall (m :: * -> *) sm so a.
Queue m sm so a -> StrategyQueue m sm a
queueStore Queue m sm so a
q)
     forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       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 =
  forall (m :: * -> *) a. (Point m -> m a) -> Event m a
Event forall a b. (a -> b) -> a -> b
$ \Point m
p ->
  do Int
c <- forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
          forall (m :: * -> *) a. MonadRef m => Ref m a -> Event m a
readRef (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 forall a. Num a => a -> a -> a
- Int
1
     Int
c' seq :: forall a b. a -> b -> b
`seq` forall (m :: * -> *) a. Point m -> Event m a -> m a
invokeEvent Point m
p forall a b. (a -> b) -> a -> b
$
       forall (m :: * -> *) a. MonadRef m => Ref m a -> a -> Event m ()
writeRef (forall (m :: * -> *) sm so a. Queue m sm so a -> Ref m Int
queueCountRef Queue m sm so a
q) Int
c'
     forall (m :: * -> *) a. Monad m => a -> m a
return a
a