Qore Programming Language Reference Manual  1.8.0
Qore::Thread::RWLock Class Reference

The RWLock class implements a read-write thread lock. More...

Inheritance diagram for Qore::Thread::RWLock:

Public Member Methods

 constructor ()
 Creates the RWLock object. More...
 
 copy ()
 Creates a new RWLock object, not based on the original. More...
 
 destructor ()
 Destroys the RWLock object. More...
 
int getReadWaiting ()
 Returns the number of threads waiting on the read lock. More...
 
int getWriteWaiting ()
 Returns the number of threads waiting on the write lock. More...
 
bool lockOwner ()
 Returns True if the current thread is holding either the read lock or the write lock, False if not. More...
 
int numReaders ()
 Returns the read lock count. More...
 
nothing readLock ()
 Acquires the read lock; blocks if the write lock is already acquired by another thread. More...
 
int readLock (timeout timeout_ms)
 Acquires the read lock with a timeout value; blocks if the write lock is already acquired by another thread. More...
 
bool readLockOwner ()
 Returns True if the current thread is holding the read lock, False if not. More...
 
nothing readUnlock ()
 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. More...
 
int tryReadLock ()
 Acquires the read lock only if it can be acquired immediately. More...
 
int tryWriteLock ()
 Acquires the write lock only if it can be acquired immediately. More...
 
int writeLock (timeout timeout_ms)
 Acquires the write lock with a timeout value; blocks if the read lock is already acquired by another thread. More...
 
nothing writeLock ()
 Acquires the write lock; blocks if the read lock is already acquired by another thread. More...
 
bool writeLockOwner ()
 Returns True if the current thread is holding the write lock, False if not. More...
 
nothing writeUnlock ()
 Releases the write lock, if any readers are waiting, wakes up all readers, otherwise if any writers are waiting, then wakes one up. More...
 
- Public Member Methods inherited from Qore::Thread::AbstractSmartLock
 constructor ()
 Throws an exception if called directly; this class can only be instantiated by builtin subclasses. More...
 
string getName ()
 Returns the name of the threading class directly inheriting this class. More...
 
bool lockOwner ()
 Returns True if the calling thread owns the lock, False if not. More...
 
int lockTID ()
 Returns the TID of the thread owning the lock or -1 if the lock is currently not acquired. More...
 

Detailed Description

The RWLock class implements a read-write thread lock.

Restrictions:
Qore::PO_NO_THREAD_CLASSES
Overview
This class inherits AbstractSmartLock, so it can be used by Condition objects, while using either the read lock or the write lock.

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
}
Thread Resource Handling
The RWLock class manages the lock as a thread resource; if the lock is not released when the thread exits (or when Qore::throw_thread_resource_exceptions() or Qore::throw_thread_resource_exceptions_to_mark() is called), the any read or write locks held are released automatically and a LOCK-ERROR exception is thrown describing the situation.

Being an builtin class, the RWLock class does not inherit AbstractThreadResource explicitly as a part of the exported API, and the internal AbstractThreadResource::cleanup() method cannot be overridden or suppressed.
Note
This class is not available with the PO_NO_THREAD_CLASSES parse option.

Member Function Documentation

◆ constructor()

Qore::Thread::RWLock::constructor ( )

Creates the RWLock object.

Example:
RWLock rwl();

◆ copy()

Qore::Thread::RWLock::copy ( )

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

Example:
RWLock new_rwl = rwl.copy();

◆ destructor()

Qore::Thread::RWLock::destructor ( )

Destroys the RWLock 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.

Example:
delete rwl;
Exceptions
LOCK-ERRORObject deleted while other threads blocked on it

◆ getReadWaiting()

int Qore::Thread::RWLock::getReadWaiting ( )

Returns the number of threads waiting on the read lock.

Returns
the number of threads waiting on the read lock
Code Flags:
CONSTANT
Example:
int num = rwl.getReadWaiting();

◆ getWriteWaiting()

int Qore::Thread::RWLock::getWriteWaiting ( )

Returns the number of threads waiting on the write lock.

Returns
the number of threads waiting on the write lock
Code Flags:
CONSTANT
Example:
int num = rwl.getWriteWaiting();

◆ lockOwner()

bool Qore::Thread::RWLock::lockOwner ( )

Returns True if the current thread is holding either the read lock or the write lock, False if not.

Returns
True if the current thread is holding either the read lock or the write lock, False if not
Code Flags:
CONSTANT
Example:
if (rwl.lockOwner())
printf("TID %d has either the read lock or the write lock\n", q_gettid());
string printf(string fmt,...)
Outputs the string passed to standard output, using the first argument as a format string; does not e...

