module Simulation.Aivika.Distributed.Optimistic.Internal.AcknowledgementMessageQueue
(AcknowledgementMessageQueue,
newAcknowledgementMessageQueue,
acknowledgementMessageQueueSize,
enqueueAcknowledgementMessage,
reduceAcknowledgementMessages,
filterAcknowledgementMessages) where
import Data.Maybe
import Data.List
import Data.IORef
import Control.Monad
import Control.Monad.Trans
import Simulation.Aivika.Vector
import Simulation.Aivika.Trans.Comp
import Simulation.Aivika.Trans.Simulation
import Simulation.Aivika.Trans.Dynamics
import Simulation.Aivika.Trans.Event
import Simulation.Aivika.Trans.Signal
import Simulation.Aivika.Trans.Internal.Types
import Simulation.Aivika.Distributed.Optimistic.Internal.Message
import Simulation.Aivika.Distributed.Optimistic.Internal.DIO
import Simulation.Aivika.Distributed.Optimistic.Internal.IO
import Simulation.Aivika.Distributed.Optimistic.DIO
data AcknowledgementMessageQueue =
AcknowledgementMessageQueue { acknowledgementMessages :: Vector AcknowledgementMessage
}
newAcknowledgementMessageQueue :: DIO AcknowledgementMessageQueue
newAcknowledgementMessageQueue =
do ms <- liftIOUnsafe newVector
return AcknowledgementMessageQueue { acknowledgementMessages = ms }
acknowledgementMessageQueueSize :: AcknowledgementMessageQueue -> IO Int
acknowledgementMessageQueueSize = vectorCount . acknowledgementMessages
complement :: Int -> Int
complement x = - x - 1
enqueueAcknowledgementMessage :: AcknowledgementMessageQueue -> AcknowledgementMessage -> IO ()
enqueueAcknowledgementMessage q m =
do i <- lookupAcknowledgementMessageIndex q m
when (i < 0) $
do
let i' = complement i
vectorInsert (acknowledgementMessages q) i' m
lookupAcknowledgementMessageIndex' :: AcknowledgementMessageQueue -> AcknowledgementMessage -> Int -> Int -> IO Int
lookupAcknowledgementMessageIndex' q m left right =
if left > right
then return $ complement left
else
do let index = (left + right) `div` 2
m' <- readVector (acknowledgementMessages q) index
let t' = acknowledgementReceiveTime m'
t = acknowledgementReceiveTime m
if t' > t || (t' == t && m' > m)
then lookupAcknowledgementMessageIndex' q m left (index - 1)
else if t' < t || (t' == t && m' < m)
then lookupAcknowledgementMessageIndex' q m (index + 1) right
else return index
lookupAcknowledgementMessageIndex :: AcknowledgementMessageQueue -> AcknowledgementMessage -> IO Int
lookupAcknowledgementMessageIndex q m =
do n <- vectorCount (acknowledgementMessages q)
lookupAcknowledgementMessageIndex' q m 0 (n - 1)
reduceAcknowledgementMessages :: AcknowledgementMessageQueue -> Double -> IO ()
reduceAcknowledgementMessages q t =
do count <- vectorCount (acknowledgementMessages q)
len <- loop count 0
when (len > 0) $
vectorDeleteRange (acknowledgementMessages q) 0 len
where
loop n i
| i >= n = return i
| otherwise = do m <- readVector (acknowledgementMessages q) i
if acknowledgementReceiveTime m < t
then loop n (i + 1)
else return i
filterAcknowledgementMessages :: (AcknowledgementMessage -> Bool) -> AcknowledgementMessageQueue -> IO [AcknowledgementMessage]
filterAcknowledgementMessages pred q =
do count <- vectorCount (acknowledgementMessages q)
loop count 0 []
where
loop n i acc
| i >= n = return (reverse acc)
| otherwise = do m <- readVector (acknowledgementMessages q) i
if pred m
then loop n (i + 1) (m : acc)
else loop n (i + 1) acc