tmc::rw_lock#

class rw_lock#

An async reader-writer lock (a.k.a. std::shared_mutex). Any number of readers may hold the lock simultaneously, or one writer may hold it exclusively. Tasks that cannot acquire the lock immediately will suspend, and be resumed when the lock is transferred to them. All operations are implemented with lock-free atomics; no operation ever blocks or spins.

Phase-fair policy (neither readers nor writers can starve):

  • New readers can acquire the lock immediately only if no writer holds it and no writers are waiting. If a writer is waiting, new readers queue behind it.

  • When the last reader releases the lock, the longest-waiting writer is woken and the lock is transferred to it.

  • When a writer releases the lock, all currently-waiting readers are woken as a batch. If no readers are waiting, the next writer is woken instead.

The reader count, waiting reader count, and waiting writer count are each packed into (STATE_BITS - 2) / 3 bits of a single atomic word. When 64-bit atomics are available, a 64-bit word is used, so none of these may exceed 1048575. Otherwise, falls back to a size_t word; on a 32-bit platform that reduces each field to 10 bits (max 1023).

Public Functions

rw_lock() noexcept = default#

The lock begins in the fully unlocked state.

inline bool is_write_locked() noexcept#

Returns true if some task is holding the write lock. This value is not guaranteed to be consistent with any other operation.

inline size_t reader_count() noexcept#

Returns the number of tasks currently holding the read lock. This value is not guaranteed to be consistent with any other operation.

bool try_lock_read() noexcept#

Tries to acquire the read lock without suspending. Returns true on success. Returns false if a writer holds the lock or any writers are waiting. Not re-entrant.

bool try_lock_write() noexcept#

Tries to acquire the write lock without suspending. Returns true on success. Returns false if the lock is held in any mode. Not re-entrant.

inline aw_rw_lock_read lock_read() noexcept#

Tries to acquire the read lock. If a writer is holding or waiting for the lock, will suspend until the read lock can be acquired by this task. Multiple tasks may hold the read lock simultaneously. Not re-entrant.

inline aw_rw_lock_write lock_write() noexcept#

Tries to acquire the write lock. If the lock is held by any other task, will suspend until the write lock can be acquired exclusively by this task. Not re-entrant.

inline aw_rw_lock_read_scope lock_read_scope() noexcept#

Same as lock_read(), but returns an object that will release the read lock (and resume awaiters) when it goes out of scope. Not re-entrant.

inline aw_rw_lock_write_scope lock_write_scope() noexcept#

Same as lock_write(), but returns an object that will release the write lock (and resume awaiters) when it goes out of scope. Not re-entrant.

void unlock_read() noexcept#

Releases the read lock. If this was the last reader and writers are waiting, a writer will be resumed and the write lock will be transferred to it. Does not symmetric transfer; the awaiter will be posted to its executor.

void unlock_write() noexcept#

Releases the write lock. If readers are waiting, all of them will be resumed and the read lock will be transferred to them. Otherwise, if writers are waiting, one writer will be resumed and the write lock will be transferred to it. Does not symmetric transfer; awaiters will be posted to their executors.

~rw_lock()#

On destruction, any awaiters will be resumed.

class aw_rw_lock_read_scope : public tmc::aw_rw_lock_read_base#

Same as aw_rw_lock_read but returns a nodiscard rw_lock_read_scope that releases the read lock on destruction.

class aw_rw_lock_write_scope : public tmc::aw_rw_lock_write_base#

Same as aw_rw_lock_write but returns a nodiscard rw_lock_write_scope that releases the write lock on destruction.

class rw_lock_read_scope#

The read lock will be released when this goes out of scope.

Public Functions

~rw_lock_read_scope()#

Releases the read lock on destruction. Does not symmetric transfer.

class rw_lock_write_scope#

The write lock will be released when this goes out of scope.

Public Functions

~rw_lock_write_scope()#

Releases the write lock on destruction. Does not symmetric transfer.