libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
LibXR::SPSCQueueBase Class Reference

单生产者单消费者字节队列内核 / Single-producer single-consumer byte-queue core More...

#include <spsc_queue_base.hpp>

Inheritance diagram for LibXR::SPSCQueueBase:
[legend]

Public Types

using IndexType = size_t
 环形缓冲区索引类型 / Ring-buffer index type.
 

Public Member Functions

 SPSCQueueBase (size_t element_size, size_t capacity)
 构造 SPSC 字节队列内核 / Construct the SPSC byte-queue core
 
 SPSCQueueBase (size_t element_size, size_t element_align, size_t capacity)
 构造 SPSC 字节队列内核并指定元素对齐 / Construct the SPSC byte-queue core with explicit element alignment
 
 ~SPSCQueueBase ()
 析构 SPSC 字节队列内核 / Destroy the SPSC byte-queue core
 
ErrorCode PushBytes (const void *value)
 按字节入队一个 payload / Enqueue one payload by bytes
 
ErrorCode PopBytes (void *value=nullptr)
 按字节出队一个 payload;传空指针时仅丢弃队头元素 / Dequeue one payload by bytes; pass null to discard the front item only
 
ErrorCode PeekBytes (void *value)
 按字节查看一个队头 payload 但不出队 / Peek one front payload by bytes without dequeuing it
 
ErrorCode PushBatchBytes (const void *data, size_t count)
 按字节批量入队多个 payload / Enqueue multiple payloads by bytes
 
template<typename Writer >
ErrorCode PushBytesWithWriter (size_t count, Writer &&writer)
 通过写入器回调批量入队 payload / Enqueue payloads through a writer callback
 
template<typename Writer >
size_t ProduceWithWriter (size_t limit, Writer &&writer)
 通过一次双 span 回调生产 payload 前缀 / Produce a payload prefix through one two-span writer callback.
 
ErrorCode PopBatchBytes (void *data, size_t count)
 按字节批量出队多个 payload / Dequeue multiple payloads by bytes
 
template<typename Reader >
ErrorCode PopBytesWithReader (size_t count, Reader &&reader)
 通过读取器回调批量出队 payload / Dequeue payloads through a reader callback
 
template<typename Reader >
size_t ConsumeWithReader (size_t limit, Reader &&reader)
 通过一次双 span 回调消费 payload 前缀 / Consume a payload prefix through one two-span reader callback.
 
ErrorCode PeekBatchBytes (void *data, size_t count)
 按字节批量查看多个 payload 但不出队 / Peek multiple payloads by bytes without dequeuing them
 
void Reset ()
 从 consumer 侧丢弃当前可见的全部 payload / Discard all currently available payloads from the consumer side
 
size_t Size () const
 获取当前已用元素数 / Get the current element count
 
size_t EmptySize () const
 获取剩余空槽数 / Get the current free-slot count
 
size_t MaxSize () const
 获取队列最大容量 / Get the maximum queue capacity
 

Detailed Description

单生产者单消费者字节队列内核 / Single-producer single-consumer byte-queue core

这个内核只负责 SPSC ring 的索引推进、容量判断与原始字节存储,不包含多消费者 抢占逻辑,也不暴露任何 CAS 路径。上层 SPSCQueue<Data> 只负责把具体类型 Data 映射到这些字节槽位。

This core contains only the SPSC ring progression, capacity checks, and raw byte storage. It does not include any multi-consumer claiming logic or expose any CAS-based path. The upper SPSCQueue<Data> wrapper is responsible only for mapping the concrete Data type onto these byte slots.

Definition at line 27 of file spsc_queue_base.hpp.

Member Typedef Documentation

◆ IndexType

环形缓冲区索引类型 / Ring-buffer index type.

Definition at line 30 of file spsc_queue_base.hpp.

Constructor & Destructor Documentation

◆ SPSCQueueBase() [1/2]

LibXR::SPSCQueueBase::SPSCQueueBase ( size_t element_size,
size_t capacity )
inline

构造 SPSC 字节队列内核 / Construct the SPSC byte-queue core

Parameters
element_size单个 payload 的字节数 / Byte size of one payload
capacity队列容量 / Queue capacity

