-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/

-- | Much safer replacement for QSemN, QSem, and SampleVar
--   
--   This provides a much safer semaphore than the QSem, QSemN, SampleVar
--   in base. Those base modules are not exception safe and can be broken
--   by killThread. See
--   https://github.com/ChrisKuklewicz/SafeSemaphore for more
--   details.
@package SafeSemaphore
@version 0.10.1

-- | Provides a fair RWLock, similar to one from Java, which is itself
--   documented at
--   http://download.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html
--   
--   There are complicated policy choices that have to be made. The policy
--   choices here are different from the ones for the RWLock in
--   concurrent-extras.
--   
--   The FairRWLock may be in a free unlocked state, it may be in
--   a read locked state, or it may be a write locked state. Many running
--   threads may hold the read lock and execute concurrently. Only one
--   running thread may hold the write lock. The scheduling is a fair FIFO
--   queue that avoids starvation.
--   
--   When in the read lock state the first acquireWrite will block,
--   and subsequent acquireRead and acquireWrite will queue
--   in order. When in the write locked state all other threads trying to
--   acquireWrite or acquireRead will queue in order.
--   
--   FairRWLock allows recursive write locks, and it allows
--   recursive read locks, and it allows the write lock holding thread to
--   acquire read locks. When the current writer also holds read locks and
--   then releases its last write lock it will immediately convert to the
--   read locked state (and other waiting readers may join it). When a
--   reader acquires a write lock it will (1) release all its read locks,
--   (2) wait to acquire the write lock, (3) retake the same number of read
--   locks released in (1).
--   
--   The preferred way to use this API is sticking to new,
--   withRead, and withWrite.
--   
--   No sequence of calling acquire on a single RWLock should lead to
--   deadlock. Exceptions, espcially from killThread, do not break
--   withRead or withWrite. The withRead and
--   withWrite ensure all locks get released when exiting due to an
--   exception.
--   
--   The readers and writers are always identified by their
--   ThreadId. Each thread that calls acquireRead must later
--   call releaseRead from the same thread. Each thread that calls
--   acquireWrite must later call releaseWrite from the same
--   thread. The main way to misuse a FairRWLock is to call a release
--   without having called an acquire. This is reported in the (Left error)
--   outcomes from releaseRead and releaseWrite. Only if the
--   FairRWLock has a bug and finds itself in an impossible state
--   then it will throw an error.
module Control.Concurrent.FairRWLock

-- | Opaque type of the fair RWLock.
data RWLock

-- | Exception type thrown or returned by this module. "Impossible"
--   conditions get the error thrown and usage problems get the error
--   returned.
data RWLockException
RWLockException :: ThreadId -> RWLockExceptionKind -> String -> RWLockException

-- | Operation in which error arose,
data RWLockExceptionKind
RWLock'acquireWrite :: RWLockExceptionKind
RWLock'releaseWrite :: RWLockExceptionKind
RWLock'acquireRead :: RWLockExceptionKind
RWLock'releaseRead :: RWLockExceptionKind

-- | Observable state of holder(s) of lock(s). The W returns a pair of Ints
--   where the first is number of read locks (at least 0) and the second is
--   the number of write locks held (at least 1). The R returns a map from
--   thread id to the number of read locks held (at least 1).
data FRW
F :: FRW
R :: TMap -> FRW
W :: (ThreadId, (Int, Int)) -> FRW
data LockKind
ReaderKind :: TSet -> LockKind
[unRK] :: LockKind -> TSet
WriterKind :: ThreadId -> LockKind
[unWK] :: LockKind -> ThreadId
type TMap = Map ThreadId Int
type TSet = Set ThreadId

-- | Create a new RWLock which starts in a free and unlocked state.
new :: IO RWLock

-- | This is by far the preferred way to acquire a read lock. This uses
--   bracket_ to ensure acquireRead and releaseRead are called correctly
--   around the passed command.
--   
--   This ought to ensure releaseRead will not return a (Left error), but
--   if it does then this error will be thrown.
--   
--   This can block and be safely interrupted.
withRead :: RWLock -> IO a -> IO a

-- | This is by far the preferred way to acquire a write lock. This uses
--   bracket_ to ensure acquireWrite and releaseWrite are called correctly
--   around the passed command.
--   
--   This ought to ensure releaseWrite will not return a (Left error), but
--   if it does then this error will be thrown.
--   
--   This can block and be safely interrupted.
withWrite :: RWLock -> IO a -> IO a

