c++-gtk-utils
Classes | Public Member Functions | List of all members
Cgu::Thread::RWLock Class Reference

A wrapper class for pthread read-write locks. More...

#include <c++-gtk-utils/rw_lock.h>

Classes

class  ReaderLock
 A scoped locking class for exception safe RWLock read locking. More...
 
class  ReaderTrackLock
 A scoped locking class for exception safe RWLock read locking which tracks the status of its read-write lock. More...
 
class  WriterLock
 A scoped locking class for exception safe RWLock write locking. More...
 
class  WriterTrackLock
 A scoped locking class for exception safe RWLock write locking which tracks the status of its read-write lock.. More...
 

Public Member Functions

 RWLock (const RWLock &)=delete
 
RWLockoperator= (const RWLock &)=delete
 
int reader_lock () noexcept
 
int reader_trylock () noexcept
 
int writer_lock () noexcept
 
int writer_trylock () noexcept
 
int unlock () noexcept
 
 RWLock ()
 
 ~RWLock ()
 

Detailed Description

A wrapper class for pthread read-write locks.

See also
Thread::Thread Thread::RWLock::ReaderLock Thread::RWLock::ReaderTrackLock Thread::RWLock::WriterLock Thread::RWLock::WriterTrackLock Thread::Mutex

This class can be used interchangeably with threads started with GThread and by this library, as both glib and this library use pthreads underneath on POSIX and other unix-like OSes. It can also in practice be used interchangeably with those started by C++11/14 std::thread, as in C++11/14 on unix-like OSes these facilities will be built on top of pthreads (for which purpose C++11/14 provides the std::native_handle_type type and std::thread::native_handle() function), or if they are not, they will use the same threading primitives provided by the kernel.

RWLock objects can be constructed statically as well as dynamically and there is no need to call g_thread_init() before they are constructed, even if glib < 2.32 is used. (If created as a static object in global scope, it will not be possible to catch Thread::RWLockError thrown by its constructor, but if a static global read-write lock throws there is nothing that could be done anyway except abort, and it would show that the pthreads installation is seriously defective.)

Read-write locks are similar to mutexes except that they allow more than one thread to hold the lock for reading at once. This can offer advantages over a mutex where a particular shared object is thread safe for lock-free reading by multiple threads simultaneously, is frequently read by different threads and is not often modified. However, the implementation of a read-write lock is more complex than that of a mutex, and unless the particular pthread read-write lock scheduling implementation favours already-blocking writers over later readers whenever a read-write lock object is unlocked, writer starvation can occur. Unless all the reads are of significant duration, might cause (if protected by a mutex) significant contention between each other and greatly exceed the number of times the write lock is held, then it is usually better to use an ordinary mutex.

Constructor & Destructor Documentation

◆ RWLock() [1/2]

Cgu::Thread::RWLock::RWLock ( const RWLock )
delete

This class cannot be copied. The copy constructor is deleted.

◆ RWLock() [2/2]

Cgu::Thread::RWLock::RWLock ( )
inline

Initialises the pthread read-write lock. It is not a cancellation point.

Exceptions
Cgu::Thread::RWLockErrorThrows this exception if initialisation of the read-write lock fails. (It is often not worth checking for this, as it means either memory is exhausted or pthread has run out of other resources to create new read-write locks.)

◆ ~RWLock()

Cgu::Thread::RWLock::~RWLock ( )
inline

Destroys the pthread read-write lock. It is not a cancellation point. It does not throw.

Member Function Documentation

◆ operator=()

RWLock& Cgu::Thread::RWLock::operator= ( const RWLock )
delete

This class cannot be copied. The assignment operator is deleted.

◆ reader_lock()

int Cgu::Thread::RWLock::reader_lock ( )
inlinenoexcept

Locks the read-write lock for reading. Blocks if already locked for writing until it becomes free. More than one thread may simultaneously hold a read lock, and a thread may lock for reading recursively provided that each call to this method is matched by a call to unlock(). It is not a cancellation point. It does not throw. It is thread safe.

Returns
0 if successful, otherwise the pthread read-write lock error number.
Note
With this library implementation, the only pthread error numbers which could be returned by this method are EDEADLK and EAGAIN. EDEADLK would be returned if the default pthread reader lock behaviour happens to return that error rather than deadlock where the thread calling this method already holds a write lock on this read-write lock. Most default implementations do not do this (they just deadlock) and hence the return value is usually not worth checking for except during debugging. EAGAIN would be returned if the maximum number of read locks for this read-write lock has been reached. Usually this number is at or around INT_MAX so it is also not usually useful to check for it except during debugging.

◆ reader_trylock()

int Cgu::Thread::RWLock::reader_trylock ( )
inlinenoexcept

Tries to lock the read-write lock for reading, but returns immediately with value EBUSY if it is already locked for writing. More than one thread may simultaneously hold a read lock, and a thread may lock for reading recursively provided that each successful call to this method is matched by a call to unlock(). It is not a cancellation point. It does not throw. It is thread safe.

Returns
0 if successful, otherwise EBUSY or other pthread read-write lock error number.
Note
With this library implementation, apart from EBUSY, the only other pthread error number which could be returned by this method is EAGAIN, which would be returned if the maximum number of read locks for this read-write lock has been reached. Usually this number is at or around INT_MAX so it is not usually useful to check for it except during debugging.

◆ unlock()

int Cgu::Thread::RWLock::unlock ( )
inlinenoexcept

Unlocks a read-write lock previously locked for reading or writing by the calling thread. If the calling thread has locked the read-write lock for writing, it relinquishes ownership. If it has previously locked the read-write lock for reading, it releases that particular lock, but the read-write lock may remain locked for reading if it has been locked for reading recursively or other threads hold a read lock and the particular implementation does not provide writer priority. It is not a cancellation point. It does not throw.

Returns
0 if successful, otherwise the pthread read-write lock error number.
Note
With this library implementation, the only pthread error number which could be returned by this method is EPERM because the calling thread does hold a lock on this read-write lock (however POSIX does not require that return value in that case and hence the return value is usually not worth checking for except during debugging).

◆ writer_lock()

int Cgu::Thread::RWLock::writer_lock ( )
inlinenoexcept

Locks the read-write lock for writing and acquires ownership. Blocks if already locked for reading or writing until it becomes free. It is not a cancellation point. It does not throw. It is thread safe.

Returns
0 if successful, otherwise the pthread read-write lock error number.
Note
With this library implementation, the only pthread error number which could be returned by this method is EDEADLK, which it would do if the default pthread reader lock behaviour happens to return that error rather than deadlock where the thread calling this method already holds a read lock or write lock on this read-write lock. Most default implementations do not do this (they just deadlock) and hence the return value is usually not worth checking for except during debugging.

◆ writer_trylock()

int Cgu::Thread::RWLock::writer_trylock ( )
inlinenoexcept

Tries to lock the read-write lock for writing and acquire ownership, but returns immediately with value EBUSY if it is already locked for reading or writing. It is not a cancellation point. It does not throw. It is thread safe.

Returns
0 if successful, otherwise EBUSY.
Note
With this library implementation, the only pthread error number which could be returned by this method is EBUSY.

The documentation for this class was generated from the following file: