Module lock

A mutex is a binary semaphore. A mutex can be created by the predicates mutex_new/1 and unslotted_new/2. A mutex need not be explicitly destroyed, it will automatically be reclaimed by the Java GC when not anymore used. To balance acquires and releases of the same semaphore the use of setup_call_cleanup/3 is recommended. Threads waiting for a sema-phore can be interrupted.

Example:
?- mutex_new(M), lock_acquire(M), lock_release(M), lock_acquire(M).
M = 0r3f10bc2a

The predicates lock_acquire/1 and lock_attempt/[1,2] allow incrementing a semaphore by one. These predicates will block, fail or timeout when the semaphore has already reached its maximum by other threads. The predicate lock_release/1 allows decrementing the semaphore by one, provided it is not already zero. The slotted versions check that the owner doesn’t change, but currently do not allow re-entrancy.

A read write pair can be created by the predicates lock_new/1 and nonescalable_new/1. In the non-escalable version the non-binary read semaphore can be retrieved by the predicate get_read/2 and it can be incremented provided the write semaphore is zero. The binary write semaphore can be retrieved by the predicate get_write/2 and it can be incremented provided the read semaphore is zero.

For the escalated version of the read write pair it is also allowed that the same thread holds a read and a write lock from a read write pair. This can for example be used to upgrade or downgrade a read write pair by using unbalanced locking. For example if a thread already holds a write lock, it can acquire the read lock and then release the write lock. The result is that the write lock was changed into a read lock.

The following lock predicates are provided:

mutex_new(M):
The predicate succeeds for a new slotted mutex M.
unslotted_new(M):
The predicate succeeds for a new unslotted mutex M.
lock_aquire(L):
The predicate succeeds after locking the lock L.
lock_attempt(L):
The predicate succeeds after locking the lock L. Otherwise the predicate fails.
lock_attempt(L, T):
The predicate succeeds after locking the lock L in the timeout T. Otherwise the predicate fails.
lock_release(L):
The predicate succeeds after unlocking the lock L.
lock_new(P):
The predicate succeeds for a new slotted and escalable read write pair P.
nonescalable_new(P):
The predicate succeeds for a new unslotted and non-escalable read write pair P.
get_read(P, R):
The predicate succeeds for the read lock R of the read write pair P.
get_write(P, W):
The predicate succeeds for the write lock W of the read write pair P.

Kommentare