Definition at line 37 of file spsc_queue_base.hpp.

38 : element_size_(element_size),
39 capacity_(capacity),
40 payload_alloc_align_(alignof(std::max_align_t)),
41 payload_stride_(ComputeStride(element_size, alignof(std::byte))),
42 payloads_(nullptr),
43 head_(0),
44 tail_(0)
45 {
46 InitStorage();
47 }

◆ SPSCQueueBase() [2/2]

LibXR::SPSCQueueBase::SPSCQueueBase ( size_t element_size,
size_t element_align,
size_t capacity )
inline

构造 SPSC 字节队列内核并指定元素对齐 / Construct the SPSC byte-queue core with explicit element alignment

Parameters
element_size单个 payload 的字节数 / Byte size of one payload
element_align单个 payload 的对齐要求 / Alignment requirement of one payload
capacity队列容量 / Queue capacity

Definition at line 56 of file spsc_queue_base.hpp.

57 : element_size_(element_size),
58 capacity_(capacity),
59 payload_alloc_align_(alignof(std::max_align_t)),
60 payload_stride_(ComputeStride(element_size, element_align)),
61 payloads_(nullptr),
62 head_(0),
63 tail_(0)
64 {
65 InitStorage();
66 }

◆ ~SPSCQueueBase()

LibXR::SPSCQueueBase::~SPSCQueueBase ( )
inline

析构 SPSC 字节队列内核 / Destroy the SPSC byte-queue core

Definition at line 88 of file spsc_queue_base.hpp.

89 {
90 ::operator delete[](payloads_, std::align_val_t(payload_alloc_align_));
91 }

Member Function Documentation

◆ ConsumeWithReader()

template<typename Reader >
size_t LibXR::SPSCQueueBase::ConsumeWithReader ( size_t limit,
Reader && reader )
inline

通过一次双 span 回调消费 payload 前缀 / Consume a payload prefix through one two-span reader callback.

Template Parameters
Reader读取器类型 / Reader callback type.
Parameters
limit最多提供的 payload 个数 / Maximum number of offered payloads.
reader接收两段数据和元素数,返回已接受的前缀个数 / Receives two data pointers and element counts; returns the accepted prefix count.
Returns
实际从队列移除的 payload 个数 / Number of payloads removed from the queue.
Precondition
队列只有一个 consumer;回调期间不得重入同侧操作或 Reset / The queue has one consumer; no same-side operation or Reset during the callback.
Note
可提供数量为零时不调用回调;返回值不得超过可提供数量;所有指针只在回调期间有效 / The callback is skipped when the offered count is zero and must return no more than the offered count; all pointers are valid only during the callback.

Definition at line 438 of file spsc_queue_base.hpp.

439 {
440 if (limit == 0U)
441 {
442 return 0U;
443 }
444
445 const auto current_head = head_.load(std::memory_order_relaxed);
446 const auto current_tail = tail_.load(std::memory_order_acquire);
447 const size_t capacity = RingCapacity();
448 const size_t available = (current_tail >= current_head)
449 ? (current_tail - current_head)
450 : (capacity - current_head + current_tail);
451 const size_t offered = std::min(limit, available);
452 if (offered == 0U)
453 {
454 return 0U;
455 }
456
457 const size_t first_count = std::min(offered, capacity - current_head);
458 const size_t second_count = offered - first_count;
459 const void* const second = second_count == 0U ? nullptr : PayloadPtr(0U);
460 const size_t accepted =
461 reader(PayloadPtr(current_head), first_count, second, second_count);
462 ASSERT(accepted <= offered);
463 if (accepted != 0U)
464 {
465 head_.store((current_head + accepted) % capacity, std::memory_order_release);
466 }
467 return accepted;
468 }

◆ EmptySize()

size_t LibXR::SPSCQueueBase::EmptySize ( ) const
inline

获取剩余空槽数 / Get the current free-slot count

Returns
当前空槽个数 / Current number of free slots

Definition at line 549 of file spsc_queue_base.hpp.

549{ return capacity_ - Size(); }
size_t Size() const
获取当前已用元素数 / Get the current element count

◆ MaxSize()

size_t LibXR::SPSCQueueBase::MaxSize ( ) const
inline

