yet-another-logger-0.3.1: src/System/Logger/Internal/Queue.hs
-- Copyright (c) 2016-2018 Lars Kuhtz <lakuhtz@gmail.com>
-- Copyright (c) 2014-2015 PivotCloud, Inc.
--
-- System.Logger
--
-- Please feel free to contact us at licensing@pivotmail.com with any
-- contributions, additions, or other feedback; we would love to hear from
-- you.
--
-- Licensed under the Apache License, Version 2.0 (the "License"); you may
-- not use this file except in compliance with the License. You may obtain a
-- copy of the License at http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- License for the specific language governing permissions and limitations
-- under the License.
-- |
-- Module: System.Logger.Internal.Queue
-- Description: Queues for Usage with Yet Another Logger
-- Copyright:
-- Copyright © 2016-2018 Lars Kuhtz <lakuhtz@gmail.com>
-- Copyright © 2015 PivotCloud, Inc.
-- License: Apache-2.0
-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>
-- Stability: experimental
--
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax #-}
module System.Logger.Internal.Queue
( BoundedCloseableQueue(..)
, FairTBMQueue
, TBMQueue
, TBMChan
) where
import Control.Concurrent
import Control.Concurrent.STM
import Control.Concurrent.STM.TBMChan
import Control.Concurrent.STM.TBMQueue
import Control.Monad.Unicode
import Numeric.Natural
import Prelude.Unicode
-- -------------------------------------------------------------------------- --
-- Queue Abstraction
class BoundedCloseableQueue q a | q → a where
newQueue ∷ Natural → IO q
closeQueue ∷ q → IO ()
-- | Returns 'False' if and only if the queue
-- is closed. If the queue is full this function blocks.
--
writeQueue ∷ q → a → IO Bool
-- | Non-blocking version of 'writeQueue'. Returns 'Nothing' if the
-- queue was full. Otherwise it returns 'Just True' if the value
-- was successfully written and 'Just False' if the queue was closed.
--
tryWriteQueue ∷ q → a → IO (Maybe Bool)
-- | Returns 'Nothing' if and only if the queue is
-- closed. If this queue is empty this function blocks.
--
readQueue ∷ q → IO (Maybe a)
{-
-- | Non-blocking version of 'readQueue'. Returns 'Nothing' if the
-- queue is empty. Returns 'Just Nothing' if the queue is closed
-- and and 'Just (Just a)' otherwise.
--
tryReadQueue ∷ q → IO (Maybe (Maybe a))
-}
-- -------------------------------------------------------------------------- --
-- TBMQueue
instance BoundedCloseableQueue (TBMQueue a) a where
newQueue = newTBMQueueIO ∘ fromIntegral
closeQueue = atomically ∘ closeTBMQueue
writeQueue q a = atomically $ isClosedTBMQueue q ≫= \case
True → return False
False → do
writeTBMQueue q a
return True
tryWriteQueue q a = atomically $ tryWriteTBMQueue q a ≫= \case
Nothing → return $ Just False
Just False → return Nothing
Just True → return $ Just True
readQueue q = atomically $ readTBMQueue q
-- -------------------------------------------------------------------------- --
-- TBMChan
instance BoundedCloseableQueue (TBMChan a) a where
newQueue = newTBMChanIO ∘ fromIntegral
closeQueue = atomically ∘ closeTBMChan
writeQueue q a = atomically $ isClosedTBMChan q ≫= \case
True → return False
False → do
writeTBMChan q a
return True
tryWriteQueue q a = atomically $ tryWriteTBMChan q a ≫= \case
Nothing → return $ Just False
Just False → return Nothing
Just True → return $ Just True
readQueue q = atomically $ readTBMChan q
-- -------------------------------------------------------------------------- --
-- FairTBMQueue
data FairTBMQueue α = FairTBMQueue
{ fairTBMQueueQueue ∷ !(TBMQueue α)
, fairTBMQueueLock ∷ !(MVar ())
}
instance BoundedCloseableQueue (FairTBMQueue a) a where
newQueue i = FairTBMQueue <$> newTBMQueueIO (fromIntegral i) <*> newMVar ()
closeQueue = closeQueue ∘ fairTBMQueueQueue
readQueue = readQueue ∘ fairTBMQueueQueue
writeQueue FairTBMQueue{..} a = do
withMVar fairTBMQueueLock $ \_ → do
writeQueue fairTBMQueueQueue a
tryWriteQueue FairTBMQueue{..} a = do
withMVar fairTBMQueueLock $ \_ → do
tryWriteQueue fairTBMQueueQueue a