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::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.
EWaitResult WriteEx (const T &data, Timeout timeout_ticks=WAIT_INFINITE)
 Write data to the pipe, preserving the full wait outcome.
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.
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.
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.
EWaitResult ReadEx (T &data, Timeout timeout_ticks=WAIT_INFINITE)
 Read data from the pipe, preserving the full wait outcome.
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.
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 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
PipeT & operator= (const PipeT &)=delete

Private Attributes

T 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.
Note
The boolean / count-returning calls (Write(), Read(), WriteBulk(), ReadBulk()) collapse a timeout and a cancellation (IKernel::CancelTaskWait()) into the same failure result. Use the *Ex() variants (WriteEx(), ReadEx(), WriteBulkEx(), ReadBulkEx()) if the caller needs to tell them apart.
// 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 848 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 853 of file stk_sync_pipe.h.

854 {}
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 1324 of file stk_sync_pipe.h.

1324{ 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 1331 of file stk_sync_pipe.h.

1331{ 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 1337 of file stk_sync_pipe.h.

1337{ 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 1344 of file stk_sync_pipe.h.

1344{ 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 1351 of file stk_sync_pipe.h.

1351{ 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 otherwise (timeout, cancellation or NO_WAIT on an empty pipe). Use ReadEx() to tell these apart.

Definition at line 1145 of file stk_sync_pipe.h.

1146 {
1148 }
EWaitResult ReadEx(T &data, Timeout timeout_ticks=WAIT_INFINITE)
Read data from the pipe, preserving the full wait outcome.

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 or a cancellation occurred. Use ReadBulkEx() to tell these apart.
// 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 1283 of file stk_sync_pipe.h.

1284 {
1285 size_t read_count = 0U;
1288 return read_count;
1289 }
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:715
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.

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

Here is the caller graph for this function:

◆ ReadBulkEx()

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

Read multiple elements from the pipe, preserving the full wait outcome.

Identical to ReadBulk(), except the caller gets the raw EWaitResult and the number of elements read through read_count, so a cancellation (via IKernel::CancelTaskWait()) can be distinguished from a timeout. Elements already copied into dst before a timeout or cancellation stay valid and are counted.

Parameters
[out]dstPointer to the destination array.
[in]countNumber of elements to read.
[out]read_countNumber of elements actually read (always set, 0 on WAIT_RESULT_FAIL).
[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
WAIT_RESULT_SIGNAL if all count elements were read (also for count = 0), WAIT_RESULT_TIMEOUT if the timeout expired (or NO_WAIT was passed) before all elements were available, WAIT_RESULT_CANCELED if the wait was cancelled via IKernel::CancelTaskWait(), WAIT_RESULT_FAIL if dst is nullptr or the kernel rejected the wait. On any non-signal result read_count holds the partial count.

Definition at line 1175 of file stk_sync_pipe.h.

1177 {
1178 read_count = 0U;
1179
1180 // null destination is rejected, an empty request is trivially satisfied
1182
1183 if ((dst != nullptr) && (count != 0U))
1184 {
1186
1187 // capture an absolute deadline once, before entering the wait loop,
1188 // preventing the timeout from resetting on intermediate partial reads
1189 const Timeout deadline = (timed_wait ?
1190 static_cast<Timeout>(GetTicks() + timeout_ticks) : timeout_ticks);
1191
1193
1194 while (read_count < count)
1195 {
1196 // wait until there is at least 1 element available
1197 while (m_count == 0U)
1198 {
1200 if (timed_wait)
1201 {
1202 const Timeout now = static_cast<Timeout>(GetTicks());
1203 remaining = (now >= deadline ? NO_WAIT : (deadline - now));
1204 }
1205
1206 const EWaitResult wr = m_cv_not_empty.WaitEx(cs_, remaining);
1207 if (wr != WAIT_RESULT_SIGNAL)
1208 {
1209 result = wr;
1210 break; // break inner condition variable loop
1211 }
1212 }
1213
1214 // if the wait failed (timeout, cancellation), drop out of the chunk processing loop
1216 {
1217 break;
1218 }
1219
1220 // determine how many we can pull in this stretch
1221 const size_t to_read = (count - read_count) < m_count ? (count - read_count) : m_count;
1222
1223 // note: if value type is not scalar or queue is small we copy with a for loop,
1224 // otherwise using faster memcpy version for large scalar arrays
1225 if (!std::is_scalar<T>::value || (N < 8U))
1226 {
1227 for (size_t i = 0U; i < to_read; ++i)
1228 {
1230 m_tail = (m_tail + 1U) % N;
1231 m_count -= 1U;
1232 }
1233 }
1234 else
1235 {
1236 const size_t first_part = N - m_tail;
1237
1238 if (to_read <= first_part)
1239 {
1240 STK_MEMCPY(&dst[read_count], &m_buffer[m_tail], to_read * sizeof(T));
1241 }
1242 else
1243 {
1246 }
1247
1249 m_tail = (m_tail + to_read) % N;
1250 m_count -= to_read;
1251 }
1252
1253 // notify producers that space is now available
1254 m_cv_not_full.NotifyAll_CS();
1255 }
1256 }
1257
1258 return result;
1259 }
static void STK_MEMCPY(void *const dest, const void *const src, const size_t size)
Implementation of STK_MEMCPY.
Definition stk_arch.h:731
static Ticks GetTicks()
Get number of ticks elapsed since kernel start.
Definition stk_helper.h:452

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

Here is the caller graph for this function:

◆ ReadEx()

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

Read data from the pipe, preserving the full wait outcome.

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

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
WAIT_RESULT_SIGNAL if an element was read, WAIT_RESULT_TIMEOUT if no data became available before the timeout expired (or NO_WAIT was passed on an empty pipe), WAIT_RESULT_CANCELED if the wait was cancelled via IKernel::CancelTaskWait(), WAIT_RESULT_FAIL if the kernel rejected the wait. data is not modified on a non-signal result.

Definition at line 1091 of file stk_sync_pipe.h.

1092 {
1095
1097
1098 // capture an absolute deadline once, before entering the wait loop; a different
1099 // consumer can steal the just-produced element between NotifyOne_CS() and this
1100 // task re-acquiring the critical section (Mesa-style wakeup, not a direct handoff),
1101 // so re-passing the original timeout_ticks on each retry would silently restart it
1102 const Timeout deadline = (timed_wait ?
1103 static_cast<Timeout>(GetTicks() + timeout_ticks) : timeout_ticks);
1104
1105 while (m_count == 0U)
1106 {
1108 if (timed_wait)
1109 {
1110 const Timeout now = static_cast<Timeout>(GetTicks());
1111 remaining = (now >= deadline ? NO_WAIT : (deadline - now));
1112 }
1113
1116 {
1117 // timeout, cancellation or kernel failure: nothing is read
1118 break;
1119 }
1120 }
1121
1123 {
1124 data = m_buffer[m_tail];
1125 m_tail = (m_tail + 1U) % N;
1126 m_count -= 1U;
1127
1128 // notify producer that space is available
1129 m_cv_not_full.NotifyOne_CS();
1130 }
1131
1132 return result;
1133 }

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

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 1307 of file stk_sync_pipe.h.

1308 {
1310
1311 m_count = 0U;
1312 m_head = 0U;
1313 m_tail = 0U;
1314
1315 // wake all blocked producers: the pipe is now entirely empty, every slot is free
1316 // note: we do not release readers here
1317 m_cv_not_full.NotifyAll_CS();
1318 }

◆ 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 1157 of file stk_sync_pipe.h.

1157{ 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 1298 of file stk_sync_pipe.h.

1298{ 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 934 of file stk_sync_pipe.h.

934{ 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 1077 of file stk_sync_pipe.h.

1077{ 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 otherwise (timeout, cancellation or NO_WAIT on a full pipe). Use WriteEx() to tell these apart.

Definition at line 922 of file stk_sync_pipe.h.

923 {
925 }
EWaitResult WriteEx(const T &data, Timeout timeout_ticks=WAIT_INFINITE)
Write data to the pipe, preserving the full wait outcome.

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 or a cancellation occurred. Use WriteBulkEx() to tell these apart.
// 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 1061 of file stk_sync_pipe.h.

1062 {
1063 size_t written = 0U;
1066 return written;
1067 }
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.

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

Here is the caller graph for this function:

◆ WriteBulkEx()

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

Write multiple elements to the pipe, preserving the full wait outcome.

Identical to WriteBulk(), except the caller gets the raw EWaitResult and the number of elements written through written, so a cancellation (via IKernel::CancelTaskWait()) can be distinguished from a timeout. Elements already copied into the pipe before a timeout or cancellation stay in the pipe.

Parameters
[in]srcPointer to the source array.
[in]countNumber of elements to write.
[out]writtenNumber of elements actually written (always set, 0 on WAIT_RESULT_FAIL).
[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
WAIT_RESULT_SIGNAL if all count elements were written (also for count = 0), WAIT_RESULT_TIMEOUT if the timeout expired (or NO_WAIT was passed) before all elements fitted, WAIT_RESULT_CANCELED if the wait was cancelled via IKernel::CancelTaskWait(), WAIT_RESULT_FAIL if src is nullptr or the kernel rejected the wait. On any non-signal result written holds the partial count.

Definition at line 952 of file stk_sync_pipe.h.

954 {
955 written = 0U;
956
957 // null source is rejected, an empty request is trivially satisfied
959
960 if ((src != nullptr) && (count != 0U))
961 {
963
964 // capture an absolute deadline once, before entering the wait loop,
965 // preventing the timeout from resetting on intermediate partial writes
966 const Timeout deadline = (timed_wait ?
967 static_cast<Timeout>(GetTicks() + timeout_ticks) : timeout_ticks);
968
970
971 while (written < count)
972 {
973 // wait until there is at least 1 free slot
974 while (m_count == N)
975 {
977 if (timed_wait)
978 {
979 const Timeout now = static_cast<Timeout>(GetTicks());
980 remaining = (now >= deadline ? NO_WAIT : (deadline - now));
981 }
982
983 const EWaitResult wr = m_cv_not_full.WaitEx(cs_, remaining);
984 if (wr != WAIT_RESULT_SIGNAL)
985 {
986 result = wr;
987 break; // break inner condition variable loop
988 }
989 }
990
991 // if the wait failed (timeout, cancellation), drop out of the chunk processing loop
993 {
994 break;
995 }
996
997 // calculate how many we can copy in this contiguous stretch
998 const size_t available = N - m_count;
999 const size_t to_write = ((count - written) < available) ? (count - written) : available;
1000
1001 // copy from source
1002 // note: if value type is not scalar or queue is small we copy with a for loop,
1003 // otherwise using faster memcpy version for large scalar arrays
1004 if (!std::is_scalar<T>::value || (N < 8U))
1005 {
1006 for (size_t i = 0U; i < to_write; ++i)
1007 {
1008 m_buffer[m_head] = src[written++];
1009 m_head = (m_head + 1U) % N;
1010 m_count += 1U;
1011 }
1012 }
1013 else
1014 {
1015 const size_t first_part = N - m_head;
1016
1017 if (to_write <= first_part)
1018 {
1019 STK_MEMCPY(&m_buffer[m_head], &src[written], to_write * sizeof(T));
1020 }
1021 else
1022 {
1023 STK_MEMCPY(&m_buffer[m_head], &src[written], first_part * sizeof(T));
1024 STK_MEMCPY(&m_buffer[0U], &src[written + first_part], (to_write - first_part) * sizeof(T));
1025 }
1026
1027 written += to_write;
1028 m_head = (m_head + to_write) % N;
1029 m_count += to_write;
1030 }
1031
1032 // notify consumers that data is ready
1033 m_cv_not_empty.NotifyAll_CS();
1034 }
1035 }
1036
1037 return result;
1038 }

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

Here is the caller graph for this function:

◆ WriteEx()

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

Write data to the pipe, preserving the full wait outcome.

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

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
WAIT_RESULT_SIGNAL if data was written, WAIT_RESULT_TIMEOUT if no space became available before the timeout expired (or NO_WAIT was passed on a full pipe), WAIT_RESULT_CANCELED if the wait was cancelled via IKernel::CancelTaskWait(), WAIT_RESULT_FAIL if the kernel rejected the wait. Nothing is written on a non-signal result.

Definition at line 868 of file stk_sync_pipe.h.

869 {
872
874
875 // capture an absolute deadline once, before entering the wait loop; a different
876 // producer can steal the just-freed slot between NotifyOne_CS() and this task
877 // re-acquiring the critical section (Mesa-style wakeup, not a direct handoff),
878 // so re-passing the original timeout_ticks on each retry would silently restart it
879 const Timeout deadline = (timed_wait ?
880 static_cast<Timeout>(GetTicks() + timeout_ticks) : timeout_ticks);
881
882 while (m_count == N)
883 {
885 if (timed_wait)
886 {
887 const Timeout now = static_cast<Timeout>(GetTicks());
888 remaining = (now >= deadline ? NO_WAIT : (deadline - now));
889 }
890
893 {
894 // timeout, cancellation or kernel failure: nothing is written
895 break;
896 }
897 }
898
900 {
902 m_head = (m_head + 1U) % N;
903 m_count += 1U;
904
905 // notify consumer that data is ready
906 m_cv_not_empty.NotifyOne_CS();
907 }
908
909 return result;
910 }

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

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 1356 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 1359 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 1360 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 1361 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 1357 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 1358 of file stk_sync_pipe.h.


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