SuperTinyKernel™ RTOS 1.06.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk::sync::PipeT< T, N > Class Template Reference

Thread-safe, type-safe FIFO communication pipe with internal storage. More...

#include <stk_sync_pipe.h>

Inheritance diagram for stk::sync::PipeT< T, N >:
Collaboration diagram for stk::sync::PipeT< T, N >:

Public Member Functions

 PipeT ()
 Constructor.
bool Write (const T &data, Timeout timeout_ticks=WAIT_INFINITE)
 Write data to the pipe.
bool TryWrite (const T &data)
 Attempt to write data 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.
size_t TryWriteBulk (const T *src, size_t count)
 Attempt to write multiple elements to the pipe without blocking.
bool Read (T &data, Timeout timeout_ticks=WAIT_INFINITE)
 Read data from the pipe.
bool TryRead (T &data)
 Attempt to read data from the pipe without blocking.
size_t ReadBulk (T *dst, size_t count, Timeout timeout_ticks=WAIT_INFINITE)
 Read multiple elements from the pipe.
size_t TryReadBulk (T *dst, size_t count)
 Attempt to read multiple elements from the pipe without blocking.
void Reset ()
 Discard all elements and reset the pipe to the empty state.
size_t GetCapacity () const
 Get the maximum number of elements the pipe can hold.
size_t GetCount () const
 Get the current number of elements in the pipe.
size_t GetSpace () const
 Get the number of free slots currently available.
bool IsEmpty () const
 Check if the pipe is currently empty.
bool IsFull () const
 Check if the pipe is currently full.

Private Member Functions

 PipeT (const PipeT &)=delete
PipeToperator= (const PipeT &)=delete

Private Attributes

m_buffer [N]
 static storage for FIFO elements
size_t m_head
 index of the next slot to be written (producer)
size_t m_tail
 index of the next slot to be read (consumer)
size_t m_count
 current number of elements stored in the pipe
ConditionVariable m_cv_not_empty
 condition variable signaled when the pipe is no longer empty
ConditionVariable m_cv_not_full
 condition variable signaled when the pipe is no longer full

Detailed Description

template<typename T, size_t N>
class stk::sync::PipeT< T, N >

Thread-safe, type-safe FIFO communication pipe with internal storage.

Template Parameters
TData type of elements.
NCapacity of the pipe (number of elements).

PipeT provides a synchronized ring-buffer mechanism that allows tasks to exchange typed data safely. It implements blocking semantics:

  • Write() blocks if the pipe is full until space becomes available.
  • Read() blocks if the pipe is empty until data is produced.

Unlike stk::sync::Pipe, which operates on raw byte buffers and uses memcpy for all transfers, PipeT is parameterised on a concrete element type T. This enables:

  • Direct typed assignment (no memcpy overhead for scalar types).
  • Compile-time constant propagation for capacity N and element size, allowing the compiler to strength-reduce modulo operations and eliminate dead branches in bulk transfer paths.
  • A fully type-safe call interface using T references and pointers.
// Example: Producer-Consumer pattern
void Task_Producer() {
uint32_t value = 42;
// blocks if pipe is full
g_DataPipe.Write(value);
}
void Task_Consumer() {
uint32_t received;
// blocks until data is available, with a 1 s timeout
if (g_DataPipe.Read(received, 1000)) {
// ... process received value ...
}
}
Thread-safe, type-safe FIFO communication pipe with internal storage.
bool Write(const T &data, Timeout timeout_ticks=WAIT_INFINITE)
Write data to the pipe.
bool Read(T &data, Timeout timeout_ticks=WAIT_INFINITE)
Read data from the pipe.
See also
Pipe, MessageQueueT, ConditionVariable
Note
Only available when kernel is compiled with KERNEL_SYNC mode enabled.

Definition at line 671 of file stk_sync_pipe.h.

Constructor & Destructor Documentation

◆ PipeT() [1/2]

template<typename T, size_t N>
stk::sync::PipeT< T, N >::PipeT ( )
inlineexplicit

Constructor.

Definition at line 676 of file stk_sync_pipe.h.

677 {}
size_t m_head
index of the next slot to be written (producer)
ConditionVariable m_cv_not_full
condition variable signaled when the pipe is no longer full
ConditionVariable m_cv_not_empty
condition variable signaled when the pipe is no longer empty
size_t m_tail
index of the next slot to be read (consumer)
T m_buffer[N]
static storage for FIFO elements
size_t m_count
current number of elements stored in the pipe

◆ PipeT() [2/2]

template<typename T, size_t N>
stk::sync::PipeT< T, N >::PipeT ( const PipeT< T, N > & )
privatedelete

Member Function Documentation

◆ GetCapacity()

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::GetCapacity ( ) const
inline

Get the maximum number of elements the pipe can hold.

