10#ifndef STK_SYNC_PIPE_H_
11#define STK_SYNC_PIPE_H_
83 explicit Pipe(uint8_t *buf,
size_t capacity,
size_t element_size);
314 size_t DrainLocked(uint8_t *dst_bytes,
size_t count);
330inline Pipe::Pipe(uint8_t *buf,
size_t capacity,
size_t element_size)
386 if ((src !=
nullptr) && (count != 0U))
388 const uint8_t *
const src_bytes =
static_cast<const uint8_t *
>(src);
393 const Timeout deadline = (timed_wait ?
398 while (written < count)
400 bool is_timeout =
false;
408 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
425 const size_t to_write = ((count - written) < available) ? (count - written) : available;
428 if (to_write <= first_part)
492 if (to_read <= first_part)
515 size_t read_count = 0U;
517 if ((dst !=
nullptr) && (count != 0U))
519 uint8_t *
const dst_bytes =
static_cast<uint8_t *
>(dst);
524 const Timeout deadline = (timed_wait ?
529 while (read_count < count)
531 bool is_timeout =
false;
539 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
569 size_t read_count = 0U;
571 if ((dst !=
nullptr) && (max_count != 0U))
574 if (trigger == 0U) { trigger = 1U; }
575 if (trigger > max_count) { trigger = max_count; }
577 uint8_t *
const dst_bytes =
static_cast<uint8_t *
>(dst);
582 const Timeout deadline = (timed_wait ?
593 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
670template <
typename T,
size_t N>
749 if ((src !=
nullptr) && (count != 0U))
755 const Timeout deadline = (timed_wait ?
760 while (written < count)
762 bool is_timeout =
false;
770 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
787 const size_t available = N -
m_count;
788 const size_t to_write = ((count - written) < available) ? (count - written) : available;
793 if (!std::is_scalar<T>::value || (N < 8U))
795 for (
size_t i = 0U; i < to_write; ++i)
804 const size_t first_part = N -
m_head;
806 if (to_write <= first_part)
813 STK_MEMCPY(&
m_buffer[0U], &src[written + first_part], (to_write - first_part) *
sizeof(T));
908 size_t read_count = 0U;
910 if ((dst !=
nullptr) && (count != 0U))
917 const Timeout deadline = (timed_wait ?
922 while (read_count < count)
924 bool is_timeout =
false;
933 remaining = (now >= deadline ?
NO_WAIT : (deadline - now));
950 const size_t to_read = (count - read_count) <
m_count ? (count - read_count) :
m_count;
954 if (!std::is_scalar<T>::value || (N < 8U))
956 for (
size_t i = 0U; i < to_read; ++i)
965 const size_t first_part = N -
m_tail;
967 if (to_read <= first_part)
974 STK_MEMCPY(&dst[read_count + first_part], &
m_buffer[0U], (to_read - first_part) *
sizeof(T));
977 read_count += to_read;
static __stk_forceinline void STK_MEMCPY(void *const dest, const void *const src, const size_t size)
A wrapper for a built-in memcpy, redefine to your own if required.
#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.
constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
int32_t Timeout
Timeout time (ticks).
static Ticks GetTicks()
Get number of ticks elapsed since kernel start.
constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
static constexpr T Min(T a, T b)
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.
bool Read(void *data, Timeout timeout_ticks=WAIT_INFINITE)
Read a single element from the pipe.
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.
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
size_t TryReadBulk(T *dst, size_t count)
Attempt to read multiple elements from the pipe without blocking.
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.
bool Read(T &data, Timeout timeout_ticks=WAIT_INFINITE)
Read data from the pipe.
ConditionVariable m_cv_not_empty
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.