-- 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
--   <a>https://github.com/ChrisKuklewicz/SafeSemaphore</a> for more
--   details.
@package SafeSemaphore
@version 0.10.1


-- | 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 <a>retry</a>. 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 <a>wait</a>. `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 <a>retry</a>.
--   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 <a>wait</a> and
--   <a>signal</a> use the <tt>with</tt> 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 <tt>retry</tt> 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 <a>waitN</a> and
--   <a>signalN</a> use the <tt>withN</tt> 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
--   <tt>retry</tt> 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


-- | Provides a fair RWLock, similar to one from Java, which is itself
--   documented at
--   <a>http://download.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html</a>
--   
--   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 <tt>FairRWLock</tt> 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 <a>acquireWrite</a> will block,
--   and subsequent <a>acquireRead</a> and <a>acquireWrite</a> will queue
--   in order. When in the write locked state all other threads trying to
--   <a>acquireWrite</a> or <a>acquireRead</a> will queue in order.
--   
--   <tt>FairRWLock</tt> 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 <a>new</a>,
--   <a>withRead</a>, and <a>withWrite</a>.
--   
--   No sequence of calling acquire on a single RWLock should lead to
--   deadlock. Exceptions, espcially from <a>killThread</a>, do not break
--   <a>withRead</a> or <a>withWrite</a>. The <a>withRead</a> and
--   <a>withWrite</a> ensure all locks get released when exiting due to an
--   exception.
--   
--   The readers and writers are always identified by their
--   <a>ThreadId</a>. Each thread that calls <a>acquireRead</a> must later
--   call <a>releaseRead</a> from the same thread. Each thread that calls
--   <a>acquireWrite</a> must later call <a>releaseWrite</a> 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 <a>releaseRead</a> and <a>releaseWrite</a>. Only if the
--   <tt>FairRWLock</tt> 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
--   <a>uninterruptibleMask_</a> 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.Show.Show Control.Concurrent.FairRWLock.FRW
instance GHC.Show.Show Control.Concurrent.FairRWLock.RWLockException
instance GHC.Show.Show Control.Concurrent.FairRWLock.RWLockExceptionKind
instance GHC.Classes.Eq Control.Concurrent.FairRWLock.LockUser
instance GHC.Show.Show Control.Concurrent.FairRWLock.LockKind
instance GHC.Classes.Ord Control.Concurrent.FairRWLock.LockKind
instance GHC.Classes.Eq Control.Concurrent.FairRWLock.LockKind
instance GHC.Exception.Exception Control.Concurrent.FairRWLock.RWLockException


-- | <a>MSampleVar</a> is a safer version of the
--   <a>Control.Concurrent.SampleVar</a> in base. The same problem as
--   QSem(N) is being fixed, that of handling waiters that die before being
--   woken normally. For <a>Control.Concurrent.SampleVar</a> in base this
--   error can lead to thinking a full <tt>SampleVar</tt> is really empty
--   and cause <tt>writeSampleVar</tt> to hang. The <a>MSampleVar</a> 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 <a>MVar</a>:
--   
--   <ul>
--   <li>Reading an empty <a>MSampleVar</a> causes the reader to block.
--   (same as <a>takeMVar</a> on empty <a>MVar</a>)</li>
--   <li>Reading a filled <a>MSampleVar</a> empties it and returns value.
--   (same as <a>takeMVar</a>)</li>
--   <li>Try reading a filled <a>MSampleVar</a> returns a Maybe value.
--   (same as <a>tryTakeMVar</a>)</li>
--   <li>Writing to an empty <a>MSampleVar</a> fills it with a value, and
--   potentially, wakes up a blocked reader (same as for <a>putMVar</a> on
--   empty <a>MVar</a>).</li>
--   <li>Writing to a filled <a>MSampleVar</a> overwrites the current
--   value. (different from <a>putMVar</a> on full <a>MVar</a>.)</li>
--   </ul>
--   
--   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

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

-- | <a>newSV</a> 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 <a>MSampleVar</a>.
newSV :: a -> IO (MSampleVar a)

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

-- | Wait for a value to become available, then take it and return. The
--   queue of blocked <a>readSV</a> threads is a fair FIFO queue.
--   
--   <a>readSV</a> 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 <a>MSampleVar</a>, overwriting any previous
--   value that was there.
--   
--   <a>writeSV</a> can block and be interrupted, in which case it does
--   nothing.
writeSV :: MSampleVar a -> a -> IO ()

-- | <a>isEmptySV</a> can block and be interrupted, in which case it does
--   nothing. If <a>isEmptySV</a> returns then it reports the momentary
--   status the <a>MSampleVar</a>. 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)


-- | Quantity semaphores in which each thread may wait for an arbitrary
--   amount. This modules is intended to improve on
--   <a>Control.Concurrent.QSemN</a>.
--   
--   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 <a>with</a> 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 <a>MSemN</a> is a quantity semaphore, in which the available
--   quantity may be signalled or waited for in arbitrary amounts.
data MSemN i

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

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

-- | <a>wait</a> allow positive, zero, and negative wanted values. Waiters
--   may block, and will be handled fairly in FIFO order.
--   
--   If <a>wait</a> returns without interruption then it left the
--   <a>MSemN</a> with a remaining quantity that was greater than or equal
--   to zero. If <a>wait</a> is interrupted then no quantity is lost. If
--   <a>wait</a> 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 ()

-- | <a>signal</a> 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 <a>signal</a>
--   may result in several waiters obtaining values. Waking waiting threads
--   is asynchronous.
--   
--   <a>signal</a> may block, but it cannot be interrupted, which allows it
--   to dependably restore value to the <a>MSemN</a>. All <a>signal</a>,
--   <a>signalF</a>, <a>peekAvail</a>, and the head waiter may momentarily
--   block in a fair FIFO manner.
signal :: Integral i => MSemN i -> i -> IO ()

-- | <a>withF</a> 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.
--   <a>withF</a> ensures the quantity of the sempahore cannot be lost if
--   there are exceptions. This uses <a>bracket</a> to ensure <a>waitF</a>
--   and <a>signal</a> get called correctly.
--   
--   Note: A long running pure function will block all other access to the
--   <a>MSemN</a> while it is evaluated.
withF :: Integral i => MSemN i -> (i -> (i, b)) -> ((i, b) -> IO a) -> IO a

-- | <tt>waitWith</tt> takes the <a>MSemN</a> 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.
--   
--   <a>waitF</a> allow positive, zero, and negative wanted values. Waiters
--   may block, and will be handled fairly in FIFO order.
--   
--   If <a>waitF</a> returns without interruption then it left the
--   <a>MSemN</a> with a remaining quantity that was greater than or equal
--   to zero. If <a>waitF</a> or the provided function are interrupted then
--   no quantity is lost. If <a>waitF</a> 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
--   <a>MSemN</a> 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,
--   <a>signalF</a> 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 <a>signalF</a> may result in several waiters
--   obtaining values. Waking waiting threads is asynchronous.
--   
--   <a>signalF</a> may block, and it can be safely interrupted. If the
--   provided function throws an error or is interrupted then it leaves the
--   <a>MSemN</a> unchanged. All <a>signal</a>, <a>signalF</a>,
--   <a>peekAvail</a>, 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
--   <a>MSemN</a> while it is evaluated.
signalF :: Integral i => MSemN i -> (i -> (i, b)) -> IO (i, b)

-- | <a>peekAvail</a> skips the queue of any blocked <a>wait</a> and
--   <a>waitF</a> threads, but may momentarily block on <a>signal</a>,
--   <a>signalF</a>, other <a>peekAvail</a>, 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.
--   
--   <a>peekAvail</a> is an optimized form of "signalF m (x -&gt; (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 <a>peekAvail</a> that joins the FIFO queue of <a>wait</a>
--   and <a>waitF</a> can be acheived by "waitF m (x -&gt; (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 (Control.Concurrent.MSemN2.MSemN i)
instance GHC.Classes.Eq i => GHC.Classes.Eq (Control.Concurrent.MSemN2.MS i)


-- | Quantity semaphores in which each thread may wait for an arbitrary
--   amount. This modules is intended to improve on
--   <a>Control.Concurrent.QSemN</a>.
--   
--   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 <a>with</a> 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 <a>MSemN</a> is a quantity semaphore, in which the available
--   quantity may be signalled or waited for in arbitrary amounts.
data MSemN i

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

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

-- | <a>wait</a> 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 <a>wait</a> 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 <a>wait</a> returns without interruption then it left the
--   <a>MSemN</a> with a remaining quantity that was greater than or equal
--   to zero. If <a>wait</a> is interrupted then no quantity is lost. If
--   <a>wait</a> 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 ()

-- | <a>signal</a> 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 <a>signal</a>
--   may result in several waiters obtaining values. Waking waiting threads
--   is asynchronous.
--   
--   <a>signal</a> may block, but it cannot be interrupted, which allows it
--   to dependably restore value to the <a>MSemN</a>. All <a>signal</a>,
--   <a>signalF</a>, <a>peekAvail</a>, and the head waiter may momentarily
--   block in a fair FIFO manner.
signal :: Integral i => MSemN i -> i -> IO ()

-- | <a>withF</a> 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.
--   <a>withF</a> ensures the quantity of the sempahore cannot be lost if
--   there are exceptions. This uses <a>bracket</a> to ensure <a>waitF</a>
--   and <a>signal</a> get called correctly.
--   
--   Note: A long running pure function will block all other access to the
--   <a>MSemN</a> while it is evaluated.
withF :: Integral i => MSemN i -> (i -> (i, b)) -> ((i, b) -> IO a) -> IO a

-- | <tt>waitWith</tt> takes the <a>MSemN</a> 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.
--   
--   <a>waitF</a> 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 <a>waitF</a> 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 <a>waitF</a> returns without interruption then it left the
--   <a>MSemN</a> with a remaining quantity that was greater than or equal
--   to zero. If <a>waitF</a> or the provided function are interrupted then
--   no quantity is lost. If <a>waitF</a> 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
--   <a>MSemN</a> 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,
--   <a>signalF</a> 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 <a>signalF</a> may result in several waiters
--   obtaining values. Waking waiting threads is asynchronous.
--   
--   <a>signalF</a> may block, and it can be safely interrupted. If the
--   provided function throws an error or is interrupted then it leaves the
--   <a>MSemN</a> unchanged. All <a>signal</a>, <a>signalF</a>,
--   <a>peekAvail</a>, 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
--   <a>MSemN</a> while it is evaluated.
signalF :: Integral i => MSemN i -> (i -> (i, b)) -> IO (i, b)

-- | <a>peekAvail</a> skips the queue of any blocked <a>wait</a> and
--   <a>waitF</a> threads, but may momentarily block on <a>signal</a>,
--   <a>signalF</a>, other <a>peekAvail</a>, 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.
--   
--   <a>peekAvail</a> is an optimized form of "signalF m (x -&gt; (0,x))".
--   
--   A version of <a>peekAvail</a> that joins the FIFO queue of <a>wait</a>
--   and <a>waitF</a> can be acheived by "waitF m (x -&gt; (0,x))"
peekAvail :: Integral i => MSemN i -> IO i
instance GHC.Classes.Eq (Control.Concurrent.MSemN.MSemN i)
instance GHC.Classes.Eq i => GHC.Classes.Eq (Control.Concurrent.MSemN.MS i)


-- | This is a literate haskell version of Control.Concurrent.MSem for
--   increased clarity.
--   
--   A semaphore in which operations may <a>wait</a> for or <a>signal</a>
--   single units of value. This modules is intended to improve on
--   <a>Control.Concurrent.QSem</a>.
--   
--   This semaphore gracefully handles threads which die while blocked
--   waiting. The fairness guarantee is that blocked threads are servied in
--   a FIFO order.
--   
--   If <a>with</a> 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.
--   
--   <a>new</a> can initialize the semaphore to negative, zero, or positive
--   quantity. <a>wait</a> always leaves the <a>MSem</a> with non-negative
--   quantity. <a>signal</a> 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 <a>signal</a> is undefined. Using (MSem Integer) prevents
--   the possibility of an overflow error. [ A version of <a>signal</a>
--   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 <a>MSem</a> 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

-- | <a>new</a> 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 <a>new</a>. Once a negative quantity becomes
--   non-negative by use of <a>signal</a> it will never later be negative.
new :: Integral i => i -> IO (MSem i)

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

-- | <a>wait</a> will take one unit of value from the sempahore, but will
--   block if the quantity available is not positive.
--   
--   If <a>wait</a> returns normally (not interrupted) then it left the
--   <a>MSem</a> with a remaining quantity that was greater than or equal
--   to zero. If <a>wait</a> is interrupted then no quantity is lost. If
--   <a>wait</a> 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 ()

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

-- | <a>peekAvail</a> skips the queue of any blocked <a>wait</a> threads,
--   but may momentarily block on <a>signal</a>, other <a>peekAvail</a>,
--   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 <a>Control.Concurrent.MSemN</a> 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)