Returns
Compile-time capacity N.
Note
ISR-safe.

Definition at line 1023 of file stk_sync_pipe.h.

1023{ return N; }

◆ GetCount()

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::GetCount ( ) const
inline

Get the current number of elements in the pipe.

Returns
Point-in-time snapshot of the element 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 1030 of file stk_sync_pipe.h.

1030{ return m_count; }

◆ GetSpace()

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::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 1036 of file stk_sync_pipe.h.

1036{ return (N - m_count); }

◆ IsEmpty()

template<typename T, size_t N>
bool stk::sync::PipeT< T, N >::IsEmpty ( ) const
inline

Check if the pipe is currently empty.

Returns
true if empty, otherwise false.
Note
The returned value is a point-in-time snapshot.
ISR-safe.

Definition at line 1043 of file stk_sync_pipe.h.

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

◆ IsFull()

template<typename T, size_t N>
bool stk::sync::PipeT< T, N >::IsFull ( ) const
inline

Check if the pipe is currently full.

Returns
true if full, otherwise false.
Note
The returned value is a point-in-time snapshot.
ISR-safe.

Definition at line 1050 of file stk_sync_pipe.h.

1050{ return (m_count == N); }

◆ operator=()

template<typename T, size_t N>
PipeT & stk::sync::PipeT< T, N >::operator= ( const PipeT< T, N > & )
privatedelete

◆ Read()