◆ numReaders()

int Qore::Thread::RWLock::numReaders ( )

Returns the read lock count.

Returns
the read lock count
Code Flags:
CONSTANT
Example:
int num = rwl.numReaders();

◆ readLock() [1/2]

nothing Qore::Thread::RWLock::readLock ( )

Acquires the read lock; blocks if the write lock is already acquired by another thread.

Example:
rwl.readLock();
Exceptions
THREAD-DEADLOCKA deadlock was detected while trying to acquire the lock
LOCK-ERRORRWLock::readLock() called while already holding the write lock, object deleted in another thread, etc.

◆ readLock() [2/2]

int Qore::Thread::RWLock::readLock ( timeout  timeout_ms)

Acquires the read lock with a timeout value; blocks if the write lock is already acquired by another thread.

Returns 0 for success, non-zero for timeout; exceptions are thrown for other errors

Parameters
timeout_msa timeout value to wait to acquire the read lock; integers are interpreted as milliseconds; relative date/time values are interpreted literally (with a resolution of milliseconds); negative timeouts mean wait indefinitely
Returns
0 for success, non-zero for timeout; exceptions are thrown for other errors
Example:
if (rwl.readLock(1500ms))
throw "TIMEOUT", "timed out after 1.5s waiting for the read lock";
Exceptions
THREAD-DEADLOCKA deadlock was detected while trying to acquire the lock
LOCK-ERRORRWLock::readLock() called while already holding the write lock, object deleted in another thread, etc.

◆ readLockOwner()

bool Qore::Thread::RWLock::readLockOwner ( )

Returns True if the current thread is holding the read lock, False if not.

Returns
True if the current thread is holding the read lock, False if not
Code Flags:
CONSTANT
Example:
if (rwl.readLockOwner())
printf("TID %d has the read lock\n", q_gettid());

◆ readUnlock()

nothing Qore::Thread::RWLock::readUnlock ( )

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.

Example:
rwl.readUnlock();
Exceptions
LOCK-ERRORRWLock::readUnlock() called while not holding the read lock, object deleted in another thread, etc

◆ tryReadLock()

int Qore::Thread::RWLock::tryReadLock ( )

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 (write lock owned by another thread) or an error occured
Example:
if (!rwl.tryReadLock()) {
on_exit rwl.readUnlock();
do_something_in_read_lock();
}

◆ tryWriteLock()

int Qore::Thread::RWLock::tryWriteLock ( )

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 (read lock owned by another thread) or an error occured
Example:
if (!rwl.tryWriteLock()) {
on_exit rwl.writeUnlock();
do_something_in_write_lock();
}

◆ writeLock() [1/2]

nothing Qore::Thread::RWLock::writeLock ( )

Acquires the write lock; blocks if the read lock is already acquired by another thread.

Example:
rwl.writeLock();
Exceptions
THREAD-DEADLOCKA deadlock was detected while trying to acquire the lock
LOCK-ERRORRWLock::writeLock() called while already holding the read lock, object deleted in another thread, etc.

◆ writeLock() [2/2]

int Qore::Thread::RWLock::writeLock ( timeout  timeout_ms)

Acquires the write lock with a timeout value; blocks if the read lock is already acquired by another thread.

Returns 0 for success, non-zero for timeout; exceptions are thrown for other errors

Parameters
timeout_msa timeout value to wait to acquire the write lock; integers are interpreted as milliseconds; relative date/time values are interpreted literally (with a resolution of milliseconds); negative timeouts mean wait indefinitely
Returns
0 for success, non-zero for timeout; exceptions are thrown for other errors
Example:
if (rwl.writeLock(1500ms))
throw "TIMEOUT", "timed out after 1.5s waiting for the write lock";
Exceptions
THREAD-DEADLOCKA deadlock was detected while trying to acquire the lock
LOCK-ERRORRWLock::writeLock() called while already holding the read lock, object deleted in another thread, etc.

◆ writeLockOwner()

bool Qore::Thread::RWLock::writeLockOwner ( )

Returns True if the current thread is holding the write lock, False if not.

Returns
True if the current thread is holding the write lock, False if not
Code Flags:
CONSTANT
Example:
if (rwl.writeLockOwner())
printf("TID %d has the write lock\n", q_gettid());

◆ writeUnlock()

nothing Qore::Thread::RWLock::writeUnlock ( )

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

Example:
rwl.writeUnlock();
Exceptions
LOCK-ERRORRWLock::writeUnlock() called while not holding the write lock, object deleted in another thread, etc