获取队列最大容量 / Get the maximum queue capacity

Returns
队列容量 / Queue capacity

Definition at line 555 of file spsc_queue_base.hpp.

555{ return capacity_; }

◆ PeekBatchBytes()

ErrorCode LibXR::SPSCQueueBase::PeekBatchBytes ( void * data,
size_t count )
inline

按字节批量查看多个 payload 但不出队 / Peek multiple payloads by bytes without dequeuing them

Parameters
data用于接收 payload 的字节缓冲区 / Byte buffer receiving payloads
countpayload 个数 / Number of payloads
Returns
成功返回 ErrorCode::OK;元素不足返回 ErrorCode::EMPTY; count 不为 0 且 data 为空时返回 ErrorCode::PTR_NULL Returns ErrorCode::OK on success; returns ErrorCode::EMPTY when there are not enough payloads available; returns ErrorCode::PTR_NULL when data is null and count is not 0

Definition at line 481 of file spsc_queue_base.hpp.

482 {
483 if (count == 0U)
484 {
485 return ErrorCode::OK;
486 }
487 if (data == nullptr)
488 {
489 return ErrorCode::PTR_NULL;
490 }
491
492 const auto current_head = head_.load(std::memory_order_relaxed);
493 const auto current_tail = tail_.load(std::memory_order_acquire);
494 const size_t capacity = RingCapacity();
495 const size_t available = (current_tail >= current_head)
496 ? (current_tail - current_head)
497 : (capacity - current_head + current_tail);
498
499 if (available < count)
500 {
501 return ErrorCode::EMPTY;
502 }
503
504 auto* dst = static_cast<std::byte*>(data);
505 for (size_t index = 0; index < count; ++index)
506 {
507 LibXR::Memory::FastCopy(dst + index * element_size_,
508 PayloadPtr((current_head + index) % capacity),
509 element_size_);
510 }
511 return ErrorCode::OK;
512 }
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
@ PTR_NULL
空指针 / Null pointer
@ EMPTY
为空 / Empty
@ OK
操作成功 / Operation successful

◆ PeekBytes()

ErrorCode LibXR::SPSCQueueBase::PeekBytes ( void * value)
inline

按字节查看一个队头 payload 但不出队 / Peek one front payload by bytes without dequeuing it

Parameters
value用于接收 payload 的缓冲区 / Buffer that receives the payload
Returns
成功返回 ErrorCode::OK;队列空返回 ErrorCode::EMPTY;空指针返回 ErrorCode::PTR_NULL Returns ErrorCode::OK on success; returns ErrorCode::EMPTY when the queue is empty; returns ErrorCode::PTR_NULL when value is null

Definition at line 157 of file spsc_queue_base.hpp.

158 {
159 if (value == nullptr)
160 {
161 return ErrorCode::PTR_NULL;
162 }
163
164 const auto current_head = head_.load(std::memory_order_relaxed);
165 if (current_head == tail_.load(std::memory_order_acquire))
166 {
167 return ErrorCode::EMPTY;
168 }
169
170 LibXR::Memory::FastCopy(value, PayloadPtr(current_head), element_size_);
171 return ErrorCode::OK;
172 }

◆ PopBatchBytes()

ErrorCode LibXR::SPSCQueueBase::PopBatchBytes ( void * data,
size_t count )
inline

按字节批量出队多个 payload / Dequeue multiple payloads by bytes

Parameters
data用于接收 payload 的字节缓冲区;传 nullptr 时仅丢弃 / Byte buffer receiving payloads; pass nullptr to discard only
countpayload 个数 / Number of payloads
Returns
成功返回 ErrorCode::OK;元素不足返回 ErrorCode::EMPTY Returns ErrorCode::OK on success; returns ErrorCode::EMPTY when there are not enough payloads available

Definition at line 331 of file spsc_queue_base.hpp.

