packages feed

stm-queue-extras-0.1.0.0: src/Control/Concurrent/STM/ETQueue.hs

{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE UnicodeSyntax #-}

-- |
-- Module: Control.Concurrent.STM.ETQueue
-- Copyright: Copyright © 2014 AlephCloud Systems, Inc.
-- License: MIT
-- Maintainer: Jon Sterling <jsterling@alephcloud.com>
-- Stability: experimental
--
module Control.Concurrent.STM.ETQueue
( ETQueue
, newETQueue
, newETQueueIO
, readETQueue
, tryReadETQueue
, peekETQueue
, tryPeekETQueue
, writeETQueue
, unGetETQueue
, isEmptyETQueue
, awaitEmpty
) where

import Control.Applicative
import Control.Concurrent.STM
import Control.Monad

-- | A variant of 'TQueue' such that you can await its emptiness.
data ETQueue α
  = ETQueue
  { etqQueue ∷ TQueue α
  , etqVar ∷ TMVar ()
  }

newETQueue ∷ STM (ETQueue α)
newETQueue = do
  etqQueue ← newTQueue
  etqVar ← newTMVar ()
  return ETQueue {..}

newETQueueIO ∷ IO (ETQueue α)
newETQueueIO = do
  etqQueue ← newTQueueIO
  etqVar ← newTMVarIO ()
  return ETQueue {..}

readETQueue
  ∷ ETQueue α
  → STM α
readETQueue ETQueue{..} = do
  a ← readTQueue etqQueue
  isEmpty ← isEmptyTQueue etqQueue
  when isEmpty $
    () <$ tryPutTMVar etqVar ()
  return a

tryReadETQueue
  ∷ ETQueue α
  → STM (Maybe α)
tryReadETQueue q =
  (Just <$> readETQueue q)
    `orElse` return Nothing

peekETQueue
  ∷ ETQueue α
  → STM α
peekETQueue ETQueue{..} =
  peekTQueue etqQueue

tryPeekETQueue
  ∷ ETQueue α
  → STM (Maybe α)
tryPeekETQueue ETQueue{..} =
  tryPeekTQueue etqQueue

writeETQueue
  ∷ ETQueue α
  → α
  → STM ()
writeETQueue ETQueue{..} a = do
  writeTQueue etqQueue a
  () <$ tryTakeTMVar etqVar

unGetETQueue
  ∷ ETQueue α
  → α
  → STM ()
unGetETQueue ETQueue{..} a = do
  unGetTQueue etqQueue a
  () <$ tryTakeTMVar etqVar

isEmptyETQueue
  ∷ ETQueue α
  → STM Bool
isEmptyETQueue ETQueue{..} =
  isEmptyTQueue etqQueue

awaitEmpty
  ∷ ETQueue α
  → STM ()
awaitEmpty ETQueue{..} =
  readTMVar etqVar