úÎbá[ÊU      !"#$%&'()*+,-./01234 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T XBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> KA broadcast variable. It can be thought of as a box, which may be empty of  full. UVCreate a new empty  variable.  Create a new ' variable containing an initial value. Read the value of a  variable. If the < variable contains a value it will be returned immediately, -otherwise it will retry until another thread s a value to the   variable. Try to read the value of a  variable; non blocking. Like  but doesn't retry. Returns W the contents of the  if it wasn' t empty, X otherwise. Write a new value into a  variable. PIf the variable is empty any threads that are reading from the variable will be Hwoken. If the variable is full its contents will simply be overwritten. Clear the contents of a  variable. XBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> +An event is in one of two possible states: "Set" or "Cleared". YZCreate an event in the "Cleared" state. Create an event in the "Set" state. Retry until the event is  . %If the state of the event is already "Set" this function will return A immediately. Otherwise it will retry until another thread calls  . "Changes the state of the event to "Set"%. All threads that where waiting for $ this event are woken. Threads that   after the state is changed to "Set"  will not retry. "Changes the state of the event to "Cleared". Threads that   after the  state is changed to "Cleared"* will retry until the state is changed to "Set".    XBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com>Like [, but not bounded by an \. KSuspends the current thread for a given number of microseconds (GHC only). LThere is no guarantee that the thread will be rescheduled promptly when the Jdelay has expired, but the thread will never continue to run earlier than  specified. XBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com>]^Like _, but not bounded by an \. Wrap an `$ computation to time out and return X in case no result is available within n microseconds (1/10^6 seconds). In case a result is &available before the timeout expires, W 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 a# it would have without the timeout wrapper. Any exceptions f6 might throw cancel the timeout and propagate further up. It also possible for f/ to receive exceptions thrown to it by another thread. BA tricky implementation detail is the question of how to abort an ` Pcomputation. This combinator relies on asynchronous exceptions internally. The Ktechnique works very well for computations executing inside of the Haskell runtime system, but it doesn',t work at all for non-Haskell code. Foreign Mfunction calls, for example, cannot be timed out with this combinator simply Mbecause an arbitrary C function cannot receive asynchronous exceptions. When timeoutB is used to wrap an FFI call that blocks, no timeout event can be Odelivered until the FFI call returns, which pretty much negates the purpose of Qthe combinator. In practice, however, this limitation is less severe than it may sound. Standard I/O functions like b, c, Network.Socket.accept, or d 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.  efghefghefghXBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> KA broadcast variable. It can be thought of as a box, which may be empty of  full. ijCreate a new empty  variable.  Create a new ' variable containing an initial value. Read the value of a  variable. If the < variable contains a value it will be returned immediately, -otherwise it will block until another thread s a value to the   variable. Try to read the value of a  variable; non blocking. Like  but doesn't block. Returns W the contents of the  if it wasn' t empty, X otherwise. Read the value of a , variable if it is available within a given amount of time. Like (, but with a timeout. A return value of X indicates a timeout  occurred. :The timeout is specified in microseconds. A timeout of 0 ¼ s will cause the function to return X without blocking in case the  was @empty. Negative timeouts are treated the same as a timeout of 0 ¼s. Write a new value into a  variable. PIf the variable is empty any threads that are reading from the variable will be Hwoken. If the variable is full its contents will simply be overwritten. Clear the contents of a  variable. kXBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> A 8 is an abstract type representing a handle to a thread.  is an instance of l, m and n , where the m instance implements an arbitrary total ordering over s. The n instance lets you convert an arbitrary-valued  to string form; showing a  value is Ooccasionally useful when debugging or diagnosing the behaviour of a concurrent  program. Note: This is a wrapper around o. pqExtract the underlying o. r+Internally used function which generalises  and . Parametrised /by the function which does the actual forking. )Sparks off a new thread to run the given ` computation and returns the  of the newly created thread. JThe new thread will be a lightweight thread; if you want to use a foreign ,library that uses thread-local storage, use  instead. GGHC note: the new thread inherits the blocked state of the parent (see s). OThe newly created thread has an exception handler that discards the exceptions BlockedOnDeadMVar, BlockedIndefinitely, and  ThreadKilled, and passes all 8other exceptions to the uncaught exception handler (see setUncaughtExceptionHandler). Like 0, this sparks off a new thread to run the given ` computation and returns the  of the newly created thread. Unlike ,  creates a bound# thread, which is necessary if you Kneed to call foreign (non-Haskell) libraries that make use of thread-local state, such as OpenGL (see Control.Concurrent). Using  instead of . makes no difference at all to the scheduling Obehaviour of the Haskell runtime system. It is a common misconception that you  need to use  instead of # to avoid blocking all the Haskell ,threads when making a foreign call; this isn'#t the case. To allow foreign calls Kto 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. ,Block until the given thread is terminated. Returns X& if the thread terminated normally or W e if the  exception e" was thrown in the thread and wasn' t caught. EBlock until the given thread is terminated or until a timer expires. Returns X if a timeout occurred or W the result  would return 4when the thread finished within the specified time. *The timeout is specified in microseconds. Returns True+ if the given thread is currently running. 9Notice that this observation is only a snapshot of thread's state. By the time a <program reacts on its result it may already be out of date. B terminates the given thread (GHC only). Any work already done by the thread isn'?t lost: the computation is suspended until required by another Ithread. The memory used by the thread will be garbage collected if it isn't referenced from anywhere. The ! function is defined in terms of !. QThis function blocks until the target thread is terminated. It is a no-op if the %target thread has already completed. Like  but with a timeout. Returns True if the target thread was -terminated without the given amount of time, False otherwise. *The timeout is specified in microseconds. QNote that even when a timeout occurs, the target thread can still terminate at a 8later time as a direct result of calling this function. !!@ raises an arbitrary exception in the target thread (GHC only). !C does not return until the exception has been raised in the target Jthread. The calling thread can thus be certain that the target thread has Qreceived the exception. This is a useful property to know when dealing with race Iconditions: eg. if there are two threads that can kill each other, it is Dguaranteed that only one of the threads will get to kill the other. QIf the target thread is currently making a foreign call, then the exception will not be raised (and hence !% will not return) until the call has Gcompleted. This is the case regardless of whether the call is inside a s or not. !Important note: the behaviour of !$ differs from that described in the paper ""Asynchronous exceptions in Haskell" ( =http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm). In the paper, !? is non-blocking; but the library implementation adopts a more synchronous design in which !( does not return until the exception is Nreceived by the target thread. The trade-off is discussed in Section 9 of the $paper. Like any blocking operation, !! is therefore interruptible (see Section 5.3 of the paper). @There is currently no guarantee that the exception delivered by ! will Lbe delivered at the first possible opportunity. In particular, a thread may t and then re-s( exceptions without receiving a pending !*. This is arguably undesirable behaviour.  !  !  !XBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> "+An event is in one of two possible states: "Set" or "Cleared". uv#Create an event in the "Cleared" state. $Create an event in the "Set" state. %Block until the event is '. %If the state of the event is already "Set" this function will return @immediately. Otherwise it will block until another thread calls '. GYou can also stop a thread that is waiting for an event by throwing an asynchronous exception. &Block until the event is ' or until a timer expires. Like %(, but with a timeout. A return value of w indicates a timeout  occurred. 9The timeout is specified in microseconds. A timeout of 0 ¼s will cause the function to return w- without blocking in case the event state is "Cleared";. Negative timeouts are treated the same as a timeout of 0 ¼s. '"Changes the state of the event to "Set"!. All threads that where waiting 'for this event are woken. Threads that % after the state is changed to "Set" will not block at all. ("Changes the state of the event to "Cleared". Threads that % after the state is changed to "Cleared"* will block until the state is changed to "Set". )Returns x if the state of the event is "Set" and w if the state is "Cleared". ONotice 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. "#$%&'()"#$%&'()"#$%&'()XBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> * A lock is in one of two states: "locked" or "unlocked". yz+Create a lock in the "unlocked" state. ,Create a lock in the "locked" state. - Acquires the *,. Blocks if another thread has acquired the *. 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 / in Panother thread wakes the calling thread. Upon awakening it will change to state to "locked". .There are two further important properties of acquire:  acquireE is single-wakeup. That is, if there are multiple threads blocked on acquireA and the lock is released, only one thread will be woken up. The 7runtime guarantees that the woken thread completes its acquire operation. & When multiple threads are blocked on acquire, they are woken up in FIFO Norder. This is useful for providing fairness properties of abstractions built Nusing locks. (Note that this differs from the Python implementation where the wake-up order is undefined.) .A non-blocking -.  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. /release changes the state to "unlocked" and returns immediately. 2Note that it is an error to release a lock in the "unlocked" state! $If there are any threads blocked on - the thread that first called acquire will be woken up. 0KA convenience function which first acquires the lock and then performs the Pcomputation. When the computation terminates, whether normally or by raising an !exception, the lock is released.  Note that: with = { | - /. 1A non-blocking 0. tryWith0 is a convenience function which first tries to !acquire the lock. If that fails, X" is returned. If it succeeds, the Ocomputation is performed. When the computation terminates, whether normally or 2by raising an exception, the lock is released and W the result of the computation is returned. 2 When the state is "locked", wait blocks until a call to / 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 = s } - l ~ / l3!Determines if the lock is in the "locked" state. MNote 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. *+,-./0123 *+,-./0123 *+,-./0123 XBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> 4The state of an 5.  X indicates an "unlocked" state.  W (tid, n) indicates a "locked"& state where the thread identified by tid acquired the lock n times. 5*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. €6Create a reentrant lock in the "unlocked" state. 7Create a reentrant lock in the "locked"# state (with the current thread as #owner and an acquired count of 1). 8 Acquires the 5,. Blocks if another thread has acquired the 5. 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 acquireE 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:  acquireE is single-wakeup. That is, if there are multiple threads blocked on acquireB, and the lock is released, only one thread will be woken up. The 7runtime guarantees that the woken thread completes its acquire operation. & When multiple threads are blocked on acquire they are woken up in FIFO Norder. This is useful for providing fairness properties of abstractions built Nusing locks. (Note that this differs from the Python implementation where the wake-up order is undefined.) 9A non-blocking 8.  When the state is "unlocked"  tryAcquire changes the state to "locked" J(with the current thread as owner and an acquired count of 1) and returns x.  When the state is "locked"  tryAcquire leaves the state unchanged and returns w. :release@ decrements the acquired count. When a lock is released with an ,acquired count of 1 its state is changed to "unlocked". 7Note that it is both an error to release a lock in the "unlocked" state and to 8release a lock that is not owned by the current thread. $If there are any threads blocked on 8 the thread that first called acquire will be woken up. ;>A convenience function which first acquires the lock and then Cperforms the computation. When the computation terminates, whether ;normally or by raising an exception, the lock is released.  Note that: with = { | 8 :. <A non-blocking ;. tryWith0 is a convenience function which first tries to !acquire the lock. If that fails, X" is returned. If it succeeds, the Ocomputation is performed. When the computation terminates, whether normally or 2by raising an exception, the lock is released and W the result of the computation is returned. = When the state is "locked" wait blocks until a call to : 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 = s } 8 l ~ : l>+Determine the state of the reentrant lock. PNote 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. 456789:;<=> 56789:;<=4> 456789:;<=> XBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com>Internal state of the ?. ‚ƒ„?@Multiple-reader, single-writer lock. Is in one of three states:  "Free"9: Read or write access can be acquired without blocking.  "Read"F: One or more threads have acquired read access. Blocks write access.  "Write"B: A single thread has acquired write access. Blocks other threads +from acquiring both read and write access. …†‡ˆ@ Create a new ? in the "Free"( state; either read or write access can be acquired without blocking. A Create a new ? in the "Read"" state; only read can be acquired without blocking. B Create a new ? in the "Write"' state; either acquiring read or write  will block. CAcquire the read lock. 7Blocks if another thread has acquired write access. If  acquireRead terminates /without throwing an exception the state of the ? will be "Read". JImplementation note: Throws an exception when more than (maxBound :: Int) Bsimultaneous threads acquire the read lock. But that is unlikely. D,Try to acquire the read lock; non blocking. Like C , but doesn't block. Returns x if the resulting state is "Read", w otherwise. ERelease the read lock. PIf 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 ? which is not in the "Read" state. FMA convenience function wich first acquires read access and then performs the Pcomputation. When the computation terminates, whether normally or by raising an &exception, the read lock is released. GA non-blocking F2. First tries to acquire the lock. If that fails, XE is returned. If it succeeds, the computation is performed. When the Qcomputation terminates, whether normally or by raising an exception, the lock is  released and W, the result of the computation is returned. HAcquire the write lock. FBlocks if another thread has acquired either read or write access. If  acquireWrite; terminates without throwing an exception the state of the ? will be "Write". I-Try to acquire the write lock; non blocking. Like H , but doesn't block. Returns x if the resulting state is "Write", w otherwise. JRelease 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 ? which is not in the "Write" state. KJA convenience function wich first acquires write access and then performs Qthe computation. When the computation terminates, whether normally or by raising *an exception, the write lock is released. LA non-blocking K2. First tries to acquire the lock. If that fails, XE is returned. If it succeeds, the computation is performed. When the Qcomputation terminates, whether normally or by raising an exception, the lock is  released and W, the result of the computation is returned. ‰?@ABCDEFGHIJKL?@ABCEFDGHJKIL?@ABCDEFGHIJKL XBas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> M:Concurrently readable and sequentially writable variable. ŠN Create a new M. O7Execute an action that operates on the contents of the M. LThe action is guaranteed to have a consistent view of the stored value. Any function that attempts to R- the contents will block until the action is  completed. 3If another thread is modifying the contents of the M this function will 2block until the other thread finishes its action. PLike O but doesn't block. Returns W the result if read access $could be acquired without blocking, X otherwise. QModify the contents of an M. 2This function needs exclusive write access to the M. Only one thread can  modify an M* at the same time. All others will block. RModify the contents of an M! and return an additional value. Like Q%, but allows a value to be returned (²) in addition to the modified value of the M. S%Attempt to modify the contents of an M. Like Q , but doesn't block. Returns x if the contents could be  replaced, w otherwise. T%Attempt to modify the contents of an M! and return an additional value. Like R , but doesn't block. Returns W the additional value if the contents could be replaced, X otherwise. MNOPQRSTMNOPQRSTMNOPQRST‹   !"#$ %&'()*+, - .  & ' ( ) * +  / 0  1 2 3 4 5 6 7 8 9 : ; < =  * + > ? @ A BCDECDFGCHIJKLMMCNJKOCHPCQRCQSCQT U V W X BYCZ[CZ\C]^CH_`CabCacGJdeJdf%gChiCjkClmCln . g - o p q 0 / r s t =uconcurrent-extra-0.2 Control.Concurrent.STM.BroadcastControl.Concurrent.STM.EventControl.Concurrent.Thread.DelayControl.Concurrent.TimeoutControl.Concurrent.BroadcastControl.Concurrent.ThreadControl.Concurrent.EventControl.Concurrent.LockControl.Concurrent.RLock Control.Concurrent.ReadWriteLockControl.Concurrent.ReadWriteVarUtils Broadcastnew newWrittenreadtryReadwriteclearEventnewSetwaitsetisSetdelaytimeout readTimeoutThreadIdthreadIdforkIOforkOS waitTimeout isRunning killThreadkillThreadTimeoutthrowToLock newAcquiredacquire tryAcquirereleasewithtryWithlockedStateRLockstateRWLocknewAcquiredReadnewAcquiredWrite acquireReadtryAcquireRead releaseReadwithRead tryWithRead acquireWritetryAcquireWrite releaseWrite withWrite tryWithWriteRWVarmodify_modify tryModify_ tryModify unBroadcastbase Data.MaybeJustNothing evBroadcastGHC.Conc threadDelayghc-prim GHC.TypesIntTimeoutSystem.TimeoutIO myThreadIdGHC.IO.Handle.TexthGetBufhPutBuf hWaitForInputvoidpurelyModifyMVar modifyIORefM modifyIORefM_ deleteReader GHC.ClassesEqOrdGHC.ShowShowstoppedforkGHC.IOblockunblockGHC.BoolFalseTrueunControl.ApplicativeliftA2Control.Exception.Basebracket_GHC.Base$>>WriteReadFreereadLock writeLock moduleName