332 {
333 if (count == 0U)
334 {
335 return ErrorCode::OK;
336 }
337
338 const auto current_head = head_.load(std::memory_order_relaxed);
339 const auto current_tail = tail_.load(std::memory_order_acquire);
340 const size_t capacity = RingCapacity();
341 const size_t available = (current_tail >= current_head)
342 ? (current_tail - current_head)
343 : (capacity - current_head + current_tail);
344
345 if (available < count)
346 {
347 return ErrorCode::EMPTY;
348 }
349
350 auto* dst = static_cast<std::byte*>(data);
351 if (dst != nullptr)
352 {
353 for (size_t index = 0; index < count; ++index)
354 {
355 LibXR::Memory::FastCopy(dst + index * element_size_,
356 PayloadPtr((current_head + index) % capacity),
357 element_size_);
358 }
359 }
360
361 head_.store((current_head + count) % capacity, std::memory_order_release);
362 return ErrorCode::OK;
363 }

◆ PopBytes()

ErrorCode LibXR::SPSCQueueBase::PopBytes ( void * value = nullptr)
inline

按字节出队一个 payload;传空指针时仅丢弃队头元素 / Dequeue one payload by bytes; pass null to discard the front item only

Parameters
value用于接收 payload 的缓冲区;传 nullptr 时仅丢弃 / Buffer that receives the payload; pass nullptr to discard only
Returns
成功返回 ErrorCode::OK;队列空返回 ErrorCode::EMPTY Returns ErrorCode::OK on success; returns ErrorCode::EMPTY when the queue is empty

Definition at line 130 of file spsc_queue_base.hpp.

131 {
132 const auto current_head = head_.load(std::memory_order_relaxed);
133
134 if (current_head == tail_.load(std::memory_order_acquire))
135 {
136 return ErrorCode::EMPTY;
137 }
138
139 if (value != nullptr)
140 {
141 LibXR::Memory::FastCopy(value, PayloadPtr(current_head), element_size_);
142 }
143
144 head_.store(Increment(current_head), std::memory_order_release);
145 return ErrorCode::OK;
146 }

◆ PopBytesWithReader()

template<typename Reader >
ErrorCode LibXR::SPSCQueueBase::PopBytesWithReader ( size_t count,
Reader && reader )
inline

通过读取器回调批量出队 payload / Dequeue payloads through a reader callback

Template Parameters
Reader读取器类型 / Reader callback type
Parameters
countpayload 个数 / Number of payloads
reader读取器,签名为 ErrorCode(const void* buffer, size_t chunk_count) / Reader with signature ErrorCode(const void* buffer, size_t chunk_count)
Returns
成功返回 ErrorCode::OK;元素不足返回 ErrorCode::EMPTY;否则返回读取器错误码 / Returns ErrorCode::OK on success, ErrorCode::EMPTY when there are not enough payloads, otherwise returns the reader error code
Note
读取器每次收到一段连续 payload 存储区,字节长度为 chunk_count * element_size / The reader receives one contiguous payload storage chunk each time, with byte length chunk_count * element_size

Definition at line 382 of file spsc_queue_base.hpp.

383 {
384 if (count == 0U)
385 {
386 return ErrorCode::OK;
387 }
388
389 const auto current_head = head_.load(std::memory_order_relaxed);
390 const auto current_tail = tail_.load(std::memory_order_acquire);
391 const size_t capacity = RingCapacity();
392 const size_t available = (current_tail >= current_head)
393 ? (current_tail - current_head)
394 : (capacity - current_head + current_tail);
395
396 if (available < count)
397 {
398 return ErrorCode::EMPTY;
399 }
400
401 const size_t first_chunk = std::min(count, capacity - current_head);
402 Reader& reader_ref = reader;
403 const ErrorCode first_ec = reader_ref(PayloadPtr(current_head), first_chunk);
404 if (first_ec != ErrorCode::OK)
405 {
406 return first_ec;
407 }
408
409 if (count > first_chunk)
410 {
411 const ErrorCode second_ec = reader_ref(PayloadPtr(0), count - first_chunk);
412 if (second_ec != ErrorCode::OK)
413 {
414 return second_ec;
415 }
416 }
417
418 head_.store((current_head + count) % capacity, std::memory_order_release);
419 return ErrorCode::OK;
420 }
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes

◆ ProduceWithWriter()

template<typename Writer >
size_t LibXR::SPSCQueueBase::ProduceWithWriter ( size_t limit,
Writer && writer )
inline

通过一次双 span 回调生产 payload 前缀 / Produce a payload prefix through one two-span writer callback.

