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::MessageQueue Class Reference

Fixed-capacity, fixed-message-size FIFO queue for inter-task communication. More...

#include <stk_sync_msgqueue.h>

Inheritance diagram for stk::sync::MessageQueue:
Collaboration diagram for stk::sync::MessageQueue:

Public Member Functions

 MessageQueue (uint8_t *buf, size_t capacity, size_t msg_size)
 Constructor.
 ~MessageQueue ()=default
 Destructor.
EWaitResult PutEx (const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Put a message into the back of the queue (FIFO order), preserving the full wait outcome.
bool Put (const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Put a message into the back of the queue (FIFO order).
bool TryPut (const void *msg_ptr)
 Attempt to put a message into the back of the queue without blocking.
EWaitResult PutFrontEx (const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Put a message into the front of the queue (LIFO / priority-insert order), preserving the full wait outcome.
bool PutFront (const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Put a message into the front of the queue (LIFO / priority-insert order).
bool TryPutFront (const void *msg_ptr)
 Attempt to put a message into the front of the queue without blocking.
EWaitResult GetEx (void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Get a message from the queue, preserving the full wait outcome.
bool Get (void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Get a message from the queue.
bool TryGet (void *msg_ptr)
 Attempt to get a message from the queue without blocking.
EWaitResult PeekEx (void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Peek at the next message to be delivered without removing it, preserving the full wait outcome.
bool Peek (void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Peek at the next message to be delivered (the one Get() returns next) without removing it.
bool TryPeek (void *msg_ptr)
 Attempt to peek at the next message without blocking.
EWaitResult PeekFrontEx (void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Peek at the front of the queue without removing it, preserving the full wait outcome.
bool PeekFront (void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
 Peek at the front of the queue (the message Get() returns next) without removing it.
bool TryPeekFront (void *msg_ptr)
 Attempt to peek at the front message without blocking.
void Reset ()
 Discard all messages and reset the queue to the empty state.
size_t GetCapacity () const
 Get the maximum number of messages the queue can hold.
size_t GetMsgSize () const
 Get the size of each message in bytes.
size_t GetCount () const
 Get the current number of messages in the queue.
size_t GetSpace () const
 Get the number of free slots currently available.
uint8_t * GetBuffer ()
 Get pointer to the message buffer.
bool IsEmpty () const
 Check whether the queue is currently empty.
bool IsFull () const
 Check whether the queue is currently full.
bool IsStorageValid () const
 Verify that the backing storage is valid and the pool is ready for use.
void SetTraceName (const char *name)
 Set name.
const char * GetTraceName () const
 Get name.

Static Public Attributes

static const size_t CAPACITY_MAX = 0xFFFEU
 Max capacity supported (number of messages).

Private Member Functions

 MessageQueue (const MessageQueue &)=delete
MessageQueue & operator= (const MessageQueue &)=delete
uint8_t * Slot (size_t idx) const
size_t Next (size_t idx) const
size_t Prev (size_t idx) const
EWaitResult WaitNotFull (IMutex &cs, Timeout timeout_ticks)
EWaitResult WaitNotEmpty (IMutex &cs, Timeout timeout_ticks)

Private Attributes

uint8_t * m_buffer
 flat byte ring-buffer: capacity slots of msg_size bytes each
const size_t m_capacity
 maximum number of messages stored in the queue
const size_t m_msg_size
 size of each message in bytes
size_t m_count
 current number of messages stored in the queue
size_t m_head
 write index (next slot to be written by Put())
size_t m_tail
 read index (next slot to be read by Get())
ConditionVariable m_cv_not_empty
 signaled by Put() when the queue transitions from empty
ConditionVariable m_cv_not_full
 signaled by Get()/Reset() when the queue is no longer full

Detailed Description

Fixed-capacity, fixed-message-size FIFO queue for inter-task communication.

MessageQueue provides a synchronized ring-buffer that transports opaque, fixed-size byte messages between tasks. It follows the following blocking semantics:

  • Put() blocks if the queue is full until space becomes available or the timeout expires.
  • Get() blocks if the queue is empty until a message is produced or the timeout expires.

Like stk::sync::Pipe (and unlike the type-safe stk::sync::PipeT), MessageQueue is parameterised on a byte count (MSG) rather than on an element type. This makes it suitable for passing heterogeneous or C-ABI structs without requiring the message type to be copyable via the C++ assignment operator. The message payload is always copied with memcpy. In addition to the plain FIFO operations it supports front insertion (PutFront()) and non-destructive reads (Peek()).

// Caller owns and provides the buffer (e.g. from a static pool):
struct SensorMsg { uint32_t timestamp_ms; int16_t value; };
static uint8_t s_buf[8 * sizeof(SensorMsg)];
stk::sync::MessageQueue g_SensorQ(s_buf, 8, sizeof(SensorMsg));
Fixed-capacity, fixed-message-size FIFO queue for inter-task communication.
Note
The caller is responsible for ensuring that buf remains valid for the entire lifetime of the queue object.
Maximum number of messages (capacity) must not exceed CAPACITY_MAX.
Message size (msg_size) must be at least 1.
The boolean calls (Put(), PutFront(), Get(), Peek(), PeekFront()) collapse a timeout and a cancellation (IKernel::CancelTaskWait()) into the same failure result. Use the *Ex() variants (PutEx(), PutFrontEx(), GetEx(), PeekEx(), PeekFrontEx()) if the caller needs to tell them apart.
See also
MessageQueueT, Pipe, PipeT, ConditionVariable, Semaphore
Note
Only available when kernel is compiled with KERNEL_SYNC mode enabled.
Examples
D:/SVN/private/stk/interop/c/include/stk_c.h.

Definition at line 62 of file stk_sync_msgqueue.h.

Constructor & Destructor Documentation

◆ MessageQueue() [1/2]

stk::sync::MessageQueue::MessageQueue ( uint8_t * buf,
size_t capacity,
size_t msg_size )
inlineexplicit

Constructor.

Parameters
[in]bufPointer to the externally-allocated storage. Must be at least capacity * msg_size bytes.
[in]capacityMaximum number of messages [1, CAPACITY_MAX].
[in]msg_sizeSize of each message in bytes (>= 1).

Definition at line 416 of file stk_sync_msgqueue.h.

417: m_buffer(buf),
418 m_capacity(capacity),
419 m_msg_size(msg_size),
420 m_count(0U),
421 m_head(0U),
422 m_tail(0U)
423{
424 STK_ASSERT(buf != nullptr);
425 STK_ASSERT(capacity >= 1U);
426 STK_ASSERT(capacity <= CAPACITY_MAX);
427 STK_ASSERT(msg_size >= 1U);
428}
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:516
static const size_t CAPACITY_MAX
Max capacity supported (number of messages).
size_t m_tail
read index (next slot to be read by Get())
const size_t m_capacity
maximum number of messages stored in the queue
size_t m_head
write index (next slot to be written by Put())
uint8_t * m_buffer
flat byte ring-buffer: capacity slots of msg_size bytes each
size_t m_count
current number of messages stored in the queue
const size_t m_msg_size
size of each message in bytes

References CAPACITY_MAX, m_buffer, m_capacity, m_count, m_head, m_msg_size, m_tail, and STK_ASSERT.

Referenced by MessageQueue(), and stk::sync::MessageQueueT< N, MSG >::MessageQueueT().

Here is the caller graph for this function:

◆ ~MessageQueue()

stk::sync::MessageQueue::~MessageQueue ( )
default

Destructor.

Note
If tasks are still waiting at destruction time it is considered a logical error (dangling waiters). An assertion is triggered in debug builds via the ConditionVariable destructors.
MISRA deviation: [STK-DEV-005] Rule 10-3-2.

References STK_VIRT_DTOR, and stk::WAIT_INFINITE.

Referenced by tx_queue_delete().

Here is the caller graph for this function:

◆ MessageQueue() [2/2]

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

References MessageQueue().

Here is the call graph for this function:

Member Function Documentation

◆ Get()

bool stk::sync::MessageQueue::Get ( void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Get a message from the queue.

Copies msg_size bytes from the oldest slot in the ring buffer into the buffer pointed to by msg_ptr. If the queue is empty the calling task is suspended until a message is produced or the timeout expires.

Parameters
[out]msg_ptrDestination buffer for the retrieved message (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a message (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
true if a message was successfully retrieved, false otherwise (timeout, cancellation or NO_WAIT on an empty queue). Use GetEx() to tell these apart.

Definition at line 204 of file stk_sync_msgqueue.h.

205 {
206 return (GetEx(msg_ptr, timeout_ticks) == WAIT_RESULT_SIGNAL);
207 }
@ WAIT_RESULT_SIGNAL
The wake was caused by a signal.
Definition stk_common.h:139
EWaitResult GetEx(void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Get a message from the queue, preserving the full wait outcome.

References GetEx(), stk::WAIT_INFINITE, and stk::WAIT_RESULT_SIGNAL.

Referenced by stk_msgq_get(), TryGet(), xMessageBufferReceive(), and xQueueSelectFromSet().

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

◆ GetBuffer()

uint8_t * stk::sync::MessageQueue::GetBuffer ( )
inline

Get pointer to the message buffer.

Returns
Pointer to the beginning of the message buffer.
Note
ISR-safe.

Definition at line 355 of file stk_sync_msgqueue.h.

355{ return m_buffer; }

References m_buffer.

Referenced by stk_msgq_get_buffer().

Here is the caller graph for this function:

◆ GetCapacity()

size_t stk::sync::MessageQueue::GetCapacity ( ) const
inline

Get the maximum number of messages the queue can hold.

Returns
Construction-time capacity.
Note
ISR-safe.

Definition at line 330 of file stk_sync_msgqueue.h.

330{ return m_capacity; }

References m_capacity.

Referenced by osMessageQueueGetCapacity(), and stk_msgq_get_capacity().

Here is the caller graph for this function:

◆ GetCount()

size_t stk::sync::MessageQueue::GetCount ( ) const
inline

Get the current number of messages in the queue.

Returns
Point-in-time snapshot of the message count. May be stale by the time the caller acts on it in a multi-task environment.
Note
ISR-safe on targets where a size_t-aligned read is atomic.

Definition at line 343 of file stk_sync_msgqueue.h.

343{ return m_count; }

References m_count.

Referenced by osMessageQueueGetCount(), stk_msgq_get_count(), tx_queue_info_get(), uxQueueMessagesWaiting(), and uxQueueMessagesWaitingFromISR().

Here is the caller graph for this function:

◆ GetEx()

EWaitResult stk::sync::MessageQueue::GetEx ( void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Get a message from the queue, preserving the full wait outcome.

Identical to Get(), except the caller gets the raw EWaitResult, so a cancellation (via IKernel::CancelTaskWait()) can be distinguished from a timeout.

Parameters
[out]msg_ptrDestination buffer for the retrieved message (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a message (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
WAIT_RESULT_SIGNAL if a message was retrieved, WAIT_RESULT_TIMEOUT if no message became available before the timeout expired (or NO_WAIT was passed on an empty queue), WAIT_RESULT_CANCELED if the wait was cancelled via IKernel::CancelTaskWait(), WAIT_RESULT_FAIL if the kernel rejected the wait. Nothing is dequeued or copied on a non-signal result.

Definition at line 562 of file stk_sync_msgqueue.h.

563{
564 STK_ASSERT(msg_ptr != nullptr); // API contract: msg_ptr must not be null
565
566 ScopedCriticalSection cs_;
567
568 const EWaitResult result = WaitNotEmpty(cs_, timeout_ticks);
569
570 if (result == WAIT_RESULT_SIGNAL)
571 {
572 STK_MEMCPY(msg_ptr, Slot(m_tail), m_msg_size);
573 m_tail = Next(m_tail);
574 m_count--;
575
576 m_cv_not_full.NotifyOne_CS();
577 }
578
579 return result;
580}
static void STK_MEMCPY(void *const dest, const void *const src, const size_t size)
Implementation of STK_MEMCPY.
Definition stk_arch.h:731
EWaitResult
Wait result (see IKernelService::Wait).
Definition stk_common.h:137
size_t Next(size_t idx) const
uint8_t * Slot(size_t idx) const
ConditionVariable m_cv_not_full
signaled by Get()/Reset() when the queue is no longer full
EWaitResult WaitNotEmpty(IMutex &cs, Timeout timeout_ticks)

References m_count, m_cv_not_full, m_msg_size, m_tail, Next(), Slot(), STK_ASSERT, STK_MEMCPY(), stk::WAIT_RESULT_SIGNAL, and WaitNotEmpty().

Referenced by Get(), and stk_msgq_get_ex().

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

◆ GetMsgSize()

size_t stk::sync::MessageQueue::GetMsgSize ( ) const
inline

Get the size of each message in bytes.

Returns
Construction-time message size.
Note
ISR-safe.

Definition at line 336 of file stk_sync_msgqueue.h.

336{ return m_msg_size; }

References m_msg_size.

Referenced by osMessageQueueGetMsgSize(), and stk_msgq_get_msg_size().

Here is the caller graph for this function:

◆ GetSpace()

size_t stk::sync::MessageQueue::GetSpace ( ) const
inline

Get the number of free slots currently available.

Returns
Point-in-time snapshot of the free-slot count.
Note
ISR-safe.

Definition at line 349 of file stk_sync_msgqueue.h.

349{ return (m_capacity - m_count); }

References m_capacity, and m_count.

Referenced by osMessageQueueGetSpace(), stk_msgq_get_space(), tx_queue_info_get(), and uxQueueSpacesAvailable().

Here is the caller graph for this function:

◆ 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 582 of file stk_common.h.

583 {
584 #if STK_SYNC_DEBUG_NAMES
585 return m_trace_name;
586 #else
587 return nullptr;
588 #endif
589 }

◆ IsEmpty()

bool stk::sync::MessageQueue::IsEmpty ( ) const
inline

Check whether the queue is currently empty.

Returns
true if the queue contains no messages.
Note
ISR-safe.

Definition at line 361 of file stk_sync_msgqueue.h.

361{ return (m_count == 0U); }

References m_count.

Referenced by stk_msgq_is_empty(), xQueueAddToSet(), and xQueueRemoveFromSet().

Here is the caller graph for this function:

◆ IsFull()

bool stk::sync::MessageQueue::IsFull ( ) const
inline

Check whether the queue is currently full.

Returns
true if the queue contains capacity messages.
Note
ISR-safe.

Definition at line 367 of file stk_sync_msgqueue.h.

367{ return (m_count == m_capacity); }

References m_capacity, and m_count.

Referenced by stk_msgq_is_full().

Here is the caller graph for this function:

◆ IsStorageValid()

bool stk::sync::MessageQueue::IsStorageValid ( ) const
inline

Verify that the backing storage is valid and the pool is ready for use.

Always true for pools constructed with external storage. For heap-constructed queue, false if operator new failed. Must be checked after the heap constructor when operating without exceptions (the typical embedded configuration).

Returns
true if the queue is ready for use.
Note
ISR-safe.

Definition at line 377 of file stk_sync_msgqueue.h.

377{ return (m_buffer != nullptr); }

References m_buffer.

Referenced by osMessageQueueNew(), stk_msgq_is_storage_valid(), xMessageBufferCreate(), xMessageBufferCreateWithCallback(), and xQueueCreate().

Here is the caller graph for this function:

◆ Next()

size_t stk::sync::MessageQueue::Next ( size_t idx) const
inlineprivate

Definition at line 386 of file stk_sync_msgqueue.h.

386{ return (idx + 1U) % m_capacity; }

References m_capacity.

Referenced by GetEx(), and PutEx().

Here is the caller graph for this function:

◆ operator=()

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

◆ Peek()

bool stk::sync::MessageQueue::Peek ( void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Peek at the next message to be delivered (the one Get() returns next) without removing it.

Copies msg_size bytes from the oldest slot in the ring buffer into the buffer pointed to by msg_ptr, leaving the message in place so that a subsequent Get() will return the same message. If the queue is empty the calling task is suspended until a message is produced or the timeout expires.

Parameters
[out]msg_ptrDestination buffer for the peeked message (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a message (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
true if a message was successfully peeked, false otherwise (timeout, cancellation or NO_WAIT on an empty queue). Use PeekEx() to tell these apart.
Note
A successful peek hands the wake-up on to the next waiting task (if any), so a Get() waiter queued behind a Peek() waiter is not left blocked while a message is available.
See also
Get, TryPeek, PeekFront

Definition at line 252 of file stk_sync_msgqueue.h.

253 {
254 return (PeekEx(msg_ptr, timeout_ticks) == WAIT_RESULT_SIGNAL);
255 }
EWaitResult PeekEx(void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Peek at the next message to be delivered without removing it, preserving the full wait outcome.

References PeekEx(), stk::WAIT_INFINITE, and stk::WAIT_RESULT_SIGNAL.

Referenced by stk_msgq_peek(), and TryPeek().

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

◆ PeekEx()

EWaitResult stk::sync::MessageQueue::PeekEx ( void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Peek at the next message to be delivered without removing it, preserving the full wait outcome.

Identical to Peek(), except the caller gets the raw EWaitResult, so a cancellation (via IKernel::CancelTaskWait()) can be distinguished from a timeout.

Parameters
[out]msg_ptrDestination buffer for the peeked message (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a message (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
Same values as GetEx(). Nothing is copied on a non-signal result.

Definition at line 586 of file stk_sync_msgqueue.h.

587{
588 STK_ASSERT(msg_ptr != nullptr); // API contract: msg_ptr must not be null
589
590 ScopedCriticalSection cs_;
591
592 const EWaitResult result = WaitNotEmpty(cs_, timeout_ticks);
593
594 if (result == WAIT_RESULT_SIGNAL)
595 {
596 // copy from the tail slot without advancing the index or decrementing
597 // the count, so the message remains available for the next Get()
598 STK_MEMCPY(msg_ptr, Slot(m_tail), m_msg_size);
599
600 // the message was not consumed: pass the wake-up on to the next waiter (if any),
601 // otherwise a Get() waiter queued behind this Peek() would stay blocked although
602 // a message is available (Put() notifies only one waiter)
603 m_cv_not_empty.NotifyOne_CS();
604 }
605
606 return result;
607}
ConditionVariable m_cv_not_empty
signaled by Put() when the queue transitions from empty

References m_cv_not_empty, m_msg_size, m_tail, Slot(), STK_ASSERT, STK_MEMCPY(), stk::WAIT_RESULT_SIGNAL, and WaitNotEmpty().

Referenced by Peek(), and stk_msgq_peek_ex().

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

◆ PeekFront()

bool stk::sync::MessageQueue::PeekFront ( void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Peek at the front of the queue (the message Get() returns next) without removing it.

Copies msg_size bytes from the read slot (the one Get() would return next) into the buffer pointed to by msg_ptr, leaving the message in place. Because PutFront() inserts at the read slot, this is the most recently PutFront()-inserted message if one is still pending, otherwise the oldest Put() message. The behavior is identical to Peek(); this method exists for symmetry with PutFront(). If the queue is empty the calling task is suspended until a message is produced or the timeout expires.

Parameters
[out]msg_ptrDestination buffer for the peeked message (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a message (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks= NO_WAIT, ISR-unsafe otherwise.
Returns
true if a message was successfully peeked, false otherwise (timeout, cancellation or NO_WAIT on an empty queue). Use PeekFrontEx() to tell these apart.
See also
PutFront, TryPeekFront, Peek

Definition at line 300 of file stk_sync_msgqueue.h.

301 {
302 return (PeekFrontEx(msg_ptr, timeout_ticks) == WAIT_RESULT_SIGNAL);
303 }
EWaitResult PeekFrontEx(void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Peek at the front of the queue without removing it, preserving the full wait outcome.

References PeekFrontEx(), stk::WAIT_INFINITE, and stk::WAIT_RESULT_SIGNAL.

Referenced by stk_msgq_peekfront(), and TryPeekFront().

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

◆ PeekFrontEx()

EWaitResult stk::sync::MessageQueue::PeekFrontEx ( void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Peek at the front of the queue without removing it, preserving the full wait outcome.

Identical to PeekFront(), except the caller gets the raw EWaitResult, so a cancellation (via IKernel::CancelTaskWait()) can be distinguished from a timeout.

Parameters
[out]msg_ptrDestination buffer for the peeked message (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a message (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
Same values as GetEx(). Nothing is copied on a non-signal result.

Definition at line 613 of file stk_sync_msgqueue.h.

614{
615 STK_ASSERT(msg_ptr != nullptr); // API contract: msg_ptr must not be null
616
617 ScopedCriticalSection cs_;
618
619 const EWaitResult result = WaitNotEmpty(cs_, timeout_ticks);
620
621 if (result == WAIT_RESULT_SIGNAL)
622 {
623 // the front-inserted message is at m_tail (PutFront retreats m_tail then
624 // writes, so the newly placed message is always at the current m_tail);
625 // for a pure-Put queue this is equally correct: m_tail is the oldest slot
626 STK_MEMCPY(msg_ptr, Slot(m_tail), m_msg_size);
627
628 // the message was not consumed: pass the wake-up on to the next waiter (if any),
629 // see PeekEx()
630 m_cv_not_empty.NotifyOne_CS();
631 }
632
633 return result;
634}

References m_cv_not_empty, m_msg_size, m_tail, Slot(), STK_ASSERT, STK_MEMCPY(), stk::WAIT_RESULT_SIGNAL, and WaitNotEmpty().

Referenced by PeekFront(), and stk_msgq_peekfront_ex().

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

◆ Prev()

size_t stk::sync::MessageQueue::Prev ( size_t idx) const
inlineprivate

Definition at line 390 of file stk_sync_msgqueue.h.

390{ return (idx == 0U) ? (m_capacity - 1U) : (idx - 1U); }

References m_capacity.

Referenced by PutFrontEx().

Here is the caller graph for this function:

◆ Put()

bool stk::sync::MessageQueue::Put ( const void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Put a message into the back of the queue (FIFO order).

Copies msg_size bytes from msg_ptr into the next available slot in the ring buffer. If the queue is full the calling task is suspended until space becomes available or the timeout expires.

Parameters
[in]msg_ptrPointer to the message payload (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a free slot (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
true if the message was successfully enqueued, false otherwise (timeout, cancellation or NO_WAIT on a full queue). Use PutEx() to tell these apart.

Definition at line 114 of file stk_sync_msgqueue.h.

115 {
116 return (PutEx(msg_ptr, timeout_ticks) == WAIT_RESULT_SIGNAL);
117 }
EWaitResult PutEx(const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Put a message into the back of the queue (FIFO order), preserving the full wait outcome.

References PutEx(), stk::WAIT_INFINITE, and stk::WAIT_RESULT_SIGNAL.

Referenced by stk_msgq_put(), TryPut(), xMessageBufferSend(), and xQueueSend().

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

◆ PutEx()

EWaitResult stk::sync::MessageQueue::PutEx ( const void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Put a message into the back of the queue (FIFO order), preserving the full wait outcome.

Identical to Put(), except the caller gets the raw EWaitResult, so a cancellation (via IKernel::CancelTaskWait()) can be distinguished from a timeout.

Parameters
[in]msg_ptrPointer to the message payload (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a free slot (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
WAIT_RESULT_SIGNAL if the message was enqueued, WAIT_RESULT_TIMEOUT if no slot became available before the timeout expired (or NO_WAIT was passed on a full queue), WAIT_RESULT_CANCELED if the wait was cancelled via IKernel::CancelTaskWait(), WAIT_RESULT_FAIL if the kernel rejected the wait. Nothing is enqueued on a non-signal result.

Definition at line 509 of file stk_sync_msgqueue.h.

510{
511 STK_ASSERT(msg_ptr != nullptr); // API contract: msg_ptr must not be null
512 STK_ASSERT(m_count <= (CAPACITY_MAX - 1U)); // API contract: must not exceed capacity
513
514 ScopedCriticalSection cs_;
515
516 const EWaitResult result = WaitNotFull(cs_, timeout_ticks);
517
518 if (result == WAIT_RESULT_SIGNAL)
519 {
520 STK_MEMCPY(Slot(m_head), msg_ptr, m_msg_size);
521 m_head = Next(m_head);
522 m_count++;
523
524 m_cv_not_empty.NotifyOne_CS();
525 }
526
527 return result;
528}
EWaitResult WaitNotFull(IMutex &cs, Timeout timeout_ticks)

References CAPACITY_MAX, m_count, m_cv_not_empty, m_head, m_msg_size, Next(), Slot(), STK_ASSERT, STK_MEMCPY(), stk::WAIT_RESULT_SIGNAL, and WaitNotFull().

Referenced by Put(), anonymous_namespace{threadx_stk.cpp}::QueueSend(), and stk_msgq_put_ex().

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

◆ PutFront()

bool stk::sync::MessageQueue::PutFront ( const void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Put a message into the front of the queue (LIFO / priority-insert order).

Copies msg_size bytes from msg_ptr into the slot immediately before the current read pointer, making it the next message that Get() will return. If the queue is full the calling task is suspended until space becomes available or the timeout expires.

Parameters
[in]msg_ptrPointer to the message payload (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a free slot (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
true if the message was successfully enqueued at the front, false otherwise (timeout, cancellation or NO_WAIT on a full queue). Use PutFrontEx() to tell these apart.
See also
Put, TryPutFront

Definition at line 157 of file stk_sync_msgqueue.h.

158 {
159 return (PutFrontEx(msg_ptr, timeout_ticks) == WAIT_RESULT_SIGNAL);
160 }
EWaitResult PutFrontEx(const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Put a message into the front of the queue (LIFO / priority-insert order), preserving the full wait ou...

References PutFrontEx(), stk::WAIT_INFINITE, and stk::WAIT_RESULT_SIGNAL.

Referenced by stk_msgq_putfront(), TryPutFront(), and xQueueSendToFront().

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

◆ PutFrontEx()

EWaitResult stk::sync::MessageQueue::PutFrontEx ( const void * msg_ptr,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Put a message into the front of the queue (LIFO / priority-insert order), preserving the full wait outcome.

Identical to PutFront(), except the caller gets the raw EWaitResult, so a cancellation (via IKernel::CancelTaskWait()) can be distinguished from a timeout.

Parameters
[in]msg_ptrPointer to the message payload (must be at least msg_size bytes).
[in]timeout_ticksMaximum time to wait for a free slot (ticks). Use WAIT_INFINITE to block indefinitely, NO_WAIT for a non-blocking attempt.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
Same values as PutEx(). Nothing is enqueued on a non-signal result.

Definition at line 534 of file stk_sync_msgqueue.h.

535{
536 STK_ASSERT(msg_ptr != nullptr); // API contract: msg_ptr must not be null
537 STK_ASSERT(m_count <= (CAPACITY_MAX - 1U)); // API contract: must not exceed capacity
538
539 ScopedCriticalSection cs_;
540
541 const EWaitResult result = WaitNotFull(cs_, timeout_ticks);
542
543 if (result == WAIT_RESULT_SIGNAL)
544 {
545 // retreat the tail pointer to claim the slot that Get() would read next,
546 // then write the message there; this makes the new message the head of
547 // the logical sequence without touching m_head at all
548 m_tail = Prev(m_tail);
549 STK_MEMCPY(Slot(m_tail), msg_ptr, m_msg_size);
550 m_count++;
551
552 m_cv_not_empty.NotifyOne_CS();
553 }
554
555 return result;
556}
size_t Prev(size_t idx) const

References CAPACITY_MAX, m_count, m_cv_not_empty, m_msg_size, m_tail, Prev(), Slot(), STK_ASSERT, STK_MEMCPY(), stk::WAIT_RESULT_SIGNAL, and WaitNotFull().

Referenced by PutFront(), anonymous_namespace{threadx_stk.cpp}::QueueSend(), and stk_msgq_putfront_ex().

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

◆ Reset()

void stk::sync::MessageQueue::Reset ( )
inline

Discard all messages and reset the queue to the empty state.

Resets the head, tail and count to zero. Any tasks blocked in Put() are woken so they can re-evaluate and enqueue their messages into the now-empty queue.

Warning
Messages that were in the queue are silently discarded. Ensure no consumers depend on them before calling Reset().
ISR-safe.

Definition at line 640 of file stk_sync_msgqueue.h.

641{
642 const ScopedCriticalSection cs_;
643
644 m_count = 0U;
645 m_head = 0U;
646 m_tail = 0U;
647
648 // wake all blocked producers: the queue is now entirely empty
649 m_cv_not_full.NotifyAll_CS();
650}

References m_count, m_cv_not_full, m_head, and m_tail.

Referenced by stk_msgq_reset(), tx_queue_flush(), xMessageBufferReset(), xMessageBufferResetFromISR(), xQueueOverwrite(), and xQueueOverwriteFromISR().

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 570 of file stk_common.h.

571 {
572 #if STK_SYNC_DEBUG_NAMES
573 m_trace_name = name;
574 #else
575 STK_UNUSED(name);
576 #endif
577 }
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:715

References STK_UNUSED.

Referenced by stk::memory::BlockMemoryPool::BlockMemoryPool(), stk::memory::BlockMemoryPool::BlockMemoryPool(), stk::memory::BytePool::BytePool(), stk::memory::BytePool::BytePool(), tx_block_pool_create(), tx_event_flags_create(), tx_mutex_create(), tx_queue_create(), and tx_semaphore_create().

Here is the caller graph for this function:

◆ Slot()

uint8_t * stk::sync::MessageQueue::Slot ( size_t idx) const
inlineprivate

Definition at line 383 of file stk_sync_msgqueue.h.

383{ return m_buffer + (idx * m_msg_size); }

References m_buffer, and m_msg_size.

Referenced by GetEx(), PeekEx(), PeekFrontEx(), PutEx(), and PutFrontEx().

Here is the caller graph for this function:

◆ TryGet()

bool stk::sync::MessageQueue::TryGet ( void * msg_ptr)
inline

Attempt to get a message from the queue without blocking.

Dequeues a message only if one is immediately available. Returns false instantly if the queue is empty.

Parameters
[out]msg_ptrDestination buffer for the retrieved message.
Warning
ISR-safe.
Returns
true if a message was retrieved, false if the queue was empty.

Definition at line 217 of file stk_sync_msgqueue.h.

217{ return Get(msg_ptr, 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:234
bool Get(void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Get a message from the queue.

References Get(), and stk::NO_WAIT.

Referenced by stk_msgq_tryget(), xMessageBufferReceiveFromISR(), xMessageBufferReset(), xMessageBufferResetFromISR(), and xQueueSelectFromSetFromISR().

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

◆ TryPeek()

bool stk::sync::MessageQueue::TryPeek ( void * msg_ptr)
inline

Attempt to peek at the next message without blocking.

Copies the oldest message into msg_ptr only if one is immediately available. The message is not removed from the queue. Returns false instantly if the queue is empty.

Parameters
[out]msg_ptrDestination buffer for the peeked message.
Warning
ISR-safe.
Returns
true if a message was peeked, false if the queue was empty.
See also
Peek, TryGet

Definition at line 266 of file stk_sync_msgqueue.h.

266{ return Peek(msg_ptr, NO_WAIT); }
bool Peek(void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Peek at the next message to be delivered (the one Get() returns next) without removing it.

References stk::NO_WAIT, and Peek().

Referenced by stk_msgq_trypeek(), and xMessageBufferNextLengthBytes().

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

◆ TryPeekFront()

bool stk::sync::MessageQueue::TryPeekFront ( void * msg_ptr)
inline

Attempt to peek at the front message without blocking.

Copies the message that Get() would return next into msg_ptr only if one is immediately available. The message is not removed from the queue. Returns false instantly if the queue is empty.

Parameters
[out]msg_ptrDestination buffer for the peeked message.
Warning
ISR-safe.
Returns
true if a message was peeked, false if the queue was empty.
See also
PeekFront, TryPutFront

Definition at line 314 of file stk_sync_msgqueue.h.

314{ return PeekFront(msg_ptr, NO_WAIT); }
bool PeekFront(void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Peek at the front of the queue (the message Get() returns next) without removing it.

References stk::NO_WAIT, and PeekFront().

Referenced by stk_msgq_trypeekfront().

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

◆ TryPut()

bool stk::sync::MessageQueue::TryPut ( const void * msg_ptr)
inline

Attempt to put a message into the back of the queue without blocking.

Enqueues the message only if a free slot is immediately available. Returns false instantly if the queue is full.

Parameters
[in]msg_ptrPointer to the message payload.
Warning
ISR-safe.
Returns
true if the message was enqueued, false if the queue was full.

Definition at line 127 of file stk_sync_msgqueue.h.

127{ return Put(msg_ptr, NO_WAIT); }
bool Put(const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Put a message into the back of the queue (FIFO order).

References stk::NO_WAIT, and Put().

Referenced by stk_msgq_tryput(), xMessageBufferReceive(), xMessageBufferSendFromISR(), xQueueOverwrite(), xQueueOverwriteFromISR(), and xQueueSendFromISR().

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

◆ TryPutFront()

bool stk::sync::MessageQueue::TryPutFront ( const void * msg_ptr)
inline

Attempt to put a message into the front of the queue without blocking.

Enqueues the message at the front only if a free slot is immediately available. Returns false instantly if the queue is full.

Parameters
[in]msg_ptrPointer to the message payload.
Warning
ISR-safe.
Returns
true if the message was enqueued at the front, false if the queue was full.
See also
TryPut, PutFront

Definition at line 171 of file stk_sync_msgqueue.h.

171{ return PutFront(msg_ptr, NO_WAIT); }
bool PutFront(const void *msg_ptr, Timeout timeout_ticks=WAIT_INFINITE)
Put a message into the front of the queue (LIFO / priority-insert order).

References stk::NO_WAIT, and PutFront().

Referenced by stk_msgq_tryputfront(), xMessageBufferReceiveFromISR(), and xQueueSendToFrontFromISR().

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

◆ WaitNotEmpty()

EWaitResult stk::sync::MessageQueue::WaitNotEmpty ( IMutex & cs,
Timeout timeout_ticks )
inlineprivate

Definition at line 471 of file stk_sync_msgqueue.h.

472{
474
475 const bool timed_wait = (timeout_ticks != WAIT_INFINITE) && (timeout_ticks != NO_WAIT);
476
477 // capture an absolute deadline once, before entering the wait loop; a different
478 // consumer can steal the just-produced message (or drain the queue via Get()/TryGet())
479 // between NotifyOne_CS() and this task re-acquiring the critical section (Mesa-style
480 // wakeup, not a direct handoff), so re-passing the original timeout_ticks on each
481 // retry would silently restart it
482 const Timeout deadline = (timed_wait ?
483 static_cast<Timeout>(GetTicks() + timeout_ticks) : timeout_ticks);
484
485 while (m_count == 0U)
486 {
487 Timeout remaining = deadline;
488 if (timed_wait)
489 {
490 const Timeout now = static_cast<Timeout>(GetTicks());
491 remaining = (now >= deadline ? NO_WAIT : (deadline - now));
492 }
493
494 result = m_cv_not_empty.WaitEx(cs, remaining);
495 if (result != WAIT_RESULT_SIGNAL)
496 {
497 // timeout, cancellation or kernel failure
498 break;
499 }
500 }
501
502 return result;
503}
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:170
static Ticks GetTicks()
Get number of ticks elapsed since kernel start.
Definition stk_helper.h:452
static constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:228

References stk::GetTicks(), m_count, m_cv_not_empty, stk::NO_WAIT, stk::WAIT_INFINITE, and stk::WAIT_RESULT_SIGNAL.

Referenced by GetEx(), PeekEx(), and PeekFrontEx().

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

◆ WaitNotFull()

EWaitResult stk::sync::MessageQueue::WaitNotFull ( IMutex & cs,
Timeout timeout_ticks )
inlineprivate

Definition at line 434 of file stk_sync_msgqueue.h.

435{
437
438 const bool timed_wait = (timeout_ticks != WAIT_INFINITE) && (timeout_ticks != NO_WAIT);
439
440 // capture an absolute deadline once, before entering the wait loop; a different
441 // producer can steal the just-freed slot between NotifyOne_CS() and this task
442 // re-acquiring the critical section (Mesa-style wakeup, not a direct handoff),
443 // so re-passing the original timeout_ticks on each retry would silently restart it
444 const Timeout deadline = (timed_wait ?
445 static_cast<Timeout>(GetTicks() + timeout_ticks) : timeout_ticks);
446
447 while (m_count == m_capacity)
448 {
449 Timeout remaining = deadline;
450 if (timed_wait)
451 {
452 const Timeout now = static_cast<Timeout>(GetTicks());
453 remaining = (now >= deadline ? NO_WAIT : (deadline - now));
454 }
455
456 result = m_cv_not_full.WaitEx(cs, remaining);
457 if (result != WAIT_RESULT_SIGNAL)
458 {
459 // timeout, cancellation or kernel failure
460 break;
461 }
462 }
463
464 return result;
465}

References stk::GetTicks(), m_capacity, m_count, m_cv_not_full, stk::NO_WAIT, stk::WAIT_INFINITE, and stk::WAIT_RESULT_SIGNAL.

Referenced by PutEx(), and PutFrontEx().

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

Member Data Documentation

◆ CAPACITY_MAX

const size_t stk::sync::MessageQueue::CAPACITY_MAX = 0xFFFEU
static

Max capacity supported (number of messages).

Definition at line 67 of file stk_sync_msgqueue.h.

Referenced by MessageQueue(), osMessageQueueNew(), PutEx(), PutFrontEx(), tx_queue_create(), xQueueCreate(), xQueueCreateSet(), and xQueueCreateStatic().

◆ m_buffer

uint8_t* stk::sync::MessageQueue::m_buffer
private

flat byte ring-buffer: capacity slots of msg_size bytes each

Definition at line 402 of file stk_sync_msgqueue.h.

Referenced by GetBuffer(), IsStorageValid(), MessageQueue(), and Slot().

◆ m_capacity

const size_t stk::sync::MessageQueue::m_capacity
private

maximum number of messages stored in the queue

Definition at line 403 of file stk_sync_msgqueue.h.

Referenced by GetCapacity(), GetSpace(), IsFull(), MessageQueue(), Next(), Prev(), and WaitNotFull().

◆ m_count

size_t stk::sync::MessageQueue::m_count
private

current number of messages stored in the queue

Definition at line 405 of file stk_sync_msgqueue.h.

Referenced by GetCount(), GetEx(), GetSpace(), IsEmpty(), IsFull(), MessageQueue(), PutEx(), PutFrontEx(), Reset(), WaitNotEmpty(), and WaitNotFull().

◆ m_cv_not_empty

ConditionVariable stk::sync::MessageQueue::m_cv_not_empty
private

signaled by Put() when the queue transitions from empty

Definition at line 408 of file stk_sync_msgqueue.h.

Referenced by PeekEx(), PeekFrontEx(), PutEx(), PutFrontEx(), and WaitNotEmpty().

◆ m_cv_not_full

ConditionVariable stk::sync::MessageQueue::m_cv_not_full
private

signaled by Get()/Reset() when the queue is no longer full

Definition at line 409 of file stk_sync_msgqueue.h.

Referenced by GetEx(), Reset(), and WaitNotFull().

◆ m_head

size_t stk::sync::MessageQueue::m_head
private

write index (next slot to be written by Put())

Definition at line 406 of file stk_sync_msgqueue.h.

Referenced by MessageQueue(), PutEx(), and Reset().

◆ m_msg_size

const size_t stk::sync::MessageQueue::m_msg_size
private

size of each message in bytes

Definition at line 404 of file stk_sync_msgqueue.h.

Referenced by GetEx(), GetMsgSize(), MessageQueue(), PeekEx(), PeekFrontEx(), PutEx(), PutFrontEx(), and Slot().

◆ m_tail

size_t stk::sync::MessageQueue::m_tail
private

read index (next slot to be read by Get())

Definition at line 407 of file stk_sync_msgqueue.h.

Referenced by GetEx(), MessageQueue(), PeekEx(), PeekFrontEx(), PutFrontEx(), and Reset().


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