2016-06-06 00:25:46 +03:00
|
|
|
-- |
|
|
|
|
-- Module : Control.Concurrent.Classy.QSem
|
|
|
|
-- Copyright : (c) 2016 Michael Walker
|
|
|
|
-- License : MIT
|
|
|
|
-- Maintainer : Michael Walker <mike@barrucadu.co.uk>
|
|
|
|
-- Stability : stable
|
|
|
|
-- Portability : portable
|
|
|
|
--
|
|
|
|
-- Simple quantity semaphores.
|
2016-03-26 05:57:40 +03:00
|
|
|
module Control.Concurrent.Classy.QSem
|
|
|
|
( -- * Simple Quantity Semaphores
|
|
|
|
QSem
|
|
|
|
, newQSem
|
|
|
|
, waitQSem
|
|
|
|
, signalQSem
|
|
|
|
) where
|
|
|
|
|
2017-04-08 07:20:39 +03:00
|
|
|
import Control.Concurrent.Classy.QSemN
|
|
|
|
import Control.Monad.Conc.Class (MonadConc)
|
2016-03-26 05:57:40 +03:00
|
|
|
|
|
|
|
-- | @QSem@ is a quantity semaphore in which the resource is acquired
|
|
|
|
-- and released in units of one. It provides guaranteed FIFO ordering
|
|
|
|
-- for satisfying blocked 'waitQSem' calls.
|
|
|
|
--
|
|
|
|
-- The pattern
|
|
|
|
--
|
|
|
|
-- > bracket_ qaitQSem signalSSem (...)
|
|
|
|
--
|
|
|
|
-- is safe; it never loses a unit of the resource.
|
2017-04-05 23:25:02 +03:00
|
|
|
--
|
|
|
|
-- @since 1.0.0.0
|
2016-03-26 05:57:40 +03:00
|
|
|
newtype QSem m = QSem (QSemN m)
|
|
|
|
|
|
|
|
-- | Build a new 'QSem' with a supplied initial quantity. The initial
|
|
|
|
-- quantity must be at least 0.
|
2017-04-05 23:25:02 +03:00
|
|
|
--
|
|
|
|
-- @since 1.0.0.0
|
2016-03-26 05:57:40 +03:00
|
|
|
newQSem :: MonadConc m => Int -> m (QSem m)
|
|
|
|
newQSem initial
|
|
|
|
| initial < 0 = fail "newQSem: Initial quantity mus tbe non-negative."
|
|
|
|
| otherwise = QSem <$> newQSemN initial
|
|
|
|
|
|
|
|
-- | Wait for a unit to become available.
|
2017-04-05 23:25:02 +03:00
|
|
|
--
|
|
|
|
-- @since 1.0.0.0
|
2016-03-26 05:57:40 +03:00
|
|
|
waitQSem :: MonadConc m => QSem m -> m ()
|
|
|
|
waitQSem (QSem qSemN) = waitQSemN qSemN 1
|
|
|
|
|
|
|
|
-- | Signal that a unit of the 'QSem' is available.
|
2017-04-05 23:25:02 +03:00
|
|
|
--
|
|
|
|
-- @since 1.0.0.0
|
2016-03-26 05:57:40 +03:00
|
|
|
signalQSem :: MonadConc m => QSem m -> m ()
|
|
|
|
signalQSem (QSem qSemN) = signalQSemN qSemN 1
|