Template Parameters
Writer写入器类型 / Writer callback type.
Parameters
limit最多提供的 payload 个数 / Maximum number of offered payloads.
writer接收两段存储和元素数,返回已写入的前缀个数 / Receives two storage pointers and element counts; returns the written prefix count.
Returns
实际发布到队列的 payload 个数 / Number of payloads published to the queue.
Precondition
队列只有一个 producer;回调期间不得重入同侧操作或 Reset / The queue has one producer; no same-side operation or Reset during the callback.
Note
可提供数量为零时不调用回调;第二段为空时指针为 nullptr,所有指针只在回调期间 有效 / The callback is skipped when the offered count is zero; an empty second span is nullptr, and all pointers are valid only during the callback.

Definition at line 290 of file spsc_queue_base.hpp.

291 {
292 if (limit == 0U)
293 {
294 return 0U;
295 }
296
297 const auto current_tail = tail_.load(std::memory_order_relaxed);
298 const auto current_head = head_.load(std::memory_order_acquire);
299 const size_t capacity = RingCapacity();
300 const size_t free_space = (current_tail >= current_head)
301 ? (capacity - (current_tail - current_head) - 1U)
302 : (current_head - current_tail - 1U);
303 const size_t offered = std::min(limit, free_space);
304 if (offered == 0U)
305 {
306 return 0U;
307 }
308
309 const size_t first_count = std::min(offered, capacity - current_tail);
310 const size_t second_count = offered - first_count;
311 void* const second = second_count == 0U ? nullptr : PayloadPtr(0U);
312 const size_t produced =
313 writer(PayloadPtr(current_tail), first_count, second, second_count);
314 ASSERT(produced <= offered);
315 if (produced != 0U)
316 {
317 tail_.store((current_tail + produced) % capacity, std::memory_order_release);
318 }
319 return produced;
320 }

◆ PushBatchBytes()

ErrorCode LibXR::SPSCQueueBase::PushBatchBytes ( const void * data,
size_t count )
inline

按字节批量入队多个 payload / Enqueue multiple payloads by bytes

Parameters
data指向 payload 数组的字节指针 / Byte pointer to the payload array
countpayload 个数 / Number of payloads
Returns
成功返回 ErrorCode::OK;队列满返回 ErrorCode::FULL; count 不为 0 且 data 为空时返回 ErrorCode::PTR_NULL Returns ErrorCode::OK on success; returns ErrorCode::FULL when the queue is full; returns ErrorCode::PTR_NULL when data is null and count is not 0

Definition at line 184 of file spsc_queue_base.hpp.

185 {
186 if (count == 0U)
187 {
188 return ErrorCode::OK;
189 }
190 if (data == nullptr)
191 {
192 return ErrorCode::PTR_NULL;
193 }
194
195 const auto current_tail = tail_.load(std::memory_order_relaxed);
196 const auto current_head = head_.load(std::memory_order_acquire);
197 const size_t capacity = RingCapacity();
198 const size_t free_space = (current_tail >= current_head)
199 ? (capacity - (current_tail - current_head) - 1)
200 : (current_head - current_tail - 1);
201
202 if (free_space < count)
203 {
204 return ErrorCode::FULL;
205 }
206
207 const auto* src = static_cast<const std::byte*>(data);
208 for (size_t index = 0; index < count; ++index)
209 {
210 LibXR::Memory::FastCopy(PayloadPtr((current_tail + index) % capacity),
211 src + index * element_size_, element_size_);
212 }
213
214 tail_.store((current_tail + count) % capacity, std::memory_order_release);
215 return ErrorCode::OK;
216 }
@ FULL
已满 / Full

◆ PushBytes()

ErrorCode LibXR::SPSCQueueBase::PushBytes ( const void * value)
inline

按字节入队一个 payload / Enqueue one payload by bytes

Parameters
value指向待入队 payload 的指针 / Pointer to the payload to enqueue
Returns
成功返回 ErrorCode::OK;队列满返回 ErrorCode::FULL;空指针返回 ErrorCode::PTR_NULL Returns ErrorCode::OK on success; returns ErrorCode::FULL when the queue is full; returns ErrorCode::PTR_NULL when value is null

