SuperTinyKernel™ RTOS 1.08.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk::sync::RWMutex Class Referencefinal

Reader-Writer Lock synchronization primitive for non-recursive shared and exclusive access. More...

#include <stk_sync_rwmutex.h>

Inheritance diagram for stk::sync::RWMutex:
Collaboration diagram for stk::sync::RWMutex:

Classes

class  ScopedTimedLock
 RAII wrapper for attempting exclusive write access with a timeout. More...
class  ScopedTimedReadMutex
 RAII wrapper for attempting shared read access with a timeout. More...

Public Member Functions

 RWMutex ()
 Construct an RWMutex in the unlocked state with no active readers or writers.
 ~RWMutex ()
 Destructor.
bool TimedReadLock (Timeout timeout_ticks)
 Acquire the lock for shared reading with a timeout.
void ReadLock ()
 Acquire the lock for shared reading.
bool TryReadLock ()
 Attempt to acquire the lock for shared reading without blocking.
void ReadUnlock ()
 Release the shared reader lock.
bool TimedLock (Timeout timeout_ticks)
 Acquire the lock for exclusive writing with a timeout.
void Lock () override
 Acquire the lock for exclusive writing (IMutex interface).
bool TryLock ()
 Attempt to acquire the lock for exclusive writing without blocking.
void Unlock () override
 Release the exclusive writer lock (IMutex interface).
void SetTraceName (const char *name)
 Set name.
const char * GetTraceName () const
 Get name.

Private Member Functions

 RWMutex (const RWMutex &)=delete
RWMutexoperator= (const RWMutex &)=delete

Private Attributes

ConditionVariable m_cv_readers
 signaled when readers can proceed
ConditionVariable m_cv_writers
 signaled when a writer can proceed
uint16_t m_readers
 current active reader count
uint16_t m_writers_waiting
 count of writers waiting for access
bool m_writer_active
 true if a writer currently holds the lock

Static Private Attributes

static const uint16_t READERS_MAX = 0xFFFEU
 maximum number of concurrent readers
static const uint16_t WRITERS_MAX = 0xFFFEU
 maximum number of waiting writers

Detailed Description

Reader-Writer Lock synchronization primitive for non-recursive shared and exclusive access.

RWMutex allows multiple tasks to read a shared resource simultaneously (shared access) while ensuring that only one task can write to the resource at a time (exclusive access). This is particularly efficient for data structures that are read frequently but modified infrequently.

Note
Writer Preference Policy: To prevent "writer starvation," this implementation prioritizes waiting writers. If a writer is waiting for the lock, new readers will be blocked until the writer has completed its operation.
Maximum number of concurrent readers must not exceed READERS_MAX (0xFFFE). Maximum number of waiting writers must not exceed WRITERS_MAX (0xFFFE).
Non-recursive: a task must not call ReadLock() or Lock() more than once without a matching unlock. Doing so will deadlock.
// Example: Protecting app settings
stk::sync::RWMutex g_SettingsLock;
Settings g_Settings;
void Engine_Task() {
// Multiple engine instances can read settings concurrently
Apply(g_Settings);
}
void UI_Control_Task() {
// Exclusive access to update settings
g_SettingsLock.Lock();
g_Settings.volume = new_volume;
g_SettingsLock.Unlock();
}
Reader-Writer Lock synchronization primitive for non-recursive shared and exclusive access.
void Unlock() override
Release the exclusive writer lock (IMutex interface).
void Lock() override
Acquire the lock for exclusive writing (IMutex interface).
RAII wrapper for attempting shared read access with a timeout.
See also
Mutex, ConditionVariable, ScopedReadMutex
Examples
D:/SVN/private/stk/interop/c/include/stk_c.h.

Definition at line 61 of file stk_sync_rwmutex.h.

Constructor & Destructor Documentation

◆ RWMutex() [1/2]

stk::sync::RWMutex::RWMutex ( )
inlineexplicit

Construct an RWMutex in the unlocked state with no active readers or writers.

Definition at line 66 of file stk_sync_rwmutex.h.

67 {}
bool m_writer_active
true if a writer currently holds the lock
uint16_t m_writers_waiting
count of writers waiting for access
uint16_t m_readers
current active reader count

