Control.Concurrent.Lock

concurrent-extra-0.7.0.6: Extra concurrency primitives

Maintainer | Bas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com>
Safe Haskell | Safe

Control.Concurrent.Lock

Contents

- Creating locks
- Locking and unlocking
- Convenience functions
- Querying locks

Description

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 ( ... )

Synopsis

- data Lock
- new :: IO Lock
- newAcquired :: IO Lock
- acquire :: Lock -> IO ()
- tryAcquire :: Lock -> IO Bool
- release :: Lock -> IO ()
- with :: Lock -> IO a -> IO a
- tryWith :: Lock -> IO α -> IO (Maybe α)
- wait :: Lock -> IO ()
- locked :: Lock -> IO Bool

# Documentation

data Lock

A lock is in one of two states: "locked" or "unlocked".

Instances

Eq Lock |
Typeable Lock |

# Creating locks

new :: IO Lock

Create a lock in the "unlocked" state.

newAcquired :: IO Lock

Create a lock in the "locked" state.

# Locking and unlocking

acquire :: Lock -> IO ()

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.)

tryAcquire :: Lock -> IO Bool

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`.

release :: Lock -> IO ()

`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.

# Convenience functions

with :: Lock -> IO a -> IO a

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``.

tryWith :: Lock -> IO α -> IO (Maybe α)

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.

wait :: Lock -> IO ()

- 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 we can be defined as:

    wait l = block $ acquire l >> release l

# Querying locks

locked :: Lock -> IO Bool

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.