-- 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 in base. -- Performance has not been compared. In the source is a -- tests/TestKillSem.hs executable (run by cabal test) that shows the -- problem with QSem. @package SafeSemaphore @version 0.6.0 -- | 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: -- -- -- -- 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 Eq (MSampleVar a) instance Typeable1 MSampleVar -- | 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. 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 -- | new allows positive, zero, and negative initial values. The -- initial value is forced here to better localize errors. new :: Integer -> IO MSemN -- | 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 :: MSemN -> Integer -> 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 :: MSemN -> Integer -> 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 :: MSemN -> Integer -> 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 :: MSemN -> (Integer -> (Integer, b)) -> ((Integer, 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 :: MSemN -> (Integer -> (Integer, b)) -> IO (Integer, 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 :: MSemN -> (Integer -> (Integer, b)) -> IO (Integer, 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 :: MSemN -> IO Integer instance Typeable MS instance Typeable MSemN instance Eq MS instance Eq MSemN -- | 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 FIFO. -- -- If with is used to guard a critical section then no quantity of -- the semaphore will be lost if the activity throws an exception. -- new can initialize the semaphore to negative, zero, or positive -- quantity. wait always leaves the MSem with non-negative -- quantity. 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 -- | new allows positive, zero, and negative initial values. The -- initial value is forced here to better localize errors. new :: Integer -> IO MSem -- | 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. -- -- with uses bracket_ to ensure wait and -- signal get called correctly. with :: MSem -> 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 without interruption 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. wait :: MSem -> IO () -- | signal adds one unit to the sempahore. -- -- 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 :: MSem -> 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 :: MSem -> IO Integer instance Typeable MS instance Typeable MSem instance Eq MS instance Eq MSem