Copyright | (c) 2010-2011 Bas van Dijk & Roel van Dijk |
---|---|
License | BSD3 (see the file LICENSE) |
Maintainer | Bas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> |
Safe Haskell | Safe |
Language | Haskell98 |
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 ( ... )
Documentation
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.
Creating reentrant locks
newAcquired :: IO RLock Source #
Create a reentrant lock in the "locked" state (with the current thread as owner and an acquired count of 1).
Locking and unlocking
acquire :: RLock -> IO () Source #
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 calledacquire
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 onacquire
, and the lock is released, only one thread will be woken up. The runtime guarantees that the woken thread completes itsacquire
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.)
release :: RLock -> IO () Source #
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.
Convenience functions
tryWith :: RLock -> IO a -> IO (Maybe a) Source #
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.