{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}

-- |
-- Module     : Simulation.Aivika.Lattice.QueueStrategy
-- Copyright  : Copyright (c) 2016-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 7.10.3
--
-- This module defines queue strategies 'FCFS' and 'LCFS' for the 'LIO' computation.
--
module Simulation.Aivika.Lattice.QueueStrategy () where

import Control.Monad.Trans

import Simulation.Aivika.Trans
import qualified Simulation.Aivika.Trans.DoubleLinkedList as LL

import Simulation.Aivika.Lattice.Internal.LIO
import Simulation.Aivika.Lattice.Ref.Base

-- | An implementation of the 'FCFS' queue strategy.
instance QueueStrategy LIO FCFS where

  -- | A queue used by the 'FCFS' strategy.
  newtype StrategyQueue LIO FCFS a = FCFSQueueLIO (LL.DoubleLinkedList LIO a)

  newStrategyQueue :: forall a. FCFS -> Simulation LIO (StrategyQueue LIO FCFS a)
newStrategyQueue FCFS
s = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. DoubleLinkedList LIO a -> StrategyQueue LIO FCFS a
FCFSQueueLIO forall (m :: * -> *) a.
MonadRef m =>
Simulation m (DoubleLinkedList m a)
LL.newList

  strategyQueueNull :: forall a. StrategyQueue LIO FCFS a -> Event LIO Bool
strategyQueueNull (FCFSQueueLIO DoubleLinkedList LIO a
q) = forall (m :: * -> *) a.
MonadRef m =>
DoubleLinkedList m a -> Event m Bool
LL.listNull DoubleLinkedList LIO a
q

-- | An implementation of the 'FCFS' queue strategy.
instance DequeueStrategy LIO FCFS where

  strategyDequeue :: forall a. StrategyQueue LIO FCFS a -> Event LIO a
strategyDequeue (FCFSQueueLIO DoubleLinkedList LIO a
q) =
    do a
i <- forall (m :: * -> *) a.
MonadRef m =>
DoubleLinkedList m a -> Event m a
LL.listFirst DoubleLinkedList LIO a
q
       forall (m :: * -> *) a.
MonadRef m =>
DoubleLinkedList m a -> Event m ()
LL.listRemoveFirst DoubleLinkedList LIO a
q
       forall (m :: * -> *) a. Monad m => a -> m a
return a
i

-- | An implementation of the 'FCFS' queue strategy.
instance EnqueueStrategy LIO FCFS where

  strategyEnqueue :: forall a. StrategyQueue LIO FCFS a -> a -> Event LIO ()
strategyEnqueue (FCFSQueueLIO DoubleLinkedList LIO a
q) a
i = forall (m :: * -> *) a.
MonadRef m =>
DoubleLinkedList m a -> a -> Event m ()
LL.listAddLast DoubleLinkedList LIO a
q a
i

-- | An implementation of the 'LCFS' queue strategy.
instance QueueStrategy LIO LCFS where

  -- | A queue used by the 'LCFS' strategy.
  newtype StrategyQueue LIO LCFS a = LCFSQueueLIO (LL.DoubleLinkedList LIO a)

  newStrategyQueue :: forall a. LCFS -> Simulation LIO (StrategyQueue LIO LCFS a)
newStrategyQueue LCFS
s = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. DoubleLinkedList LIO a -> StrategyQueue LIO LCFS a
LCFSQueueLIO forall (m :: * -> *) a.
MonadRef m =>
Simulation m (DoubleLinkedList m a)
LL.newList
       
  strategyQueueNull :: forall a. StrategyQueue LIO LCFS a -> Event LIO Bool
strategyQueueNull (LCFSQueueLIO DoubleLinkedList LIO a
q) = forall (m :: * -> *) a.
MonadRef m =>
DoubleLinkedList m a -> Event m Bool
LL.listNull DoubleLinkedList LIO a
q

-- | An implementation of the 'LCFS' queue strategy.
instance DequeueStrategy LIO LCFS where

  strategyDequeue :: forall a. StrategyQueue LIO LCFS a -> Event LIO a
strategyDequeue (LCFSQueueLIO DoubleLinkedList LIO a
q) =
    do a
i <- forall (m :: * -> *) a.
MonadRef m =>
DoubleLinkedList m a -> Event m a
LL.listFirst DoubleLinkedList LIO a
q
       forall (m :: * -> *) a.
MonadRef m =>
DoubleLinkedList m a -> Event m ()
LL.listRemoveFirst DoubleLinkedList LIO a
q
       forall (m :: * -> *) a. Monad m => a -> m a
return a
i

-- | An implementation of the 'LCFS' queue strategy.
instance EnqueueStrategy LIO LCFS where

  strategyEnqueue :: forall a. StrategyQueue LIO LCFS a -> a -> Event LIO ()
strategyEnqueue (LCFSQueueLIO DoubleLinkedList LIO a
q) a
i = forall (m :: * -> *) a.
MonadRef m =>
DoubleLinkedList m a -> a -> Event m ()
LL.listInsertFirst DoubleLinkedList LIO a
q a
i