SpECTRE  v2025.08.19
Parallel::MultiReaderSpinlock Class Reference

A two-state spinlock that allows multiple readers of a shared resource to acquire the lock simultaneously. More...

#include <MultiReaderSpinlock.hpp>

Public Member Functions

 MultiReaderSpinlock (const MultiReaderSpinlock &)=delete
 
MultiReaderSpinlockoperator= (const MultiReaderSpinlock &)=delete
 
 MultiReaderSpinlock (MultiReaderSpinlock &&)=delete
 
MultiReaderSpinlockoperator= (MultiReaderSpinlock &&)=delete
 
void read_lock () noexcept
 Acquire the lock in a reader state. More...
 
void read_unlock () noexcept
 Release the lock from a reader state. More...
 
void write_lock () noexcept
 Acquire the lock in a writer state. More...
 
void write_unlock () noexcept
 Release the lock from a reader state.
 

Detailed Description

A two-state spinlock that allows multiple readers of a shared resource to acquire the lock simultaneously.

A spinlock (i.e. a non-yielding lock) that can be used to guard a resource where multiple threads can safely perform some types of operations (e.g. reader entries from a container), while only one thread can safely perform other types of operations (e.g. modifying the container).

Implementation

We lock by using a std::atomic<std::int64_t> (a signed integer). The lock is not locked if the integer is 0. It is read-locked if it is positive and write-locked if it is negative. To read-lock we first check that the integer is non-negative and then fetch_add(1, std::memory_order_acq_rel), then check that the number before the increment is non-negative. The reason for the second check is that between checking that the lock is not write-locked and the fetch_add() operation, it could be write-locked by another thread. To write-lock, we check that the integer is 0 and if so we set it to std::numeric_limits<std::int64_t>::lowest() (i.e. -2^{63}). We achieve this by using a compare_exchange_strong() with failure memory order relaxed and success memory order acq_rel. This guarantees that different threads synchronize using the lock.

A thread read-unlocks the lock using a fetch_sub(1, std::memory_order_acq_rel) operation.

A thread write-unlocks the lock using a store(0, std::memory_order_release) operation.

Member Function Documentation

◆ read_lock()

void Parallel::MultiReaderSpinlock::read_lock ( )
inlinenoexcept

Acquire the lock in a reader state.

Note
Multiple threads can acquire a reader state simultaneously.

◆ read_unlock()

void Parallel::MultiReaderSpinlock::read_unlock ( )
inlinenoexcept

Release the lock from a reader state.

Note
Since multiple threads can simultaneously acquire a reader state, unlock from a single reader does not guarantee a writer can acquire the lock in a write state.

◆ write_lock()

void Parallel::MultiReaderSpinlock::write_lock ( )
inlinenoexcept

Acquire the lock in a writer state.

Once acquired, no other thread can acquire the lock in either a read or a write state until this thread unlocks it.


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