4.25. Thread::RWLock Class

Note: This class is not available with the PO_NO_THREAD_CLASSES parse option.

The RWLock class implements a read-write lock for efficient thread locking when write actions must be atomic and reads can be made in parallel if no write is in progress. When a thread holds the write lock, no other thread can grab the read or write lock. Multiple threads can hold the read lock at one time.

As with all Qore threading primitives, this class supports deadlock detection and throws exceptions when threading errors are encountered (for example, trying to free the read lock while holding the write lock, etc).

This read-write lock favors readers, so the read lock can be safely acquired recursively.

See the AutoReadLock and the AutoWriteLock classes for classes that assist in exception-safe RWLock locking.

Additionally, the on_exit statement can provide exception-safe RWLock handling at the lexical block level as in the following example:

{
    $rwl.writeLock();
    on_exit
        $rwl.writeUnlock();

    # ... when this block exits the lock will be released, even in the
    #     case of return statements or exceptions
}

Table 4.920. RWLock Method Overview

Method

Except?

Description

RWLock::constructor()

N

Creates the RWLock object.

RWLock::destructor()

Y

Destroys the RWLock object.

RWLock::copy()

N

Creates a new RWLock object, not based on the original.

RWLock::readLock()

Y

Acquires the read lock with an optional timeout value; blocks if the write lock is already acquired.

RWLock::readUnlock()

Y

Decrements the read lock counter and releases the read lock if the counter is zero. If at least one thread is blocked trying to acquire the write lock and the read counter reaches zero, then one thread waiting on the write lock is woken up.

RWLock::writeLock()

Y

Acquires the write lock with an optional timeout; blocks if either the read lock or write lock is already acquired.

RWLock::writeUnlock()

Y

Releases the write lock, if any writers are waiting, then wakes one up, otherwise if any readers are waiting, wakes up all readers.

RWLock::tryReadLock()

N

Acquires the read lock only if it can be acquired immediately. Returns 0 for success (read lock acquired, read lock count incremented) or -1 if the call would block.

RWLock::tryWriteLock()

N

Acquires the write lock only if it can be acquired immediately. Returns 0 for success (write lock acquired) or -1 if the call would block.

RWLock::numReaders()

N

Returns the read lock count.

RWLock::getReadWaiting()

N

Returns the number of threads waiting on the read lock.

RWLock::getWriteWaiting()

N

Returns the number of threads waiting on the write lock.


4.25.1. RWLock::constructor()

Synopsis

Creates the RWLock object.

Usage
new RWLock()
Example
$rwl = new RWLock();

Table 4.921. Arguments for RWLock::constructor()

Argument

Type

Description

n/a

n/a

This method takes no arguments.


Table 4.922. Return Values for RWLock::constructor()

Return Type

Description

RWLock Object

The object created.


4.25.2. RWLock::destructor()

Synopsis

Destroys the object. Note that it is a programming error to delete this object while other threads are blocked on it; in this case an exception is thrown in the deleting thread, and in each thread blocked on this object when it is deleted.

Usage
delete lvalue
Example
delete $rwl;

Table 4.923. Exceptions Thrown by RWLock::destructor()

err

desc

LOCK-ERROR

Object deleted while other threads blocked on it.


4.25.3. RWLock::copy()

Synopsis

Creates a new RWLock object, not based on the original.

Usage
RWLock::copy()
Example
$new_rwl = $rwl.copy();

Table 4.924. Arguments for RWLock::copy()

Argument

Type

Description

n/a

n/a

This method takes no arguments.


Table 4.925. Return Values for RWLock::copy()

Return Type

Description

RWLock Object

A new RWLock object, not based on the original.


4.25.4. RWLock::readLock()

Synopsis

Acquires the read lock with an optional timeout value; blocks if the write lock is already acquired. The read lock may be acquired recursively, however, each call to RWLock::readLock() requires a corresponding call to RWLock::readUnlock(). An optional timeout value may be passed to this method, giving a time in milliseconds to wait for the lock to become free. Like all Qore functions and methods taking timeout values, a relative date/time value may be passed instead of an integer to make the timeout units clear.

Usage
RWLock::readLock([timeout_ms])
Example
$rwl.readLock();

Table 4.926. Arguments for RWLock::readLock()

Argument

Type

Description

[timeout_ms]

Integer or Relative Date/Time

If an argument is present, it is interpreted as a timeout in milliseconds. Note that it's recommended to use a relative time value (i.e. 250ms) to make the units clear in the source code.


Table 4.927. Return Values for RWLock::readLock()

Return Type

Description

Integer

0 for success, -1 for failure (only returned with a timeout)


Table 4.928. Exceptions Thrown by RWLock::readLock()

err

desc

THREAD-DEADLOCK

A deadlock was detected while trying to acquire the lock.

LOCK-ERROR

readLock() called while already holding the write lock, object deleted in another thread, etc.


4.25.5. RWLock::readUnlock()

Synopsis

Decrements the read lock counter and releases the read lock if the counter is zero. If at least one thread is blocked trying to acquire the write lock and the read counter reaches zero, then one thread waiting on the write lock is woken up.