References m_readers, m_writer_active, and m_writers_waiting.

Referenced by operator=(), stk::sync::RWMutex::ScopedTimedLock::ScopedTimedLock(), and stk::sync::RWMutex::ScopedTimedReadMutex::ScopedTimedReadMutex().

Here is the caller graph for this function:

◆ ~RWMutex()

stk::sync::RWMutex::~RWMutex ( )
inline

Destructor.

Note
Destroying an RWMutex while readers are active, writers are waiting, or a writer holds the lock is a logical error (dangling state). An assertion is triggered in debug builds.
MISRA deviation: [STK-DEV-005] Rule 10-3-2.

Definition at line 75 of file stk_sync_rwmutex.h.

76 {
77 // API contract: must not be destroyed while readers are active, writers are waiting,
78 // or a writer holds the lock
80 }
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:516

References m_readers, m_writer_active, m_writers_waiting, STK_ASSERT, and STK_VIRT_DTOR.

◆ RWMutex() [2/2]

stk::sync::RWMutex::RWMutex ( const RWMutex & )
privatedelete

Member Function Documentation

◆ GetTraceName()

const char * stk::ITraceable::GetTraceName ( ) const
inlineinherited

Get name.

Returns
Name string, or NULL if not set or if STK_SYNC_DEBUG_NAMES is 0.

Definition at line 534 of file stk_common.h.

535 {
536 #if STK_SYNC_DEBUG_NAMES
537 return m_trace_name;
538 #else
539 return nullptr;
540 #endif
541 }

◆ Lock()

void stk::sync::RWMutex::Lock ( )
inlineoverridevirtual

Acquire the lock for exclusive writing (IMutex interface).

Blocks the calling task until all active readers have released their locks and no other writer is active.

Note
Non-recursive.
Warning
ISR-safe.

Implements stk::IMutex.

Definition at line 178 of file stk_sync_rwmutex.h.

#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:715
static constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:211
bool TimedLock(Timeout timeout_ticks)
Acquire the lock for exclusive writing with a timeout.

References STK_UNUSED, TimedLock(), and stk::WAIT_INFINITE.

Referenced by stk_rwmutex_lock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=()

RWMutex & stk::sync::RWMutex::operator= ( const RWMutex & )
privatedelete

References RWMutex().

Here is the call graph for this function:

◆ ReadLock()

void stk::sync::RWMutex::ReadLock ( )
inline

Acquire the lock for shared reading.

Blocks the calling task if a writer is currently active or if there are writers waiting to acquire the lock.

Note
Non-recursive.
Warning
ISR-unsafe.

Definition at line 146 of file stk_sync_rwmutex.h.

bool TimedReadLock(Timeout timeout_ticks)
Acquire the lock for shared reading with a timeout.

References STK_UNUSED, TimedReadLock(), and stk::WAIT_INFINITE.

Referenced by stk_rwmutex_read_lock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReadUnlock()

void stk::sync::RWMutex::ReadUnlock ( )
inline

Release the shared reader lock.

Decrements the reader count. If this was the last active reader, notifies any waiting writers.

Warning
ISR-safe.

Definition at line 244 of file stk_sync_rwmutex.h.

245{
246 const ScopedCriticalSection cs_;
247
248 STK_ASSERT(m_readers != 0U); // API contract: must have a matching ReadLock()
249
250 m_readers = static_cast<uint16_t>(m_readers - 1U);
251
252 // wake a waiting writer when the last reader exits
253 if (m_readers == 0U)
254 {
255 m_cv_writers.NotifyOne_CS();
256 }
257}
ConditionVariable m_cv_writers
signaled when a writer can proceed

References m_cv_writers, m_readers, and STK_ASSERT.

Referenced by stk_rwmutex_read_unlock().

Here is the caller graph for this function:

◆ SetTraceName()

void stk::ITraceable::SetTraceName ( const char * name)
inlineinherited

Set name.

Parameters
[in]nameNull-terminated string or NULL.
Note
If STK_SYNC_DEBUG_NAMES is 0 then calling this function has no effect.

Definition at line 522 of file stk_common.h.