-- | Any thread may call acquireRead (even ones holding write locks). This
--   read lock may be acquired multiple times, requiring an identical
--   number of releaseRead calls.
--   
--   All previous calls to acquireWrite by other threads will have
--   succeeded and been released (or interrupted) before this acquireRead
--   will return.
--   
--   The best way to use acquireRead is to use withRead instead to ensure
--   releaseRead will be called exactly once.
--   
--   This may block and be safely interrupted. If interrupted then the
--   RWLock will be left unchanged.
acquireRead :: RWLock -> IO ()

-- | Any thread may call acquireWrite (even ones holding read locks, but
--   see below for interrupted behavior). This write lock may be acquired
--   multiple times, requiring an identical number of releaseWrite calls.
--   
--   All previous calls to acquireRead by other threads will have succeeded
--   and been released (or interrupted) before this acquireWrite will
--   return.
--   
--   The best way to use acquireWrite is to use withWrite instead to ensure
--   releaseWrite will be called exactly once.
--   
--   This may block and usually be safely interrupted. If interrupted then
--   the RWLock will be left unchanged. The exception to being able to
--   interrupted when this blocks is very subtle: if this thread holds read
--   locks and calls acquireWrite then it will release those read locks and
--   go to the back of the queue to acquire the write lock (it does not get
--   to skip the queue). While blocking waiting for the write lock to be
--   available this thread may be interrupted. If not interrupted then the
--   write lock will eventually be acquired, followed by re-acquiring the
--   original number of read locks. But if acquireWrite is interrupted
--   after releasing read locks then it MUST restore those read locks on
--   the way out. To do this the internal error handler will use
--   uninterruptibleMask_ and a special version of acquireRead that
--   skips to the front of the queue; when the current lock state is a
--   reader this works instantly but when the current lock state is a
--   writer this thread will block in an UNINTERRUPTIBLE state until the
--   current writer is finished. Once this other writer is finished the
--   error handler will obtain the read locks it needs to allow the error
--   propagation to continue.
acquireWrite :: RWLock -> IO ()

-- | A thread that calls acquireRead must later call releaseRead once for
--   each call to acquireRead.
--   
--   If this thread has not previous called acquireRead then releaseRead
--   will do nothing and return a (Left error).
--   
--   This can block but cannot be interrupted.
releaseRead :: RWLock -> IO (Either RWLockException ())

-- | A thread that calls acquireWrite must later call releaseWrite once for
--   each call to acquireWrite.
--   
--   If this thread has not previous called acquireWrite then releaseWrite
--   will do nothing and return a (Left error).
--   
--   This can block but cannot be interrupted.
releaseWrite :: RWLock -> IO (Either RWLockException ())

-- | Observe which threads are holding the lock and which threads are
--   waiting (in order). This is particularly useful for writing tests.
peekLock :: RWLock -> IO (FRW, [LockKind])

-- | checkLocks return a pair of numbers, the first is the count of read
--   locks this thread holds, the second is the number of write locks that
--   this thread holds. This may be useful for sanity checking complex
--   usage of RWLocks.
--   
--   This may block and be safely interrupted.
checkLock :: RWLock -> IO (Int, Int)
instance GHC.Classes.Eq Control.Concurrent.FairRWLock.LockKind
instance GHC.Classes.Eq Control.Concurrent.FairRWLock.LockUser
instance GHC.Internal.Exception.Type.Exception Control.Concurrent.FairRWLock.RWLockException
instance GHC.Classes.Ord Control.Concurrent.FairRWLock.LockKind
instance GHC.Internal.Show.Show Control.Concurrent.FairRWLock.FRW
instance GHC.Internal.Show.Show Control.Concurrent.FairRWLock.LockKind
instance GHC.Internal.Show.Show Control.Concurrent.FairRWLock.RWLockException
instance GHC.Internal.Show.Show Control.Concurrent.FairRWLock.RWLockExceptionKind

-- | MSampleVar is a safer version of the
--   Control.Concurrent.SampleVar in base. The same problem as
--   QSem(N) is being fixed, that of handling waiters that die before being
--   woken normally. For Control.Concurrent.SampleVar in base this
--   error can lead to thinking a full SampleVar is really empty
--   and cause writeSampleVar to hang. The MSampleVar in
--   this module is immune to this error, and has a simpler implementation.
module Control.Concurrent.MSampleVar

