10#ifndef STK_SYNC_PIPE_H_
11#define STK_SYNC_PIPE_H_
89 explicit Pipe(uint8_t *buf,
size_t capacity,
size_t element_size);
280 size_t read_count = 0U;
345 size_t read_count = 0U;
440 size_t DrainLocked(uint8_t *dst_bytes,
size_t count);
456inline Pipe::Pipe(uint8_t *buf,
size_t capacity,
size_t element_size)
488 const Timeout deadline = (timed_wait ?
497 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
532 if ((src !=
nullptr) && (count != 0U))
534 const uint8_t *
const src_bytes =
static_cast<const uint8_t *
>(src);
539 const Timeout deadline = (timed_wait ?
544 while (written < count)
553 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
571 const size_t to_write = ((count - written) < available) ? (count - written) : available;
574 if (to_write <= first_part)
613 const Timeout deadline = (timed_wait ?
622 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
655 if (to_read <= first_part)
683 if ((dst !=
nullptr) && (count != 0U))
685 uint8_t *
const dst_bytes =
static_cast<uint8_t *
>(dst);
690 const Timeout deadline = (timed_wait ?
695 while (read_count < count)
704 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
741 if ((dst !=
nullptr) && (max_count != 0U))
744 if (trigger == 0U) { trigger = 1U; }
745 if (trigger > max_count) { trigger = max_count; }
747 uint8_t *
const dst_bytes =
static_cast<uint8_t *
>(dst);
752 const Timeout deadline = (timed_wait ?
763 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
847template <
typename T,
size_t N>
879 const Timeout deadline = (timed_wait ?
888 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
960 if ((src !=
nullptr) && (count != 0U))
966 const Timeout deadline = (timed_wait ?
971 while (written < count)
980 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
998 const size_t available = N -
m_count;
999 const size_t to_write = ((count - written) < available) ? (count - written) : available;
1004 if (!std::is_scalar<T>::value || (N < 8U))
1006 for (
size_t i = 0U; i < to_write; ++i)
1015 const size_t first_part = N -
m_head;
1017 if (to_write <= first_part)
1024 STK_MEMCPY(&
m_buffer[0U], &src[written + first_part], (to_write - first_part) *
sizeof(T));
1027 written += to_write;
1063 size_t written = 0U;
1102 const Timeout deadline = (timed_wait ?
1111 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
1183 if ((dst !=
nullptr) && (count != 0U))
1189 const Timeout deadline = (timed_wait ?
1194 while (read_count < count)
1203 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
1221 const size_t to_read = (count - read_count) <
m_count ? (count - read_count) :
m_count;
1225 if (!std::is_scalar<T>::value || (N < 8U))
1227 for (
size_t i = 0U; i < to_read; ++i)
1236 const size_t first_part = N -
m_tail;
1238 if (to_read <= first_part)
1245 STK_MEMCPY(&dst[read_count + first_part], &
m_buffer[0U], (to_read - first_part) *
sizeof(T));
1248 read_count += to_read;
1285 size_t read_count = 0U;
static void STK_MEMCPY(void *const dest, const void *const src, const size_t size)
Implementation of STK_MEMCPY.
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
#define STK_NONCOPYABLE_CLASS(TYPE)
Disables copy construction and assignment for a class.
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Implementation of synchronization primitive: stk::sync::ConditionVariable.
Namespace of STK package.
static constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
EWaitResult
Wait result (see IKernelService::Wait).
@ WAIT_RESULT_FAIL
IKernelService::Wait returned with error without waiting.
@ WAIT_RESULT_SIGNAL
The wake was caused by a signal.
int32_t Timeout
Timeout time (ticks).
static Ticks GetTicks()
Get number of ticks elapsed since kernel start.
static constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
static constexpr T Min(T a, T b) noexcept
Compile-time minimum of two values.
Synchronization primitives for task coordination and resource protection.
RAII-style low-level synchronization primitive for atomic code execution. Used as building brick for ...
Condition Variable primitive for signaling between tasks based on specific predicates.
size_t WriteBulk(const void *src, size_t count, Timeout timeout_ticks=WAIT_INFINITE)
Write multiple elements to the pipe.
bool TryRead(void *data)
Attempt to read a single element from the pipe without blocking.
const size_t m_capacity
maximum number of elements stored in the pipe
~Pipe()=default
Destructor.
size_t TryReadBulkTriggered(void *dst, size_t max_count)
Non-blocking variant of ReadBulkTriggered.
void Reset()
Discard all elements and reset the pipe to the empty state.
EWaitResult WriteBulkEx(const void *src, size_t count, size_t &written, Timeout timeout_ticks=WAIT_INFINITE)
Write multiple elements to the pipe, preserving the full wait outcome.
bool Read(void *data, Timeout timeout_ticks=WAIT_INFINITE)
Read a single element from the pipe.
EWaitResult ReadBulkTriggeredEx(void *dst, size_t trigger, size_t max_count, size_t &read_count, Timeout timeout_ticks=WAIT_INFINITE)
Read at least trigger elements, then drain up to max_count without blocking, preserving the full wait...
EWaitResult ReadBulkEx(void *dst, size_t count, size_t &read_count, Timeout timeout_ticks=WAIT_INFINITE)
Read multiple elements from the pipe, preserving the full wait outcome.
EWaitResult ReadEx(void *data, Timeout timeout_ticks=WAIT_INFINITE)
Read a single element from the pipe, preserving the full wait outcome.
size_t ReadBulk(void *dst, size_t count, Timeout timeout_ticks=WAIT_INFINITE)
Read multiple elements from the pipe.
uint8_t * Slot(size_t idx) const
ConditionVariable m_cv_not_full
signaled by Read()/Reset() when the pipe is no longer full
bool Write(const void *data, Timeout timeout_ticks=WAIT_INFINITE)
Write a single element to the pipe.
size_t GetElementSize() const
Get the size of each element in bytes.
size_t m_head
write index (next slot to be written by Write())
size_t TryWriteBulk(const void *src, size_t count)
Attempt to write multiple elements to the pipe without blocking.
bool IsEmpty() const
Check if the pipe is currently empty.
EWaitResult WriteEx(const void *data, Timeout timeout_ticks=WAIT_INFINITE)
Write a single element to the pipe, preserving the full wait outcome.
size_t GetCapacity() const
Get the maximum number of elements the pipe can hold.
size_t Next(size_t idx) const
bool TryWrite(const void *data)
Attempt to write a single element to the pipe without blocking.
size_t GetCount() const
Get the current number of elements in the pipe.
ConditionVariable m_cv_not_empty
signaled by Write() when the pipe transitions from empty
bool IsFull() const
Check if the pipe is currently full.
size_t TryReadBulk(void *dst, size_t count)
Attempt to read multiple elements from the pipe without blocking.
const size_t m_element_size
size of each element in bytes
static const size_t CAPACITY_MAX
Max capacity supported (number of elements).
Pipe(uint8_t *buf, size_t capacity, size_t element_size)
Constructor.
size_t m_tail
read index (next slot to be read by Read())
uint8_t * m_buffer
flat byte ring-buffer: capacity slots of element_size bytes each
size_t DrainLocked(uint8_t *dst_bytes, size_t count)
size_t GetSpace() const
Get the number of free slots currently available.
size_t ReadBulkTriggered(void *dst, size_t trigger, size_t max_count, Timeout timeout_ticks=WAIT_INFINITE)
Read at least trigger elements, then drain up to max_count without blocking.
bool IsStorageValid() const
Verify that the backing storage is valid and the pipe is ready for use.
uint8_t * GetBuffer()
Get a pointer to the raw backing buffer.
size_t m_count
current number of elements stored in the pipe
EWaitResult ReadBulkEx(T *dst, size_t count, size_t &read_count, Timeout timeout_ticks=WAIT_INFINITE)
Read multiple elements from the pipe, preserving the full wait outcome.
size_t TryReadBulk(T *dst, size_t count)
Attempt to read multiple elements from the pipe without blocking.
EWaitResult WriteBulkEx(const T *src, size_t count, size_t &written, Timeout timeout_ticks=WAIT_INFINITE)
Write multiple elements to the pipe, preserving the full wait outcome.
ConditionVariable m_cv_not_full
size_t GetCount() const
Get the current number of elements in the pipe.
bool IsEmpty() const
Check if the pipe is currently empty.
size_t ReadBulk(T *dst, size_t count, Timeout timeout_ticks=WAIT_INFINITE)
Read multiple elements from the pipe.
bool Write(const T &data, Timeout timeout_ticks=WAIT_INFINITE)
Write data to the pipe.
bool TryRead(T &data)
Attempt to read data from the pipe without blocking.
EWaitResult WriteEx(const T &data, Timeout timeout_ticks=WAIT_INFINITE)
Write data to the pipe, preserving the full wait outcome.
bool Read(T &data, Timeout timeout_ticks=WAIT_INFINITE)
Read data from the pipe.
ConditionVariable m_cv_not_empty
EWaitResult ReadEx(T &data, Timeout timeout_ticks=WAIT_INFINITE)
Read data from the pipe, preserving the full wait outcome.
bool TryWrite(const T &data)
Attempt to write data to the pipe without blocking.
size_t TryWriteBulk(const T *src, size_t count)
Attempt to write multiple elements to the pipe without blocking.
size_t WriteBulk(const T *src, size_t count, Timeout timeout_ticks=WAIT_INFINITE)
Write multiple elements to the pipe.
void Reset()
Discard all elements and reset the pipe to the empty state.
bool IsFull() const
Check if the pipe is currently full.
size_t GetSpace() const
Get the number of free slots currently available.
size_t GetCapacity() const
Get the maximum number of elements the pipe can hold.