-- |-- Module : Simulation.Aivika.Dynamics.FIFO-- Copyright : Copyright (c) 2009-2012, David Sorokin <david.sorokin@gmail.com>-- License : BSD3-- Maintainer : David Sorokin <david.sorokin@gmail.com>-- Stability : experimental-- Tested with: GHC 7.4.1---- This module defines the FIFO queue.--moduleSimulation.Aivika.Dynamics.FIFO(FIFO,fifoQueue,fifoNull,fifoFull,fifoMaxCount,fifoCount,fifoLostCount,newFIFO,dequeueFIFO,tryDequeueFIFO,enqueueFIFO,tryEnqueueFIFO,enqueueFIFOOrLost)whereimportData.IORefimportData.ArrayimportData.Array.IOimportControl.MonadimportControl.Monad.TransimportSimulation.Aivika.DynamicsimportSimulation.Aivika.Dynamics.SimulationimportSimulation.Aivika.Dynamics.EventQueueimportSimulation.Aivika.Dynamics.ProcessimportSimulation.Aivika.Dynamics.Resource-- | Represents the FIFO queue with rule: first input - first output.dataFIFOa=FIFO{fifoQueue::EventQueue,-- ^ Return the event queue.fifoMaxCount::Int,-- ^ The maximum available number of items.fifoReadRes::Resource,fifoWriteRes::Resource,fifoCountRef::IORefInt,fifoLostCountRef::IORefInt,fifoStartRef::IORefInt,fifoEndRef::IORefInt,fifoArray::IOArrayInta}-- | Create a new FIFO queue with the specified maximum available number of items. newFIFO::EventQueue->Int->Simulation(FIFOa)newFIFOqcount=doi<-liftIO$newIORef0l<-liftIO$newIORef0s<-liftIO$newIORef0e<-liftIO$newIORef0a<-liftIO$newArray_(0,count-1)r<-newResourceWithCountqcount0w<-newResourceWithCountqcountcountreturnFIFO{fifoQueue=q,fifoMaxCount=count,fifoReadRes=r,fifoWriteRes=w,fifoCountRef=i,fifoLostCountRef=l,fifoStartRef=s,fifoEndRef=e,fifoArray=a}-- | Test whether the FIFO queue is empty.fifoNull::FIFOa->DynamicsBoolfifoNullfifo=doa<-fifoCountfiforeturn(a==0)-- | Test whether the FIFO queue is full.fifoFull::FIFOa->DynamicsBoolfifoFullfifo=doa<-fifoCountfiforeturn(a==fifoMaxCountfifo)-- | Return the queue size.fifoCount::FIFOa->DynamicsIntfifoCountfifo=liftIO$readIORef(fifoCountReffifo)-- | Return the number of lost items.fifoLostCount::FIFOa->DynamicsIntfifoLostCountfifo=liftIO$readIORef(fifoLostCountReffifo)-- | Dequeue from the FIFO queue suspending the process if-- the queue is empty.dequeueFIFO::FIFOa->ProcessadequeueFIFOfifo=dorequestResource(fifoReadResfifo)a<-liftIO$dequeueImplfiforeleaseResource(fifoWriteResfifo)returna-- | Try to dequeue from the FIFO queue immediately. tryDequeueFIFO::FIFOa->Dynamics(Maybea)tryDequeueFIFOfifo=dox<-tryRequestResourceInDynamics(fifoReadResfifo)ifxthendoa<-liftIO$dequeueImplfiforeleaseResourceInDynamics(fifoWriteResfifo)return$JustaelsereturnNothing-- | Enqueue the item in the FIFO queue suspending the process-- if the queue is full. enqueueFIFO::FIFOa->a->Process()enqueueFIFOfifoa=dorequestResource(fifoWriteResfifo)liftIO$enqueueImplfifoareleaseResource(fifoReadResfifo)-- | Try to enqueue the item in the FIFO queue. Return 'False' in-- the monad if the queue is full.tryEnqueueFIFO::FIFOa->a->DynamicsBooltryEnqueueFIFOfifoa=dox<-tryRequestResourceInDynamics(fifoWriteResfifo)ifxthendoliftIO$enqueueImplfifoareleaseResourceInDynamics(fifoReadResfifo)returnTrueelsereturnFalse-- | Try to enqueue the item in the FIFO queue. If the queue is full-- then the item will be lost.enqueueFIFOOrLost::FIFOa->a->Dynamics()enqueueFIFOOrLostfifoa=dox<-tryRequestResourceInDynamics(fifoWriteResfifo)ifxthendoliftIO$enqueueImplfifoareleaseResourceInDynamics(fifoReadResfifo)elseliftIO$modifyIORef(fifoLostCountReffifo)$(+)1-- | An implementation method.dequeueImpl::FIFOa->IOadequeueImplfifo=doi<-readIORef(fifoCountReffifo)s<-readIORef(fifoStartReffifo)leti'=i-1s'=(s+1)`mod`fifoMaxCountfifoa<-readArray(fifoArrayfifo)swriteArray(fifoArrayfifo)sundefinedi'`seq`writeIORef(fifoCountReffifo)i's'`seq`writeIORef(fifoStartReffifo)s'returna-- | An implementation method.enqueueImpl::FIFOa->a->IO()enqueueImplfifoa=doi<-readIORef(fifoCountReffifo)e<-readIORef(fifoEndReffifo)leti'=i+1e'=(e+1)`mod`fifoMaxCountfifoa`seq`writeArray(fifoArrayfifo)eai'`seq`writeIORef(fifoCountReffifo)i'e'`seq`writeIORef(fifoEndReffifo)e'