-- | Sample variables are slightly different from a normal MVar:
--   
--   
--   
- Reading an empty MSampleVar causes the reader to block.
--   (same as takeMVar on empty MVar)
--   
- Reading a filled MSampleVar empties it and returns value.
--   (same as takeMVar)
--   
- Try reading a filled MSampleVar returns a Maybe value.
--   (same as tryTakeMVar)
--   
- Writing to an empty MSampleVar fills it with a value, and
--   potentially, wakes up a blocked reader (same as for putMVar on
--   empty MVar).
--   
- Writing to a filled MSampleVar overwrites the current
--   value. (different from putMVar on full MVar.)
--   
--   
--   The readers queue in FIFO order, with the lead reader joining the
--   writers in a second FIFO queue to access the stored value. Thus
--   writers can jump the queue of non-leading waiting readers to update
--   the value, but the lead reader has to wait on all previous writes to
--   finish before taking the value.
--   
--   This design choice emphasises that each reader sees the most
--   up-to-date value possible while still guaranteeing progress.
data MSampleVar a

-- | newEmptySV allocates a new MSampleVar in an empty state. No
--   futher allocation is done when using the MSampleVar.
newEmptySV :: IO (MSampleVar a)

-- | newSV allocates a new MSampleVar containing the passed value.
--   The value is not evalated or forced, but stored lazily. No futher
--   allocation is done when using the MSampleVar.
newSV :: a -> IO (MSampleVar a)

-- | If the MSampleVar is full, forget the value and leave it empty.
--   Otherwise, do nothing. This avoids any the FIFO queue of blocked
--   readSV threads.
--   
--   emptySV can block and be interrupted, in which case it does
--   nothing. If emptySV returns then it left the MSampleVar
--   in an empty state.
emptySV :: MSampleVar a -> IO ()

-- | Wait for a value to become available, then take it and return. The
--   queue of blocked readSV threads is a fair FIFO queue.
--   
--   readSV can block and be interrupted, in which case it takes
--   nothing. If 'readSV returns normally then it has taken a value.
readSV :: MSampleVar a -> IO a

-- | Write a value into the MSampleVar, overwriting any previous
--   value that was there.
--   
--   writeSV can block and be interrupted, in which case it does
--   nothing.
writeSV :: MSampleVar a -> a -> IO ()

-- | isEmptySV can block and be interrupted, in which case it does
--   nothing. If isEmptySV returns then it reports the momentary
--   status the MSampleVar. Using this value without producing
--   unwanted race conditions is left up to the programmer.
isEmptySV :: MSampleVar a -> IO Bool
instance GHC.Classes.Eq (Control.Concurrent.MSampleVar.MSampleVar a)

-- | This is a literate haskell version of Control.Concurrent.MSem for
--   increased clarity.
--   
--   A semaphore in which operations may wait for or signal
--   single units of value. This modules is intended to improve on
--   Control.Concurrent.QSem.
--   
--   This semaphore gracefully handles threads which die while blocked
--   waiting. The fairness guarantee is that blocked threads are servied in
--   a FIFO order.
--   
--   If with is used to guard a critical section then no quantity of
--   the semaphore will be lost if the activity throws an exception or if
--   this thread is killed by the rest of the program.
--   
--   new can initialize the semaphore to negative, zero, or positive
--   quantity. wait always leaves the MSem with non-negative
--   quantity. signal alawys adds one to the quantity.
--   
--   The functions below are generic in (Integral i) with specialization to
--   Int, Word, and Integer.
--   
--   Overflow warning: These operations do not check for overflow errors.
--   If the Integral type is too small to accept the new total then the
--   behavior of signal is undefined. Using (MSem Integer) prevents
--   the possibility of an overflow error. [ A version of signal
--   that checks the upper bound could be added, but how would it report
--   failure and how would you use this sanely? ]
module Control.Concurrent.MSem

-- | A MSem is a semaphore in which the available quantity can be
--   added and removed in single units, and which can start with positive,
--   zero, or negative value.
data MSem i

-- | new allows positive, zero, and negative initial values. The
--   initial value is forced here to better localize errors.
--   
--   The only way to achieve a negative value with MSem is to start
--   negative with new. Once a negative quantity becomes
--   non-negative by use of signal it will never later be negative.
new :: Integral i => i -> IO (MSem i)