template<typename T, size_t N>
bool stk::sync::PipeT< T, N >::Read ( T & data,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Read data from the pipe.

Attempts to retrieve an element from the FIFO queue. If pipe is empty, the calling task will be suspended until data is provided by a producer or the timeout expires.

Parameters
[out]dataReference to the variable where the retrieved data will be stored.
[in]timeout_ticksMaximum time to wait for data (ticks). Default: WAIT_INFINITE.
Warning
ISR-safe only with timeout_ticks=NO_WAIT, ISR-unsafe otherwise.
Returns
true if data was successfully read, false if timeout expired before any data became available.

Definition at line 849 of file stk_sync_pipe.h.

850 {
852 bool success = true;
853
854 while (m_count == 0U)
855 {
856 if (!m_cv_not_empty.Wait(cs_, timeout_ticks))
857 {
858 success = false;
859 break;
860 }
861 }
862
863 if (success)
864 {
866 m_tail = (m_tail + 1U) % N;
867 m_count -= 1U;
868
869 // notify producer that space is available
870 m_cv_not_full.NotifyOne_CS();
871 }
872
873 return success;
874 }

Referenced by stk::sync::PipeT< Timer *, 32U >::TryRead().

Here is the caller graph for this function:

◆ ReadBulk()

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::ReadBulk ( T * dst,
size_t count,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Read multiple elements from the pipe.

Attempts to retrieve a block of data from the FIFO. If pipe does not contain enough elements to satisfy the requested count, it will block until the full amount is read or the timeout expires.

Parameters
[out]dstPointer to the destination array.
[in]countNumber of elements to read.
[in]timeout_ticksMaximum time to wait for data (ticks). Default: WAIT_INFINITE.
Warning
ISR-safe only with timeout_ticks=NO_WAIT, ISR-unsafe otherwise.
Returns
Number of elements actually read. Equal to count unless a timeout occurred.
// Example:
Sample frame[64];
size_t result = g_Pipe.ReadBulk(frame, 64, 500);
if (result == 64) {
// process full frame
} else {
// handle partial read / timeout
}

Definition at line 906 of file stk_sync_pipe.h.

907 {
908 size_t read_count = 0U;
909
910 if ((dst != nullptr) && (count != 0U))
911 {
913
914 // capture an absolute deadline once, before entering the wait loop,
915 // this prevents the timeout from being silently restarted on each
916 // spurious wakeup (e.g. a partial Set() that does not satisfy WAIT_ALL)
917 const Timeout deadline = (timed_wait ?
918 static_cast<Timeout>(GetTicks() + timeout_ticks) : timeout_ticks);
919
921
922 while (read_count < count)
923 {
924 bool is_timeout = false;
925
926 // wait until there is at least 1 element available
927 while (m_count == 0U)
928 {
930 if (timed_wait)
931 {
932 const Timeout now = static_cast<Timeout>(GetTicks());
933 remaining = (now >= deadline ? NO_WAIT : (deadline - now));
934 }
935
936 if (!m_cv_not_empty.Wait(cs_, remaining))
937 {
938 is_timeout = true;
939 break; // break inner condition variable loop
940 }
941 }
942
943 // if a timeout, drop out of the chunk processing loop
944 if (is_timeout)
945 {
946 break;
947 }
948
949 // determine how many we can pull in this stretch
950 const size_t to_read = (count - read_count) < m_count ? (count - read_count) : m_count;
951
952 // note: if value type is not scalar or queue is small we copy with a for loop,
953 // otherwise using faster memcpy version for large scalar arrays
954 if (!std::is_scalar<T>::value || (N < 8U))
955 {
956 for (size_t i = 0U; i < to_read; ++i)
957 {
959 m_tail = (m_tail + 1U) % N;
960 m_count -= 1U;
961 }
962 }
963 else
964 {
965 const size_t first_part = N - m_tail;
966
967 if (to_read <= first_part)
968 {
970 }
971 else
972 {
975 }
976
978 m_tail = (m_tail + to_read) % N;
979 m_count -= to_read;
980 }
981
982 // notify producers that space is now available
983 m_cv_not_full.NotifyAll_CS();
984 }
985 }
986
987 return read_count;
988 }
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.
Definition stk_arch.h:534
static Ticks GetTicks()
Get number of ticks elapsed since kernel start.
Definition stk_helper.h:319

Referenced by stk::sync::PipeT< Timer *, 32U >::TryReadBulk().

Here is the caller graph for this function:

◆ Reset()

template<typename T, size_t N>
void stk::sync::PipeT< T, N >::Reset ( )
inline

Discard all elements and reset the pipe to the empty state.

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

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

Definition at line 1006 of file stk_sync_pipe.h.

1007 {
1009
1010 m_count = 0U;
1011 m_head = 0U;
1012 m_tail = 0U;
1013
1014 // wake all blocked producers: the pipe is now entirely empty, every slot is free
1015 // note: we do not release readers here
1016 m_cv_not_full.NotifyAll_CS();
1017 }

◆ TryRead()

template<typename T, size_t N>
bool stk::sync::PipeT< T, N >::TryRead ( T & data)
inline

Attempt to read data from the pipe without blocking.

Dequeues an element only if one is immediately available. Returns false instantly if the pipe is empty.

Parameters
[out]dataReference to the variable where the retrieved data will be stored.
Warning
ISR-safe.
Returns
true if data was successfully read, false if the pipe was empty.

Definition at line 883 of file stk_sync_pipe.h.

883{ return Read(data, NO_WAIT); }

◆ TryReadBulk()

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::TryReadBulk ( T * dst,
size_t count )
inline

Attempt to read multiple elements from the pipe without blocking.

Reads as many elements as are currently available without blocking.

Parameters
[out]dstPointer to the destination array.
[in]countNumber of elements to read.
Warning
ISR-safe.
Returns
Number of elements actually read.

Definition at line 997 of file stk_sync_pipe.h.

997{ return ReadBulk(dst, count, NO_WAIT); }
size_t ReadBulk(T *dst, size_t count, Timeout timeout_ticks=WAIT_INFINITE)
Read multiple elements from the pipe.

◆ TryWrite()

template<typename T, size_t N>
bool stk::sync::PipeT< T, N >::TryWrite ( const T & data)
inline

Attempt to write data to the pipe without blocking.

Enqueues the element only if a free slot is immediately available. Returns false instantly if the pipe is full.

Parameters
[in]dataReference to the data element to be copied into the pipe.
Warning
ISR-safe.
Returns
true if data was successfully written, false if no space is available.

Definition at line 723 of file stk_sync_pipe.h.

723{ return Write(data, NO_WAIT); }

◆ TryWriteBulk()

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::TryWriteBulk ( const T * src,
size_t count )
inline

Attempt to write multiple elements to the pipe without blocking.

Copies as many elements as possible without blocking. Elements that do not fit are discarded.

Parameters
[in]srcPointer to the source array.
[in]countNumber of elements to write.
Warning
ISR-safe.
Returns
Number of elements actually written.

Definition at line 837 of file stk_sync_pipe.h.

837{ return WriteBulk(src, count, NO_WAIT); }
size_t WriteBulk(const T *src, size_t count, Timeout timeout_ticks=WAIT_INFINITE)
Write multiple elements to the pipe.

◆ Write()

template<typename T, size_t N>
bool stk::sync::PipeT< T, N >::Write ( const T & data,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Write data to the pipe.

Attempts to push an element into the FIFO queue. If pipe is full, the calling task will be suspended until space is made available by a consumer or the timeout expires.

Parameters
[in]dataReference to the data element to be copied into the pipe.
[in]timeout_ticksMaximum time to wait for space (ticks). Default: WAIT_INFINITE.
Warning
ISR-safe only with timeout_ticks=NO_WAIT, ISR-unsafe otherwise.
Returns
true if data was successfully written, false if timeout expired before space became available.

Definition at line 689 of file stk_sync_pipe.h.

690 {
692 bool success = true;
693
694 while (m_count == N)
695 {
696 if (!m_cv_not_full.Wait(cs_, timeout_ticks))
697 {
698 success = false;
699 break;
700 }
701 }
702
703 if (success)
704 {
706 m_head = (m_head + 1U) % N;
707 m_count += 1U;
708
709 // notify consumer that data is ready
710 m_cv_not_empty.NotifyOne_CS();
711 }
712
713 return success;
714 }

Referenced by stk::sync::PipeT< Timer *, 32U >::TryWrite().

Here is the caller graph for this function:

◆ WriteBulk()

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::WriteBulk ( const T * src,
size_t count,
Timeout timeout_ticks = WAIT_INFINITE )
inline

Write multiple elements to the pipe.

Copies a block of data into the FIFO. If the pipe does not have enough space for the entire block, it will block until the full amount can be written or the timeout expires.

Parameters
[in]srcPointer to the source array.
[in]countNumber of elements to write.
[in]timeout_ticksMaximum time to wait for sufficient space (ticks). Default: WAIT_INFINITE.
Warning
ISR-safe only with timeout_ticks=NO_WAIT, ISR-unsafe otherwise.
Returns
Number of elements actually written. Equal to count unless a timeout occurred.
// Example:
Sample frame[64];
FillFrame(frame);
size_t result = g_Pipe.WriteBulk(frame, 64, 500);
if (result < 64) {
// handle partial write / timeout
}

Definition at line 745 of file stk_sync_pipe.h.

746 {
747 size_t written = 0U;
748
749 if ((src != nullptr) && (count != 0U))
750 {
752
753 // capture an absolute deadline once, before entering the wait loop,
754 // preventing the timeout from resetting on intermediate partial writes
755 const Timeout deadline = (timed_wait ?
756 static_cast<Timeout>(GetTicks() + timeout_ticks) : timeout_ticks);
757
759
760 while (written < count)
761 {
762 bool is_timeout = false;
763
764 while (m_count == N)
765 {
767 if (timed_wait)
768 {
769 const Timeout now = static_cast<Timeout>(GetTicks());
770 remaining = (now >= deadline ? NO_WAIT : (deadline - now));
771 }
772
773 if (!m_cv_not_full.Wait(cs_, remaining))
774 {
775 is_timeout = true;
776 break; // break inner condition variable loop
777 }
778 }
779
780 // if timeout, drop out of the chunk processing loop
781 if (is_timeout)
782 {
783 break;
784 }
785
786 // calculate how many we can copy in this contiguous stretch
787 const size_t available = N - m_count;
788 const size_t to_write = ((count - written) < available) ? (count - written) : available;
789
790 // copy from source
791 // note: if value type is not scalar or queue is small we copy with a for loop,
792 // otherwise using faster memcpy version for large scalar arrays
793 if (!std::is_scalar<T>::value || (N < 8U))
794 {
795 for (size_t i = 0U; i < to_write; ++i)
796 {
798 m_head = (m_head + 1U) % N;
799 m_count += 1U;
800 }
801 }
802 else
803 {
804 const size_t first_part = N - m_head;
805
806 if (to_write <= first_part)
807 {
808 STK_MEMCPY(&m_buffer[m_head], &src[written], to_write * sizeof(T));
809 }
810 else
811 {
814 }
815
816 written += to_write;
817 m_head = (m_head + to_write) % N;
818 m_count += to_write;
819 }
820
821 // notify consumers that data is ready
822 m_cv_not_empty.NotifyAll_CS();
823 }
824 }
825
826 return written;
827 }

Referenced by stk::sync::PipeT< Timer *, 32U >::TryWriteBulk().

Here is the caller graph for this function:

Member Data Documentation

◆ m_buffer

template<typename T, size_t N>
T stk::sync::PipeT< T, N >::m_buffer[N]
private

static storage for FIFO elements

Definition at line 1055 of file stk_sync_pipe.h.

◆ m_count

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::m_count
private

current number of elements stored in the pipe

Definition at line 1058 of file stk_sync_pipe.h.

◆ m_cv_not_empty

template<typename T, size_t N>
ConditionVariable stk::sync::PipeT< T, N >::m_cv_not_empty
private

condition variable signaled when the pipe is no longer empty

Definition at line 1059 of file stk_sync_pipe.h.

◆ m_cv_not_full

template<typename T, size_t N>
ConditionVariable stk::sync::PipeT< T, N >::m_cv_not_full
private

condition variable signaled when the pipe is no longer full

Definition at line 1060 of file stk_sync_pipe.h.

◆ m_head

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::m_head
private

index of the next slot to be written (producer)

Definition at line 1056 of file stk_sync_pipe.h.

◆ m_tail

template<typename T, size_t N>
size_t stk::sync::PipeT< T, N >::m_tail
private

index of the next slot to be read (consumer)

Definition at line 1057 of file stk_sync_pipe.h.


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