523 {
524 #if STK_SYNC_DEBUG_NAMES
525 m_trace_name = name;
526 #else
527 STK_UNUSED(name);
528 #endif
529 }

References STK_UNUSED.

Referenced by stk::memory::BlockMemoryPool::BlockMemoryPool(), and stk::memory::BlockMemoryPool::BlockMemoryPool().

Here is the caller graph for this function:

◆ TimedLock()

bool stk::sync::RWMutex::TimedLock ( Timeout timeout_ticks)
inline

Acquire the lock for exclusive writing with a timeout.

Parameters
[in]timeout_ticksMaximum time to wait (ticks).
Returns
True if lock acquired, false if timeout occurred.
Note
Non-recursive.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.

Definition at line 263 of file stk_sync_rwmutex.h.

264{
265 bool success = true;
266 ScopedCriticalSection cs_;
267
268 STK_ASSERT(m_writers_waiting < WRITERS_MAX); // API contract: waiting writer count must not exceed maximum
269
270 m_writers_waiting = static_cast<uint16_t>(m_writers_waiting + 1U);
271
272 // wait until there are no active readers and no active writer
273 while (m_writer_active || (m_readers != 0U))
274 {
275 if (!m_cv_writers.Wait(cs_, timeout_ticks))
276 {
277 // timed out: withdraw from the waiting writers queue
278 m_writers_waiting = static_cast<uint16_t>(m_writers_waiting - 1U);
279 success = false;
280 break;
281 }
282 }
283
284 // only finalize state if the wait didn't time out
285 if (success)
286 {
287 m_writers_waiting = static_cast<uint16_t>(m_writers_waiting - 1U);
288
289 // kernel invariant: no readers and no active writer when lock is granted
290 if ((m_readers != 0U) || m_writer_active)
291 {
293 }
294
295 m_writer_active = true;
296 }
297
298 return success;
299}
@ KERNEL_PANIC_ASSERT
Internal assertion failed (maps from STK_ASSERT).
Definition stk_common.h:62
static void STK_KERNEL_PANIC(stk::EKernelPanicId id)
Called when the kernel detects an unrecoverable internal fault.
Definition stk_arch.h:183
static const uint16_t WRITERS_MAX
maximum number of waiting writers

References stk::KERNEL_PANIC_ASSERT, m_cv_writers, m_readers, m_writer_active, m_writers_waiting, STK_ASSERT, stk::STK_KERNEL_PANIC(), and WRITERS_MAX.

Referenced by Lock(), stk::sync::RWMutex::ScopedTimedLock::ScopedTimedLock(), stk_rwmutex_timed_lock(), and TryLock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ TimedReadLock()

bool stk::sync::RWMutex::TimedReadLock ( Timeout timeout_ticks)
inline

Acquire the lock for shared reading with a timeout.

Parameters
[in]timeout_ticksMaximum time to wait (ticks).
Note
Non-recursive.
Returns
True if lock acquired, false if timeout occurred.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.

Definition at line 212 of file stk_sync_rwmutex.h.

213{
214 bool success = true;
215 ScopedCriticalSection cs_;
216
217 // wait if there is an active writer or if writers are waiting (Writer Preference)
218 while (m_writer_active || (m_writers_waiting != 0U))
219 {
220 if (!m_cv_readers.Wait(cs_, timeout_ticks))
221 {
222 success = false; // timeout
223 break;
224 }
225
226 // re-check on wake: another writer may have queued up while this task was sleeping
227 }
228
229 // only increment reader count if the lock was successfully acquired without timing out
230 if (success)
231 {
232 STK_ASSERT(m_readers < READERS_MAX); // API contract: reader count must not exceed maximum
233
234 m_readers = static_cast<uint16_t>(m_readers + 1U);
235 }
236
237 return success;
238}
static const uint16_t READERS_MAX
maximum number of concurrent readers
ConditionVariable m_cv_readers
signaled when readers can proceed

References m_cv_readers, m_readers, m_writer_active, m_writers_waiting, READERS_MAX, and STK_ASSERT.

Referenced by ReadLock(), stk::sync::RWMutex::ScopedTimedReadMutex::ScopedTimedReadMutex(), stk_rwmutex_timed_read_lock(), and TryReadLock().