-- | with takes a unit of value from the semaphore to hold while
--   performing the provided operation. with ensures the quantity of
--   the sempahore cannot be lost if there are exceptions or if killThread
--   is used.
--   
--   with uses bracket_ to ensure wait and
--   signal get called correctly.
with :: Integral i => MSem i -> IO a -> IO a

-- | wait will take one unit of value from the sempahore, but will
--   block if the quantity available is not positive.
--   
--   If wait returns normally (not interrupted) then it left the
--   MSem with a remaining quantity that was greater than or equal
--   to zero. If wait is interrupted then no quantity is lost. If
--   wait returns without interruption then it is known that each
--   earlier waiter has definitely either been interrupted or has retured
--   without interruption (the FIFO guarantee).
wait :: Integral i => MSem i -> IO ()

-- | signal adds one unit to the sempahore. Overflow is not checked.
--   
--   signal may block, but it cannot be interrupted, which allows it
--   to dependably restore value to the MSem. All signal,
--   peekAvail, and the head waiter may momentarily block in a fair
--   FIFO manner.
signal :: Integral i => MSem i -> IO ()

-- | peekAvail skips the queue of any blocked wait threads,
--   but may momentarily block on signal, other peekAvail,
--   and the head waiter. This returns the amount of value available to be
--   taken. Using this value without producing unwanted race conditions is
--   left up to the programmer.
--   
--   Note that Control.Concurrent.MSemN offers a more powerful API
--   for making decisions based on the available amount.
peekAvail :: Integral i => MSem i -> IO i
instance GHC.Classes.Eq (Control.Concurrent.MSem.MSem i)

-- | Quantity semaphores in which each thread may wait for an arbitrary
--   amount. This modules is intended to improve on
--   Control.Concurrent.QSemN.
--   
--   This semaphore gracefully handles threads which die while blocked
--   waiting for quantity. The fairness guarantee is that blocked threads
--   are FIFO. An early thread waiting for a large quantity will prevent a
--   later thread waiting for a small quantity from jumping the queue.
--   
--   If with is used to guard a critical section then no quantity of
--   the semaphore will be lost if the activity throws an exception.
--   
--   The functions below are generic in (Integral i) with specialization to
--   Int and Integer.
--   
--   Overflow warning: These operations do not check for overflow errors.
--   If the Integral type is too small to accept the new total then the
--   behavior of these operations is undefined. Using (MSem Integer)
--   prevents the possibility of an overflow error.
module Control.Concurrent.MSemN

-- | A MSemN is a quantity semaphore, in which the available
--   quantity may be signalled or waited for in arbitrary amounts.
data MSemN i

-- | new allows positive, zero, and negative initial values. The
--   initial value is forced here to better localize errors.
new :: Integral i => i -> IO (MSemN i)

-- | with takes a quantity of the semaphore to take and hold while
--   performing the provided operation. with ensures the quantity of
--   the sempahore cannot be lost if there are exceptions. This uses
--   bracket to ensure wait and signal get called
--   correctly.
with :: Integral i => MSemN i -> i -> IO a -> IO a

-- | wait allow positive, zero, and negative wanted values. Waiters
--   may block, and will be handled fairly in FIFO order. Waiters will
--   succeed when the wanted value is less than or equal to the available
--   value. The FIFO order means that a wait for a large quantity
--   that blocks will prevent later requests from being considered even if
--   the later requests would be for a small quantity that could be
--   fulfilled.
--   
--   If wait returns without interruption then it left the
--   MSemN with a remaining quantity that was greater than or equal
--   to zero. If wait is interrupted then no quantity is lost. If
--   wait returns without interruption then it is known that each
--   earlier waiter has definitely either been interrupted or has retured
--   without interruption.
wait :: Integral i => MSemN i -> i -> IO ()

-- | signal allows positive, zero, and negative values, thus this is
--   also way to remove quantity that skips any threads in the
--   wait/waitF queue. If the new total is greater than the
--   next value being waited for (if present) then the first waiter is
--   woken. If there are queued waiters then the next one will wake after a
--   waiter has proceeded and notice the remaining value; thus a single
--   signal may result in several waiters obtaining values. Waking
--   waiting threads is asynchronous.
--   
--   signal may block, but it cannot be interrupted, which allows it
--   to dependably restore value to the MSemN. All signal,
--   signalF, peekAvail, and the head waiter may momentarily
--   block in a fair FIFO manner.
signal :: Integral i => MSemN i -> i -> IO ()