Usage
RWLock::readUnlock()
Example
$rwl.readUnlock();

Table 4.929. Arguments for RWLock::readUnlock()

Argument

Type

Description

n/a

n/a

This method takes no arguments.


Table 4.930. Return Values for RWLock::readUnlock()

Return Type

Description

n/a

This method return no value.


Table 4.931. Exceptions Thrown by RWLock::readUnlock()

err

desc

LOCK-ERROR

readUnlock() called while not holding the read lock, object deleted in another thread, etc.


4.25.6. RWLock::writeLock()

Synopsis

Acquires the write lock; blocks if either the read lock or write lock is already acquired. An optional timeout value may be passed to this method, giving a time in milliseconds to wait for the lock to become free. Like all Qore functions and methods taking timeout values, a relative date/time value may be passed instead of an integer to make the timeout units clear.

To release the write lock, use RWLock::readUnlock().

Usage
RWLock::writeLock([timeout_ms])
Example
$rwl.writeLock();

Table 4.932. Arguments for RWLock::writeLock()

Argument

Type

Description

[timeout_ms]

Integer or Relative Time

If an argument is present, it is interpreted as a timeout in milliseconds. Note that it's recommended to use a relative time value (i.e. 250ms) to make the units clear in the source code.


Table 4.933. Return Values for RWLock::writeLock()

Return Type

Description

Integer

0 for lock acquired, -1 for timeout (only when a timeout argument is passed)


Table 4.934. Exceptions Thrown by RWLock::writeLock()

err

desc

THREAD-DEADLOCK

A deadlock was detected while trying to acquire the lock.

LOCK-ERROR

writeLock() called while holding the read lock, writeLock() called while already holding the write lock in the same thread, object deleted in another thread, etc.


4.25.7. RWLock::writeUnlock()

Synopsis

Releases the write lock, if any writers are waiting, then wakes one up, otherwise if any readers are waiting, wakes up all readers.

Usage
RWLock::writeUnlock()
Example
$rwl.writeUnlock();

Table 4.935. Arguments for RWLock::writeUnlock()

Argument

Type

Description

n/a

n/a

This method takes no arguments.


Table 4.936. Return Values for RWLock::writeUnlock()

Return Type

Description

n/a

This method return no value.


Table 4.937. Exceptions Thrown by RWLock::writeUnlock()

err

desc

LOCK-ERROR

writeUnlock() called while not holding the write lock, object deleted in another thread, etc.


4.25.8. RWLock::tryReadLock()

Synopsis

Acquires the read lock only if it can be acquired immediately, returns 0 for success, -1 if it would block.

Usage
RWLock::tryReadLock()
Example
$bool = $rwl.tryReadLock();

Table 4.938. Arguments for RWLock::writeUnlock()

Argument

Type

Description

n/a

n/a

This method takes no arguments.


Table 4.939. Return Values for RWLock::writeUnlock()

Return Type

Description

Integer

Returns 0 for success (read lock acquired, read lock count incremented) or -1 if the call would block.


4.25.9. RWLock::tryWriteLock()

Synopsis

Acquires the write lock only if it can be acquired immediately, returns 0 for success, -1 if it would block.

Usage
RWLock::tryWriteLock()
Example
$bool = $rwl.tryWriteLock();

Table 4.940. Arguments for RWLock::tryWriteLock()

Argument

Type

Description

n/a

n/a

This method takes no arguments.


Table 4.941. Return Values for RWLock::tryWriteLock()

Return Type

Description

Integer

Returns 0 for success (write lock acquired) or -1 if the call would block.


4.25.10. RWLock::numReaders()

Synopsis

Returns the read lock count.

Usage
RWLock::numReaders()
Example
$num = $rwl.numReaders();

Table 4.942. Arguments for RWLock::numReaders()

Argument

Type

Description

n/a

n/a

This method takes no arguments.


Table 4.943. Return Values for RWLock::numReaders()

Return Type

Description

Integer

The read lock count.


4.25.11. RWLock::getReadWaiting()

Synopsis

Returns the number of threads blocked on the read lock (only non-zero while the write lock is held).

Usage
RWLock::getReadWaiting()
Example
$num = $rwl.getReadWaiting();

Table 4.944. Arguments for RWLock::getReadWaiting()

Argument

Type

Description

n/a

n/a

This method takes no arguments.


Table 4.945. Return Values for RWLock::getReadWaiting()

Return Type

Description

Integer

The number of threads blocked on the read lock.


4.25.12. RWLock::getWriteWaiting()

Synopsis

Returns the number of threads blocked on the write lock.

Usage
RWLock::getWriteWaiting()
Example
$num = $rwl.getWriteWaiting();

Table 4.946. Arguments for RWLock::getWriteWaiting()

Argument

Type

Description

n/a

n/a

This method takes no arguments.


Table 4.947. Return Values for RWLock::getWriteWaiting()

Return Type

Description

Integer

The number of threads blocked on the write lock.