Here is the caller graph for this function:

◆ TryLock()

bool stk::sync::RWMutex::TryLock ( )
inline

Attempt to acquire the lock for exclusive writing without blocking.

Checks if any readers are active or if another writer is active.

Note
Non-recursive.
Returns
True if the exclusive lock was acquired, false otherwise.
Warning
ISR-safe.

Definition at line 186 of file stk_sync_rwmutex.h.

186{ return TimedLock(NO_WAIT); }
static constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:217

References stk::NO_WAIT, and TimedLock().

Referenced by stk_rwmutex_trylock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ TryReadLock()

bool stk::sync::RWMutex::TryReadLock ( )
inline

Attempt to acquire the lock for shared reading without blocking.

Checks if a writer is active or waiting. If the resource is available for reading, it increments the reader count and returns immediately.

Note
Non-recursive.
Returns
True if the read lock was acquired, false if a writer is active or waiting.
Warning
ISR-safe.

Definition at line 155 of file stk_sync_rwmutex.h.

155{ return TimedReadLock(NO_WAIT); }

References stk::NO_WAIT, and TimedReadLock().

Referenced by stk_rwmutex_try_read_lock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Unlock()

void stk::sync::RWMutex::Unlock ( )
inlineoverridevirtual

Release the exclusive writer lock (IMutex interface).

Releases the lock and prioritizes waking waiting writers. If no writers are waiting, wakes all waiting readers.

Warning
ISR-safe.

Implements stk::IMutex.

Definition at line 305 of file stk_sync_rwmutex.h.

306{
307 const ScopedCriticalSection cs_;
308
309 STK_ASSERT(m_writer_active); // API contract: caller must hold the write lock
310
311 m_writer_active = false;
312
313 // prioritize waking waiting writers to prevent writer starvation;
314 // only wake readers if no writers are queued
315 if (m_writers_waiting != 0U)
316 {
317 m_cv_writers.NotifyOne_CS();
318 }
319 else
320 {
321 m_cv_readers.NotifyAll_CS();
322 }
323}

References m_cv_readers, m_cv_writers, m_writer_active, m_writers_waiting, and STK_ASSERT.

Referenced by stk_rwmutex_unlock().

Here is the caller graph for this function:

Member Data Documentation

◆ m_cv_readers

ConditionVariable stk::sync::RWMutex::m_cv_readers
private

signaled when readers can proceed

Definition at line 201 of file stk_sync_rwmutex.h.

Referenced by TimedReadLock(), and Unlock().

◆ m_cv_writers

ConditionVariable stk::sync::RWMutex::m_cv_writers
private

signaled when a writer can proceed

Definition at line 202 of file stk_sync_rwmutex.h.

Referenced by ReadUnlock(), TimedLock(), and Unlock().

◆ m_readers

uint16_t stk::sync::RWMutex::m_readers
private

current active reader count

Definition at line 203 of file stk_sync_rwmutex.h.

Referenced by ReadUnlock(), RWMutex(), TimedLock(), TimedReadLock(), and ~RWMutex().

◆ m_writer_active

bool stk::sync::RWMutex::m_writer_active
private

true if a writer currently holds the lock

Definition at line 205 of file stk_sync_rwmutex.h.

Referenced by RWMutex(), TimedLock(), TimedReadLock(), Unlock(), and ~RWMutex().

◆ m_writers_waiting

uint16_t stk::sync::RWMutex::m_writers_waiting
private

count of writers waiting for access

Definition at line 204 of file stk_sync_rwmutex.h.

Referenced by RWMutex(), TimedLock(), TimedReadLock(), Unlock(), and ~RWMutex().

◆ READERS_MAX

const uint16_t stk::sync::RWMutex::READERS_MAX = 0xFFFEU
staticprivate

maximum number of concurrent readers

Definition at line 198 of file stk_sync_rwmutex.h.

Referenced by TimedReadLock().

◆ WRITERS_MAX

const uint16_t stk::sync::RWMutex::WRITERS_MAX = 0xFFFEU
staticprivate

maximum number of waiting writers

Definition at line 199 of file stk_sync_rwmutex.h.

Referenced by TimedLock().


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