-- | withF takes a pure function and an operation. The pure function
--   converts the available quantity to a pair of the wanted quantity and a
--   returned value. The operation takes the result of the pure function.
--   withF ensures the quantity of the sempahore cannot be lost if
--   there are exceptions. This uses bracket to ensure waitF
--   and signal get called correctly.
--   
--   Note: A long running pure function will block all other access to the
--   MSemN while it is evaluated.
withF :: Integral i => MSemN i -> (i -> (i, b)) -> ((i, b) -> IO a) -> IO a

-- | waitWith takes the MSemN and a pure function that
--   takes the available quantity and computes the amount wanted and a
--   second value. The value wanted is stricly evaluated but the second
--   value is returned lazily.
--   
--   waitF allow positive, zero, and negative wanted values. Waiters
--   may block, and will be handled fairly in FIFO order. Waiters will
--   succeed when the wanted value is less than or equal to the available
--   value. The FIFO order means that a waitF for a large quantity
--   that blocks will prevent later requests from being considered even if
--   the later requests would be for a small quantity that could be
--   fulfilled.
--   
--   If waitF returns without interruption then it left the
--   MSemN with a remaining quantity that was greater than or equal
--   to zero. If waitF or the provided function are interrupted then
--   no quantity is lost. If waitF returns without interruption then
--   it is known that each previous waiter has each definitely either been
--   interrupted or has retured without interruption.
--   
--   Note: A long running pure function will block all other access to the
--   MSemN while it is evaluated.
waitF :: Integral i => MSemN i -> (i -> (i, b)) -> IO (i, b)

-- | Instead of providing a fixed change to the available quantity,
--   signalF applies a provided pure function to the available
--   quantity to compute the change and a second value. The requested
--   change is stricly evaluated but the second value is returned lazily.
--   If the new total is greater than the next value being waited for then
--   the first waiter is woken. If there are queued waiters then the next
--   one will wake after a waiter has proceeded and notice the remaining
--   value; thus a single signalF may result in several waiters
--   obtaining values. Waking waiting threads is asynchronous.
--   
--   signalF may block, and it can be safely interrupted. If the
--   provided function throws an error or is interrupted then it leaves the
--   MSemN unchanged. All signal, signalF,
--   peekAvail, and the head waiter may momentarily block in a fair
--   FIFO manner.
--   
--   Note: A long running pure function will block all other access to the
--   MSemN while it is evaluated.
signalF :: Integral i => MSemN i -> (i -> (i, b)) -> IO (i, b)

-- | peekAvail skips the queue of any blocked wait and
--   waitF threads, but may momentarily block on signal,
--   signalF, other peekAvail, and the head waiter. This
--   returns the amount of value available to be taken. Using this value
--   without producing unwanted race conditions is left up to the
--   programmer.
--   
--   peekAvail is an optimized form of "signalF m (x -> (0,x))".
--   
--   A version of peekAvail that joins the FIFO queue of wait
--   and waitF can be acheived by "waitF m (x -> (0,x))"
peekAvail :: Integral i => MSemN i -> IO i
instance GHC.Classes.Eq i => GHC.Classes.Eq (Control.Concurrent.MSemN.MS i)
instance GHC.Classes.Eq (Control.Concurrent.MSemN.MSemN i)

-- | Quantity semaphores in which each thread may wait for an arbitrary
--   amount. This modules is intended to improve on
--   Control.Concurrent.QSemN.
--   
--   This semaphore gracefully handles threads which die while blocked
--   waiting for quantity. The fairness guarantee is that blocked threads
--   are FIFO. An early thread waiting for a large quantity will prevent a
--   later thread waiting for a small quantity from jumping the queue.
--   
--   If with is used to guard a critical section then no quantity of
--   the semaphore will be lost if the activity throws an exception.
--   
--   The functions below are generic in (Integral i) with specialization to
--   Int and Integer.
--   
--   Overflow warning: These operations do not check for overflow errors.
--   If the Integral type is too small to accept the new total then the
--   behavior of these operations is undefined. Using (MSem Integer)
--   prevents the possibility of an overflow error.
module Control.Concurrent.MSemN2

-- | A MSemN is a quantity semaphore, in which the available
--   quantity may be signalled or waited for in arbitrary amounts.
data MSemN i

-- | new allows positive, zero, and negative initial values. The
--   initial value is forced here to better localize errors.
new :: Integral i => i -> IO (MSemN i)

