postgresql-replicant-0.1.0.1: src/Database/PostgreSQL/Replicant/Queue.hs
{-|
Module : Database.PostgreSQL.Replicant.Queue
Description : Bounded and unbounded FIFO queues
Copyright : (c) James King, 2020, 2021
License : BSD3
Maintainer : james@agentultra.com
Stability : experimental
Portability : POSIX
Shared FIFO queues
-}
module Database.PostgreSQL.Replicant.Queue where
import Control.Concurrent.MVar
import Data.Sequence (Seq, ViewR (..), (<|), (|>))
import qualified Data.Sequence as S
data BoundedFifoQueueMeta a
= BoundedFifoQueueMeta
{ boundedFifoQueueSize :: Int
, boundedFifoQueue :: Seq a
}
deriving (Eq, Show)
newtype BoundedFifoQueue a = BoundedFifoQueue (MVar (BoundedFifoQueueMeta a))
newtype BoundedQueueException a
= BoundedQueueOverflow a
deriving (Eq, Show)
emptyBounded :: Int -> IO (BoundedFifoQueue a)
emptyBounded size =
BoundedFifoQueue <$> newMVar (BoundedFifoQueueMeta size S.empty)
enqueueBounded :: BoundedFifoQueue a -> a -> IO (Either (BoundedQueueException a) ())
enqueueBounded (BoundedFifoQueue mQueue) x = do
b@(BoundedFifoQueueMeta size queue) <- takeMVar mQueue
if size == S.length queue
then pure $ Left $ BoundedQueueOverflow x
else do
putMVar mQueue $ b { boundedFifoQueue = x <| queue }
pure $ Right ()
newtype FifoQueue a = FifoQueue (MVar (Seq a))
empty :: IO (FifoQueue a)
empty = FifoQueue <$> newMVar S.empty
-- | Return @True@ if the queue is empty
null :: FifoQueue a -> IO Bool
null (FifoQueue mQueue) = do
queue <- readMVar mQueue
pure $ S.null queue
-- | Remove an item from the end of the non-empty queue.
dequeue :: FifoQueue a -> IO (Maybe a)
dequeue (FifoQueue mQueue) = do
queue <- takeMVar mQueue
case S.viewr queue of
S.EmptyR -> do
putMVar mQueue queue
pure Nothing
rest :> x -> do
putMVar mQueue rest
pure $ Just x
-- | Put an item on the front of the queue.
enqueue :: FifoQueue a -> a -> IO ()
enqueue (FifoQueue mQueue) x = do
queue <- takeMVar mQueue
putMVar mQueue $ x <| queue
-- | Put an item on the end of the queue so that it will be dequeued first.
enqueueRight :: FifoQueue a -> a -> IO ()
enqueueRight (FifoQueue mQueue) x = do
queue <- takeMVar mQueue
putMVar mQueue $ queue |> x