Definition at line 101 of file spsc_queue_base.hpp.

102 {
103 if (value == nullptr)
104 {
105 return ErrorCode::PTR_NULL;
106 }
107
108 const auto current_tail = tail_.load(std::memory_order_relaxed);
109 const auto next_tail = Increment(current_tail);
110
111 if (next_tail == head_.load(std::memory_order_acquire))
112 {
113 return ErrorCode::FULL;
114 }
115
116 LibXR::Memory::FastCopy(PayloadPtr(current_tail), value, element_size_);
117 tail_.store(next_tail, std::memory_order_release);
118 return ErrorCode::OK;
119 }

◆ PushBytesWithWriter()

template<typename Writer >
ErrorCode LibXR::SPSCQueueBase::PushBytesWithWriter ( size_t count,
Writer && writer )
inline

通过写入器回调批量入队 payload / Enqueue payloads through a writer callback

Template Parameters
Writer写入器类型 / Writer callback type
Parameters
countpayload 个数 / Number of payloads
writer写入器,签名为 ErrorCode(void* buffer, size_t chunk_count) / Writer with signature ErrorCode(void* buffer, size_t chunk_count)
Returns
成功返回 ErrorCode::OK;空间不足返回 ErrorCode::FULL;否则返回写入器错误码 / Returns ErrorCode::OK on success, ErrorCode::FULL when free space is insufficient, otherwise returns the writer error code
Note
写入器每次收到一段连续 payload 存储区,字节长度为 chunk_count * element_size / The writer receives one contiguous payload storage chunk each time, with byte length chunk_count * element_size

Definition at line 234 of file spsc_queue_base.hpp.

235 {
236 if (count == 0U)
237 {
238 return ErrorCode::OK;
239 }
240
241 const auto current_tail = tail_.load(std::memory_order_relaxed);
242 const auto current_head = head_.load(std::memory_order_acquire);
243 const size_t capacity = RingCapacity();
244 const size_t free_space = (current_tail >= current_head)
245 ? (capacity - (current_tail - current_head) - 1)
246 : (current_head - current_tail - 1);
247
248 if (free_space < count)
249 {
250 return ErrorCode::FULL;
251 }
252
253 const size_t first_chunk = std::min(count, capacity - current_tail);
254 Writer& writer_ref = writer;
255 const ErrorCode first_ec = writer_ref(PayloadPtr(current_tail), first_chunk);
256 if (first_ec != ErrorCode::OK)
257 {
258 return first_ec;
259 }
260
261 if (count > first_chunk)
262 {
263 const ErrorCode second_ec = writer_ref(PayloadPtr(0), count - first_chunk);
264 if (second_ec != ErrorCode::OK)
265 {
266 return second_ec;
267 }
268 }
269
270 tail_.store((current_tail + count) % capacity, std::memory_order_release);
271 return ErrorCode::OK;
272 }

◆ Reset()

void LibXR::SPSCQueueBase::Reset ( )
inline

从 consumer 侧丢弃当前可见的全部 payload / Discard all currently available payloads from the consumer side

本方法读取 producer 已发布的 tail 快照,并将 consumer head 推进到该位置;不会 写入 tail,因此单个 producer 可以继续运行。与该快照并发发布的 payload 可能被 丢弃,也可能保留。

This method snapshots the producer-published tail and advances the consumer head to it. It never writes tail, so the single producer may continue. Payloads published concurrently with the snapshot may be discarded or retained.

Definition at line 526 of file spsc_queue_base.hpp.

527 {
528 const auto current_tail = tail_.load(std::memory_order_acquire);
529 head_.store(current_tail, std::memory_order_release);
530 }

◆ Size()

size_t LibXR::SPSCQueueBase::Size ( ) const
inline

获取当前已用元素数 / Get the current element count

Returns
当前元素个数 / Current number of stored payloads

Definition at line 536 of file spsc_queue_base.hpp.

537 {
538 const auto current_head = head_.load(std::memory_order_acquire);
539 const auto current_tail = tail_.load(std::memory_order_acquire);
540 return (current_tail >= current_head)
541 ? (current_tail - current_head)
542 : (RingCapacity() - current_head + current_tail);
543 }

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