-- | with takes a quantity of the semaphore to take and hold while
--   performing the provided operation. with ensures the quantity of
--   the sempahore cannot be lost if there are exceptions. This uses
--   bracket to ensure wait and signal get called
--   correctly.
with :: Integral i => MSemN i -> i -> IO a -> IO a

-- | wait allow positive, zero, and negative wanted values. Waiters
--   may block, and will be handled fairly in FIFO order.
--   
--   If wait returns without interruption then it left the
--   MSemN with a remaining quantity that was greater than or equal
--   to zero. If wait is interrupted then no quantity is lost. If
--   wait returns without interruption then it is known that each
--   earlier waiter has definitely either been interrupted or has retured
--   without interruption.
wait :: Integral i => MSemN i -> i -> IO ()

-- | signal allows positive, zero, and negative values, thus this is
--   also way to remove quantity that skips any threads in the
--   wait/waitF queue. If the new total is greater than the
--   next value being waited for (if present) then the first waiter is
--   woken. If there are queued waiters then the next one will wake after a
--   waiter has proceeded and notice the remaining value; thus a single
--   signal may result in several waiters obtaining values. Waking
--   waiting threads is asynchronous.
--   
--   signal may block, but it cannot be interrupted, which allows it
--   to dependably restore value to the MSemN. All signal,
--   signalF, peekAvail, and the head waiter may momentarily
--   block in a fair FIFO manner.
signal :: Integral i => MSemN i -> i -> IO ()

-- | withF takes a pure function and an operation. The pure function
--   converts the available quantity to a pair of the wanted quantity and a
--   returned value. The operation takes the result of the pure function.
--   withF ensures the quantity of the sempahore cannot be lost if
--   there are exceptions. This uses bracket to ensure waitF
--   and signal get called correctly.
--   
--   Note: A long running pure function will block all other access to the
--   MSemN while it is evaluated.
withF :: Integral i => MSemN i -> (i -> (i, b)) -> ((i, b) -> IO a) -> IO a

-- | waitWith takes the MSemN and a pure function that
--   takes the available quantity and computes the amount wanted and a
--   second value. The value wanted is stricly evaluated but the second
--   value is returned lazily.
--   
--   waitF allow positive, zero, and negative wanted values. Waiters
--   may block, and will be handled fairly in FIFO order.
--   
--   If waitF returns without interruption then it left the
--   MSemN with a remaining quantity that was greater than or equal
--   to zero. If waitF or the provided function are interrupted then
--   no quantity is lost. If waitF returns without interruption then
--   it is known that each previous waiter has each definitely either been
--   interrupted or has retured without interruption.
--   
--   Note: A long running pure function will block all other access to the
--   MSemN while it is evaluated.
waitF :: Integral i => MSemN i -> (i -> (i, b)) -> IO (i, b)

-- | Instead of providing a fixed change to the available quantity,
--   signalF applies a provided pure function to the available
--   quantity to compute the change and a second value. The requested
--   change is stricly evaluated but the second value is returned lazily.
--   If the new total is greater than the next value being waited for then
--   the first waiter is woken. If there are queued waiters then the next
--   one will wake after a waiter has proceeded and notice the remaining
--   value; thus a single signalF may result in several waiters
--   obtaining values. Waking waiting threads is asynchronous.
--   
--   signalF may block, and it can be safely interrupted. If the
--   provided function throws an error or is interrupted then it leaves the
--   MSemN unchanged. All signal, signalF,
--   peekAvail, and the head waiter may momentarily block in a fair
--   FIFO manner.
--   
--   Note: A long running pure function will block all other access to the
--   MSemN while it is evaluated.
signalF :: Integral i => MSemN i -> (i -> (i, b)) -> IO (i, b)

-- | peekAvail skips the queue of any blocked wait and
--   waitF threads, but may momentarily block on signal,
--   signalF, other peekAvail, and the head waiter. This
--   returns the amount of value available to be taken. Using this value
--   without producing unwanted race conditions is left up to the
--   programmer.
--   
--   peekAvail is an optimized form of "signalF m (x -> (0,x))".
--   
--   Quantity that has been passed to a blocked waiter but not picked up is
--   not counted. If the blocked waiter is killed before picking it up then
--   the passed quantity will be recovered by the next waiter. In this
--   exceptional case this next waiter may see an available total that is
--   different than returned by peekAvail.
--   
--   A version of peekAvail that joins the FIFO queue of wait
--   and waitF can be acheived by "waitF m (x -> (0,x))" but this
--   will block if x is negative. On the other hand this method will see
--   the total including any recovered quantity.
peekAvail :: Integral i => MSemN i -> IO i
instance GHC.Classes.Eq i => GHC.Classes.Eq (Control.Concurrent.MSemN2.MS i)
instance GHC.Classes.Eq (Control.Concurrent.MSemN2.MSemN i)

