-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Extra concurrency primitives
--
-- The concurrent-extra package offers among other things the
-- following selection of synchronisation primitives:
--
--
-- - Broadcast: Wake multiple threads by broadcasting a
-- value.
-- - Event: Wake multiple threads by signalling an event.
-- - Lock: Enforce exclusive access to a resource. Also known
-- as a binary semaphore or mutex.
-- - RLock: A lock which can be acquired multiple times by the
-- same thread. Also known as a reentrant mutex.
-- - ReadWriteLock: Multiple-reader, single-writer locks. Used
-- to protect shared resources which may be concurrently read, but only
-- sequentially written.
-- - ReadWriteVar: Concurrent read, sequential write
-- variables.
--
--
-- Besides these synchronisation primitives the package also provides:
--
--
-- - Thread: Threads extended with the ability to wait for
-- their termination.
-- - Thread.Delay: Arbitrarily long thread delays.
-- - Timeout: Wait arbitrarily long for an IO computation to
-- finish.
--
--
-- Please consult the API documentation of the individual modules for
-- more detailed information.
--
-- This package was inspired by the concurrency libraries of Java and
-- Python.
@package concurrent-extra
@version 0.4
-- | Arbitrarily long thread delays.
module Control.Concurrent.Thread.Delay
-- | Like threadDelay, but not bounded by an Int.
--
-- Suspends the current thread for a given number of microseconds (GHC
-- only).
--
-- There is no guarantee that the thread will be rescheduled promptly
-- when the delay has expired, but the thread will never continue to run
-- earlier than specified.
delay :: Integer -> IO ()
-- | Wait arbitrarily long for an IO computation to finish.
module Control.Concurrent.Timeout
-- | Like timeout, but not bounded by an Int.
--
-- Wrap an IO computation to time out and return Nothing in
-- case no result is available within n microseconds
-- (1/10^6 seconds). In case a result is available before the
-- timeout expires, Just a is returned. A negative
-- timeout interval means "wait indefinitely".
--
-- The design of this combinator was guided by the objective that
-- timeout n f should behave exactly the same as f as
-- long as f doesn't time out. This means that f has
-- the same myThreadId it would have without the timeout wrapper.
-- Any exceptions f might throw cancel the timeout and propagate
-- further up. It also possible for f to receive exceptions
-- thrown to it by another thread.
--
-- A tricky implementation detail is the question of how to abort an
-- IO computation. This combinator relies on asynchronous
-- exceptions internally. The technique works very well for computations
-- executing inside of the Haskell runtime system, but it doesn't work at
-- all for non-Haskell code. Foreign function calls, for example, cannot
-- be timed out with this combinator simply because an arbitrary C
-- function cannot receive asynchronous exceptions. When timeout
-- is used to wrap an FFI call that blocks, no timeout event can be
-- delivered until the FFI call returns, which pretty much negates the
-- purpose of the combinator. In practice, however, this limitation is
-- less severe than it may sound. Standard I/O functions like
-- hGetBuf, hPutBuf, Network.Socket.accept, or
-- hWaitForInput appear to be blocking, but they really don't
-- because the runtime system uses scheduling mechanisms like
-- select(2) to perform asynchronous I/O, so it is possible to
-- interrupt standard socket I/O or file I/O using this combinator.
timeout :: Integer -> IO α -> IO (Maybe α)
instance Typeable Timeout
instance Eq Timeout
instance Exception Timeout
instance Show Timeout
-- | A Broadcast is a mechanism for communication between threads.
-- Multiple listeners wait until a broadcaster
-- broadcasts a value. The listeners block until the
-- value is received. When the broadcaster broadcasts a value all
-- listeners are woken.
--
-- All functions are exception safe. Throwing asynchronous
-- exceptions will not compromise the internal state of a broadcast.
--
-- This module is designed to be imported qualified. We suggest importing
-- it like:
--
--
-- import Control.Concurrent.Broadcast ( Broadcast )
-- import qualified Control.Concurrent.Broadcast as Broadcast ( ... )
--
module Control.Concurrent.Broadcast
-- | A broadcast is in one of two possible states:
--
--
-- - "Silent": listening to the broadcast will block
-- until a value is broadcasted.
-- - "Broadcasting x": listening to the
-- broadcast will return the value x without blocking.
--
data Broadcast α
-- | new Creates a broadcast in the "silent" state.
new :: IO (Broadcast α)
-- | newBroadcasting x Creates a broadcast in the "broadcasting
-- x" state.
newBroadcasting :: α -> IO (Broadcast α)
-- | Listen to a broadcast.
--
--
-- - If the broadcast is "broadcasting x", listen
-- will return x immediately.
-- - If the broadcast is "silent", listen will block until
-- another thread broadcasts a value to the
-- broadcast.
--
listen :: Broadcast α -> IO α
-- | Try to listen to a broadcast; non blocking.
--
--
-- - If the broadcast is "broadcasting x", tryListen
-- will return Just x immediately.
-- - If the broadcast is "silent", tryListen returns
-- Nothing immediately.
--
tryListen :: Broadcast α -> IO (Maybe α)
-- | Listen to a broadcast if it is available within a given amount of
-- time.
--
-- Like listen, but with a timeout. A return value of
-- Nothing indicates a timeout occurred.
--
-- The timeout is specified in microseconds.
--
-- If the broadcast is "silent" and a timeout of 0 μs is specified the
-- function returns Nothing without blocking.
--
-- Negative timeouts are treated the same as a timeout of 0 μs.
listenTimeout :: Broadcast α -> Integer -> IO (Maybe α)
-- | Broadcast a value.
--
-- broadcast b x changes the state of the broadcast b
-- to "broadcasting x".
--
-- If the broadcast was "silent" all threads that are
-- listening to the broadcast will be woken.
broadcast :: Broadcast α -> α -> IO ()
-- | Broadcast a value before becoming "silent".
--
-- The state of the broadcast is changed to "silent" after all threads
-- that are listening to the broadcast are woken and
-- resume with the signalled value.
--
-- The semantics of signal are equivalent to the following definition:
--
--
-- signal b x = block $ broadcast b x >> silence b
--
signal :: Broadcast α -> α -> IO ()
-- | Set a broadcast to the "silent" state.
silence :: Broadcast α -> IO ()
instance Typeable1 Broadcast
instance Eq (Broadcast α)
-- | Standard threads extended with the ability to wait for their
-- termination.
--
-- Inspired by: http://hackage.haskell.org/package/threadmanager
--
-- This module re-implements several functions from
-- Control.Concurrent. Avoid ambiguities by importing one or
-- both qualified. We suggest importing this module like:
--
--
-- import qualified Control.Concurrent.Thread as Thread ( ... )
--
module Control.Concurrent.Thread
-- | A ThreadId α is an abstract type representing a handle
-- to a thread that is executing or has executed a computation of type
-- IO α.
--
-- ThreadId α is an instance of Eq, Ord and
-- Show, where the Ord instance implements an arbitrary
-- total ordering over ThreadIds. The Show instance lets
-- you convert an arbitrary-valued ThreadId to string form;
-- showing a ThreadId value is occasionally useful when debugging
-- or diagnosing the behaviour of a concurrent program.
data ThreadId α
-- | Extract the underlying ThreadId
-- (Conctrol.Concurrent.ThreadId).
threadId :: ThreadId α -> ThreadId
-- | Sparks off a new thread to run the given IO computation and
-- returns the ThreadId of the newly created thread.
--
-- The new thread will be a lightweight thread; if you want to use a
-- foreign library that uses thread-local storage, use forkOS
-- instead.
--
-- GHC note: the new thread inherits the blocked state of the parent (see
-- block).
--
-- The newly created thread has an exception handler that discards the
-- exceptions BlockedIndefinitelyOnMVar,
-- BlockedIndefinitelyOnSTM, and ThreadKilled. All other
-- exceptions are recorded in the ThreadId and can be retrieved
-- using wait.
forkIO :: IO α -> IO (ThreadId α)
-- | Like forkIO, this sparks off a new thread to run the given
-- IO computation and returns the ThreadId of the newly
-- created thread.
--
-- Unlike forkIO, forkOS creates a bound thread,
-- which is necessary if you need to call foreign (non-Haskell) libraries
-- that make use of thread-local state, such as OpenGL (see
-- Control.Concurrent).
--
-- Using forkOS instead of forkIO makes no difference at
-- all to the scheduling behaviour of the Haskell runtime system. It is a
-- common misconception that you need to use forkOS instead of
-- forkIO to avoid blocking all the Haskell threads when making a
-- foreign call; this isn't the case. To allow foreign calls to be made
-- without blocking all the Haskell threads (with GHC), it is only
-- necessary to use the -threaded option when linking your
-- program, and to make sure the foreign import is not marked
-- unsafe.
forkOS :: IO α -> IO (ThreadId α)
-- | Block until the given thread is terminated.
--
--
-- - Returns Right x if the thread terminated normally
-- and returned x.
-- - Returns Left e if some exception e was
-- thrown in the thread and wasn't caught.
--
wait :: ThreadId α -> IO (Either SomeException α)
-- | Like wait but will ignore the value returned by the thread.
wait_ :: ThreadId α -> IO ()
-- | Like wait but will either rethrow the exception that was thrown
-- in the thread or return the value that was returned by the thread.
unsafeWait :: ThreadId α -> IO α
-- | Like unsafeWait in that it will rethrow the exception that was
-- thrown in the thread but it will ignore the value returned by the
-- thread.
unsafeWait_ :: ThreadId α -> IO ()
-- | Block until the given thread is terminated or until a timer expires.
--
--
-- - Returns Nothing if a timeout occurred.
-- - Returns Just the result wait would return when the
-- thread finished within the specified time.
--
--
-- The timeout is specified in microseconds.
waitTimeout :: ThreadId α -> Integer -> IO (Maybe (Either SomeException α))
-- | Like waitTimeout but will ignore the value returned by the
-- thread. Returns False when a timeout occurred and True
-- otherwise.
waitTimeout_ :: ThreadId α -> Integer -> IO Bool
-- | Like waitTimeout but will rethrow the exception that was thrown
-- in the thread. Returns Nothing if a timeout occured or
-- Just the value returned from the target thread.
unsafeWaitTimeout :: ThreadId α -> Integer -> IO (Maybe α)
-- | Like unsafeWaitTimeout in that it will rethrow the exception
-- that was thrown in the thread but it will ignore the value returned by
-- the thread. Returns False when a timeout occurred and
-- True otherwise.
unsafeWaitTimeout_ :: ThreadId α -> Integer -> IO Bool
-- | Returns True if the given thread is currently running.
--
-- Notice that this observation is only a snapshot of a thread's state.
-- By the time a program reacts on its result it may already be out of
-- date.
isRunning :: ThreadId α -> IO Bool
-- | throwTo raises an arbitrary exception in the target thread (GHC
-- only).
--
-- throwTo does not return until the exception has been raised in
-- the target thread. The calling thread can thus be certain that the
-- target thread has received the exception. This is a useful property to
-- know when dealing with race conditions: eg. if there are two threads
-- that can kill each other, it is guaranteed that only one of the
-- threads will get to kill the other.
--
-- If the target thread is currently making a foreign call, then the
-- exception will not be raised (and hence throwTo will not
-- return) until the call has completed. This is the case regardless of
-- whether the call is inside a block or not.
--
-- Important note: the behaviour of throwTo differs from that
-- described in the paper "Asynchronous exceptions in Haskell"
-- (http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm).
-- In the paper, throwTo is non-blocking; but the library
-- implementation adopts a more synchronous design in which
-- throwTo does not return until the exception is received by the
-- target thread. The trade-off is discussed in Section 9 of the paper.
-- Like any blocking operation, throwTo is therefore interruptible
-- (see Section 5.3 of the paper).
--
-- There is currently no guarantee that the exception delivered by
-- throwTo will be delivered at the first possible opportunity. In
-- particular, a thread may unblock and then re-block
-- exceptions without receiving a pending throwTo. This is
-- arguably undesirable behaviour.
throwTo :: (Exception e) => ThreadId α -> e -> IO ()
-- | killThread terminates the given thread (GHC only). Any work
-- already done by the thread isn't lost: the computation is suspended
-- until required by another thread. The memory used by the thread will
-- be garbage collected if it isn't referenced from anywhere. The
-- killThread function is defined in terms of throwTo.
--
-- This function blocks until the target thread is terminated. It is a
-- no-op if the target thread has already completed.
killThread :: ThreadId α -> IO ()
-- | Like killThread but with a timeout. Returns True if the
-- target thread was terminated within the given amount of time,
-- False otherwise.
--
-- The timeout is specified in microseconds.
--
-- Note that even when a timeout occurs, the target thread can still
-- terminate at a later time as a direct result of calling this function.
killThreadTimeout :: ThreadId α -> Integer -> IO Bool
instance Typeable1 ThreadId
instance Show (ThreadId α)
instance Ord (ThreadId α)
instance Eq (ThreadId α)
-- | An Event is a simple mechanism for communication between threads: one
-- thread signals an event and other threads wait for it.
--
-- An event has a state which is either "set" or "cleared". This state
-- can be changed with the corresponding functions set and
-- clear. The wait function blocks until the state is
-- "set". An important property of setting an event is that all
-- threads waiting for it are woken.
--
-- It was inspired by the Python Event object. See:
--
-- http://docs.python.org/3.1/library/threading.html#event-objects
--
-- This module is designed to be imported qualified. We suggest importing
-- it like:
--
--
-- import Control.Concurrent.Event ( Event )
-- import qualified Control.Concurrent.Event as Event ( ... )
--
module Control.Concurrent.Event
-- | An event is in one of two possible states: "set" or "cleared".
data Event
-- | Create an event in the "cleared" state.
new :: IO Event
-- | Create an event in the "set" state.
newSet :: IO Event
-- | Block until the event is set.
--
-- If the state of the event is already "set" this function will return
-- immediately. Otherwise it will block until another thread calls
-- set.
--
-- (You can also resume a thread that is waiting for an event by throwing
-- an asynchronous exception.)
wait :: Event -> IO ()
-- | Block until the event is set or until a timer expires.
--
-- Like wait, but with a timeout. A return value of False
-- indicates a timeout occurred.
--
-- The timeout is specified in microseconds.
--
-- If the event is "cleared" and a timeout of 0 μs is specified the
-- function returns False without blocking.
--
-- Negative timeouts are treated the same as a timeout of 0 μs.
waitTimeout :: Event -> Integer -> IO Bool
-- | Returns True if the state of the event is "set" and
-- False if the state is "cleared".
--
-- Notice that this is only a snapshot of the state. By the time a
-- program reacts on its result it may already be out of date.
isSet :: Event -> IO Bool
-- | Changes the state of the event to "set". All threads that where
-- waiting for this event are woken. Threads that wait after the
-- state is changed to "set" will not block at all.
set :: Event -> IO ()
-- | Changes the state to "cleared" after all threads that where waiting
-- for this event are woken. Threads that wait after a
-- signal will block until the event is set again.
--
-- The semantics of signal are equivalent to the following definition:
--
--
-- signal e = block $ set e >> clear e
--
signal :: Event -> IO ()
-- | Changes the state of the event to "cleared". Threads that wait
-- after the state is changed to "cleared" will block until the state is
-- changed to "set".
clear :: Event -> IO ()
instance Typeable Event
instance Eq Event
-- | This module provides the Lock synchronisation mechanism. It was
-- inspired by the Python and Java Lock objects and should
-- behave in a similar way. See:
--
-- http://docs.python.org/3.1/library/threading.html#lock-objects
--
-- and:
--
--
-- http://java.sun.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html
--
-- All functions are exception safe. Throwing asynchronous
-- exceptions will not compromise the internal state of a Lock.
--
-- This module is intended to be imported qualified. We suggest importing
-- it like:
--
--
-- import Control.Concurrent.Lock ( Lock )
-- import qualified Control.Concurrent.Lock as Lock ( ... )
--
module Control.Concurrent.Lock
-- | A lock is in one of two states: "locked" or "unlocked".
data Lock
-- | Create a lock in the "unlocked" state.
new :: IO Lock
-- | Create a lock in the "locked" state.
newAcquired :: IO Lock
-- | Acquires the Lock. Blocks if another thread has acquired the
-- Lock.
--
-- acquire behaves as follows:
--
--
-- - When the state is "unlocked" acquire changes the state to
-- "locked".
-- - When the state is "locked" acquire blocks until a
-- call to release in another thread wakes the calling thread.
-- Upon awakening it will change the state to "locked".
--
--
-- There are two further important properties of acquire:
--
--
-- - acquire is single-wakeup. That is, if there are multiple
-- threads blocked on acquire and the lock is released, only one
-- thread will be woken up. The runtime guarantees that the woken thread
-- completes its acquire operation.
-- - When multiple threads are blocked on acquire, they are
-- woken up in FIFO order. This is useful for providing fairness
-- properties of abstractions built using locks. (Note that this differs
-- from the Python implementation where the wake-up order is
-- undefined.)
--
acquire :: Lock -> IO ()
-- | A non-blocking acquire.
--
--
-- - When the state is "unlocked" tryAcquire changes the state
-- to "locked" and returns True.
-- - When the state is "locked" tryAcquire leaves the state
-- unchanged and returns False.
--
tryAcquire :: Lock -> IO Bool
-- | release changes the state to "unlocked" and returns
-- immediately.
--
-- Note that it is an error to release a lock in the "unlocked" state!
--
-- If there are any threads blocked on acquire the thread that
-- first called acquire will be woken up.
release :: Lock -> IO ()
-- | A convenience function which first acquires the lock and then performs
-- the computation. When the computation terminates, whether normally or
-- by raising an exception, the lock is released.
--
-- Note that: with = liftA2 bracket_ acquire
-- release.
with :: Lock -> IO a -> IO a
-- | A non-blocking with. tryWith is a convenience function
-- which first tries to acquire the lock. If that fails, Nothing
-- is returned. If it succeeds, the computation is performed. When the
-- computation terminates, whether normally or by raising an exception,
-- the lock is released and Just the result of the computation is
-- returned.
tryWith :: Lock -> IO α -> IO (Maybe α)
-- |
-- - When the state is "locked", wait blocks until a
-- call to release in another thread changes it to
-- "unlocked".
-- - When the state is "unlocked" wait returns
-- immediately.
--
--
-- wait does not alter the state of the lock.
--
-- Note that wait is just a convenience function defined as:
--
--
-- wait l = block $ acquire l >> release l
--
wait :: Lock -> IO ()
-- | Determines if the lock is in the "locked" state.
--
-- Note that this is only a snapshot of the state. By the time a program
-- reacts on its result it may already be out of date.
locked :: Lock -> IO Bool
instance Typeable Lock
instance Eq Lock
-- | This module provides the RLock synchronisation mechanism. It
-- was inspired by the Python RLock and Java
-- ReentrantLock objects and should behave in a similar way.
-- See:
--
-- http://docs.python.org/3.1/library/threading.html#rlock-objects
--
-- and:
--
--
-- http://java.sun.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html
--
-- All functions are exception safe. Throwing asynchronous
-- exceptions will not compromise the internal state of an RLock.
--
-- This module is intended to be imported qualified. We suggest importing
-- it like:
--
--
-- import Control.Concurrent.RLock ( RLock )
-- import qualified Control.Concurrent.RLock as RLock ( ... )
--
module Control.Concurrent.RLock
-- | A reentrant lock is in one of two states: "locked" or "unlocked". When
-- the lock is in the "locked" state it has two additional properties:
--
--
-- - Its owner: the thread that acquired the lock.
-- - Its acquired count: how many times its owner acquired the
-- lock.
--
data RLock
-- | Create a reentrant lock in the "unlocked" state.
new :: IO RLock
-- | Create a reentrant lock in the "locked" state (with the current thread
-- as owner and an acquired count of 1).
newAcquired :: IO RLock
-- | Acquires the RLock. Blocks if another thread has acquired the
-- RLock.
--
-- acquire behaves as follows:
--
--
-- - When the state is "unlocked", acquire changes the state
-- to "locked" with the current thread as owner and an acquired count of
-- 1.
-- - When the state is "locked" and the current thread owns the lock
-- acquire only increments the acquired count.
-- - When the state is "locked" and the current thread does not own the
-- lock acquire blocks until the owner releases the lock.
-- If the thread that called acquire is woken upon release of
-- the lock it will take ownership and change the state to "locked" with
-- an acquired count of 1.
--
--
-- There are two further important properties of acquire:
--
--
-- - acquire is single-wakeup. That is, if there are multiple
-- threads blocked on acquire, and the lock is released, only
-- one thread will be woken up. The runtime guarantees that the woken
-- thread completes its acquire operation.
-- - When multiple threads are blocked on acquire they are
-- woken up in FIFO order. This is useful for providing fairness
-- properties of abstractions built using locks. (Note that this differs
-- from the Python implementation where the wake-up order is
-- undefined.)
--
acquire :: RLock -> IO ()
-- | A non-blocking acquire.
--
--
-- - When the state is "unlocked" tryAcquire changes the state
-- to "locked" (with the current thread as owner and an acquired count of
-- 1) and returns True.
-- - When the state is "locked" tryAcquire leaves the state
-- unchanged and returns False.
--
tryAcquire :: RLock -> IO Bool
-- | release decrements the acquired count. When a lock is
-- released with an acquired count of 1 its state is changed to
-- "unlocked".
--
-- Note that it is both an error to release a lock in the "unlocked"
-- state and to release a lock that is not owned by the current thread.
--
-- If there are any threads blocked on acquire the thread that
-- first called acquire will be woken up.
release :: RLock -> IO ()
-- | A convenience function which first acquires the lock and then performs
-- the computation. When the computation terminates, whether normally or
-- by raising an exception, the lock is released.
--
-- Note that: with = liftA2 bracket_ acquire
-- release.
with :: RLock -> IO α -> IO α
-- | A non-blocking with. tryWith is a convenience function
-- which first tries to acquire the lock. If that fails, Nothing
-- is returned. If it succeeds, the computation is performed. When the
-- computation terminates, whether normally or by raising an exception,
-- the lock is released and Just the result of the computation is
-- returned.
tryWith :: RLock -> IO α -> IO (Maybe α)
-- |
-- - When the state is "locked" wait blocks until a
-- call to release in another thread changes it to
-- "unlocked".
-- - When the state is "unlocked" wait returns
-- immediately.
--
--
-- wait does not alter the state of the lock.
--
-- Note that wait is just a convenience function defined as:
--
--
-- wait l = block $ acquire l >> release l
--
wait :: RLock -> IO ()
-- | The state of an RLock.
--
--
-- - Nothing indicates an "unlocked" state.
-- - Just (tid, n) indicates a "locked" state where the
-- thread identified by tid acquired the lock n
-- times.
--
type State = Maybe (ThreadId, Integer)
-- | Determine the state of the reentrant lock.
--
-- Note that this is only a snapshot of the state. By the time a program
-- reacts on its result it may already be out of date.
state :: RLock -> IO State
instance Typeable RLock
instance Eq RLock
-- | Multiple-reader, single-writer locks. Used to protect shared resources
-- which may be concurrently read, but only sequentially written.
--
-- All functions are exception safe. Throwing asynchronous
-- exceptions will not compromise the internal state of an RWLock.
-- This means it is perfectly safe to kill a thread that is blocking on,
-- for example, acquireRead.
--
-- See also Java's version:
-- http://java.sun.com/javase/7/docs/api/java/util/concurrent/locks/ReadWriteLock.html
--
-- This module is designed to be imported qualified. We suggest importing
-- it like:
--
--
-- import Control.Concurrent.ReadWriteLock ( RWLock )
-- import qualified Control.Concurrent.ReadWriteLock as RWL ( ... )
--
module Control.Concurrent.ReadWriteLock
-- | Multiple-reader, single-writer lock. Is in one of three states:
--
--
-- - "Free": Read or write access can be acquired without
-- blocking.
-- - "Read": One or more threads have acquired read access. Blocks
-- write access.
-- - "Write": A single thread has acquired write access. Blocks other
-- threads from acquiring both read and write access.
--
data RWLock
-- | Create a new RWLock in the "free" state; either read or write
-- access can be acquired without blocking.
new :: IO RWLock
-- | Create a new RWLock in the "read" state; only read can be
-- acquired without blocking.
newAcquiredRead :: IO RWLock
-- | Create a new RWLock in the "write" state; either acquiring read
-- or write will block.
newAcquiredWrite :: IO RWLock
-- | Acquire the read lock.
--
-- Blocks if another thread has acquired write access. If
-- acquireRead terminates without throwing an exception the
-- state of the RWLock will be "read".
--
-- Implementation note: Throws an exception when more than (maxBound ::
-- Int) simultaneous threads acquire the read lock. But that is unlikely.
acquireRead :: RWLock -> IO ()
-- | Release the read lock.
--
-- If the calling thread was the last one to relinquish read access the
-- state will revert to "free".
--
-- It is an error to release read access to an RWLock which is not
-- in the "read" state.
releaseRead :: RWLock -> IO ()
-- | A convenience function wich first acquires read access and then
-- performs the computation. When the computation terminates, whether
-- normally or by raising an exception, the read lock is released.
withRead :: RWLock -> IO α -> IO α
-- |
-- - When the state is "write", waitRead blocks until a
-- call to releaseWrite in another thread changes the state to
-- "free".
-- - When the state is "free" or "read" waitRead returns
-- immediately.
--
--
-- waitRead does not alter the state of the lock.
--
-- Note that waitRead is just a convenience function defined as:
--
--
-- waitRead l = block $ acquireRead l >> releaseRead l
--
waitRead :: RWLock -> IO ()
-- | Try to acquire the read lock; non blocking.
--
-- Like acquireRead, but doesn't block. Returns True if the
-- resulting state is "read", False otherwise.
tryAcquireRead :: RWLock -> IO Bool
-- | A non-blocking withRead. First tries to acquire the lock. If
-- that fails, Nothing is returned. If it succeeds, the
-- computation is performed. When the computation terminates, whether
-- normally or by raising an exception, the lock is released and
-- Just the result of the computation is returned.
tryWithRead :: RWLock -> IO α -> IO (Maybe α)
-- | Acquire the write lock.
--
-- Blocks if another thread has acquired either read or write access. If
-- acquireWrite terminates without throwing an exception the
-- state of the RWLock will be "write".
acquireWrite :: RWLock -> IO ()
-- | Release the write lock.
--
-- If releaseWrite terminates without throwing an exception the
-- state will be "free".
--
-- It is an error to release write access to an RWLock which is
-- not in the "write" state.
releaseWrite :: RWLock -> IO ()
-- | A convenience function wich first acquires write access and then
-- performs the computation. When the computation terminates, whether
-- normally or by raising an exception, the write lock is released.
withWrite :: RWLock -> IO α -> IO α
-- |
-- - When the state is "write" or "read" waitWrite
-- blocks until a call to releaseWrite or
-- releaseRead in another thread changes the state to "free".
-- - When the state is "free" waitWrite returns
-- immediately.
--
--
-- waitWrite does not alter the state of the lock.
--
-- Note that waitWrite is just a convenience function defined
-- as:
--
--
-- waitWrite l = block $ acquireWrite l >> releaseWrite l
--
waitWrite :: RWLock -> IO ()
-- | Try to acquire the write lock; non blocking.
--
-- Like acquireWrite, but doesn't block. Returns True if
-- the resulting state is "write", False otherwise.
tryAcquireWrite :: RWLock -> IO Bool
-- | A non-blocking withWrite. First tries to acquire the lock. If
-- that fails, Nothing is returned. If it succeeds, the
-- computation is performed. When the computation terminates, whether
-- normally or by raising an exception, the lock is released and
-- Just the result of the computation is returned.
tryWithWrite :: RWLock -> IO α -> IO (Maybe α)
instance Typeable RWLock
instance Eq RWLock
-- | Concurrent read, sequential write variables. Comparable to an
-- IORef with more advanced synchronization mechanisms. The value
-- stored inside the RWVar can be read and used by multiple
-- threads at the same time. Concurrent computations inside a with
-- "block" observe the same value.
--
-- Observing and changing the contents of an RWVar are mutually
-- exclusive. The with function will block if modify is
-- active and vice-versa. Furthermore with is fully sequential and
-- will also block on concurrent calls of with.
--
-- The following are guaranteed deadlocks:
--
--
--
-- All functions are exception safe. Throwing asynchronous
-- exceptions will not compromise the internal state of an RWVar.
-- This also means that threads blocking on with or modify
-- and friends can still be unblocked by throwing an asynchronous
-- exception.
--
-- This module is designed to be imported qualified. We suggest importing
-- it like:
--
--
-- import Control.Concurrent.ReadWriteVar ( RWVar )
-- import qualified Control.Concurrent.ReadWriteVar as RWV ( ... )
--
module Control.Concurrent.ReadWriteVar
-- | Concurrently readable and sequentially writable variable.
data RWVar α
-- | Create a new RWVar.
new :: α -> IO (RWVar α)
-- | Execute an action that operates on the contents of the RWVar.
--
-- The action is guaranteed to have a consistent view of the stored
-- value. Any function that attempts to modify the contents will
-- block until the action is completed.
--
-- If another thread is modifying the contents of the RWVar this
-- function will block until the other thread finishes its action.
with :: RWVar α -> (α -> IO β) -> IO β
-- | Like with but doesn't block. Returns Just the result if
-- read access could be acquired without blocking, Nothing
-- otherwise.
tryWith :: RWVar α -> (α -> IO β) -> IO (Maybe β)
-- | Modify the contents of an RWVar.
--
-- This function needs exclusive write access to the RWVar. Only
-- one thread can modify an RWVar at the same time. All others
-- will block.
modify_ :: RWVar α -> (α -> IO α) -> IO ()
-- | Modify the contents of an RWVar and return an additional value.
--
-- Like modify_, but allows a value to be returned (β) in addition
-- to the modified value of the RWVar.
modify :: RWVar α -> (α -> IO (α, β)) -> IO β
-- | Attempt to modify the contents of an RWVar.
--
-- Like modify_, but doesn't block. Returns True if the
-- contents could be replaced, False otherwise.
tryModify_ :: RWVar α -> (α -> IO α) -> IO Bool
-- | Attempt to modify the contents of an RWVar and return an
-- additional value.
--
-- Like modify, but doesn't block. Returns Just the
-- additional value if the contents could be replaced, Nothing
-- otherwise.
tryModify :: RWVar α -> (α -> IO (α, β)) -> IO (Maybe β)
instance Typeable1 RWVar
instance Eq (RWVar α)