-- | Very simple quantity semaphore.
module Control.Concurrent.STM.SSem
data SSem

-- | Create a new semaphore with the given argument as the initially
--   available quantity. This allows new semaphores to start with a
--   negative, zero, or positive quantity.
new :: Int -> STM SSem

-- | Try to take a unit of value from the semaphore. This succeeds when the
--   current quantity is positive, and then reduces the quantity by one.
--   Otherwise this will retry. This will never result in a negative
--   quantity. If several threads are retying then which one succeeds next
--   is undefined -- an unlucky thread might starve.
wait :: SSem -> STM ()

-- | Signal that single unit of the semaphore is available. This increases
--   the available quantity by one.
signal :: SSem -> STM ()

-- | Non-retrying version of wait. `tryWait s` is defined as `tryN s
--   1`
tryWait :: SSem -> STM (Maybe Int)

-- | Try to take the given value from the semaphore. This succeeds when the
--   quantity is greater or equal to the given value, and then subtracts
--   the given value from the quantity. Otherwise this will retry.
--   This will never result in a negative quantity. If several threads are
--   retrying then which one succeeds next is undefined -- an unlucky
--   thread might starve.
waitN :: SSem -> Int -> STM ()

-- | Signal that many units of the semaphore are available. This changes
--   the available quantity by adding the passed size.
signalN :: SSem -> Int -> STM ()

-- | Non-retrying version of waitN. It either takes the quantity from the
--   semaphore like waitN and returns `Just value taken` or finds
--   insufficient quantity to take and returns Nothing
tryWaitN :: SSem -> Int -> STM (Maybe Int)

-- | Return the current quantity in the semaphore. This is potentially
--   useful in a larger STM transaciton and less useful as `atomically
--   getValueSem :: IO Int` due to race conditions.
getValue :: SSem -> STM Int

-- | Very simple quantity semaphore.
module Control.Concurrent.SSem
data SSem

-- | Create a new semaphore with the given argument as the initially
--   available quantity. This allows new semaphores to start with a
--   negative, zero, or positive quantity.
new :: Int -> IO SSem

-- | It is recommended that all paired uses of wait and
--   signal use the with bracketed form to ensure
--   exceptions safety.
withSem :: SSem -> IO a -> IO a

-- | Try to take a unit of value from the semaphore. This succeeds when the
--   current quantity is positive, and then reduces the quantity by one.
--   Otherwise this will block and retry until it succeeds or is
--   killed. This will never result in a negative quantity. If several
--   threads are retying then which one succeeds next is undefined -- an
--   unlucky thread might starve.
wait :: SSem -> IO ()

-- | Signal that single unit of the semaphore is available. This increases
--   the available quantity by one.
signal :: SSem -> IO ()

-- | Non-waiting version of wait. `tryWait s` is defined as `tryWaitN s 1`
tryWait :: SSem -> IO (Maybe Int)

-- | It is recommended that all paired uses of waitN and
--   signalN use the withN bracketed form to ensure
--   exceptions safety.
withSemN :: SSem -> Int -> IO a -> IO a

-- | Try to take the given value from the semaphore. This succeeds when the
--   quantity is greater or equal to the given value, and then subtracts
--   the given value from the quantity. Otherwise this will block and
--   retry until it succeeds or is killed. This will never result
--   in a negative quantity. If several threads are retrying then which one
--   succeeds next is undefined -- an unlucky thread might starve.
waitN :: SSem -> Int -> IO ()

-- | Signal that many units of the semaphore are available. This changes
--   the available quantity by adding the passed size.
signalN :: SSem -> Int -> IO ()

-- | Non-waiting version of waitN. It either takes the quantity from the
--   semaphore like waitN and returns `Just value taken` or finds
--   insufficient quantity to take and returns Nothing
tryWaitN :: SSem -> Int -> IO (Maybe Int)

-- | This returns the current quantity in the semaphore. This is diffucult
--   to use due to race conditions.
getValue :: SSem -> IO Int
