libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
spsc_queue.hpp
1#pragma once
2
3#include <cstddef>
4#include <type_traits>
5
6#include "queue_typed_base.hpp"
7#include "spsc_queue_base.hpp"
8
9namespace LibXR
10{
26template <typename Data>
27class SPSCQueue final : public QueueTypedBase<SPSCQueue<Data>, Data>, public SPSCQueueBase
28{
29 public:
30 static_assert(alignof(Data) <= alignof(std::max_align_t),
31 "SPSCQueue does not support over-aligned payload types");
32
33 using ValueType = Data;
38
45 explicit SPSCQueue(size_t length) : SPSCQueueBase(sizeof(Data), alignof(Data), length)
46 {
47 }
48
52 ~SPSCQueue() = default;
53
61 ErrorCode Peek(Data& item) { return SPSCQueueBase::PeekBytes(&item); }
62
71 ErrorCode PushBatch(const Data* data, size_t size)
72 {
73 return SPSCQueueBase::PushBatchBytes(data, size);
74 }
75
89 template <typename Writer>
90 ErrorCode PushWithWriter(Writer&& writer)
91 {
92 return PushWithWriter(1, std::forward<Writer>(writer));
93 }
94
109 template <typename Writer>
110 ErrorCode PushWithWriter(size_t size, Writer&& writer)
111 {
112 static_assert(
113 std::is_trivially_copyable_v<Data>,
114 "batched SPSCQueue::PushWithWriter requires trivially copyable payloads");
115 static_assert(
116 std::is_trivially_destructible_v<Data>,
117 "batched SPSCQueue::PushWithWriter requires trivially destructible payloads");
118 static_assert(std::is_invocable_v<Writer&, Data*, size_t>,
119 "PushWithWriter writer must be callable as "
120 "ErrorCode(Data* buffer, size_t count)");
121 using WriterRet = std::invoke_result_t<Writer&, Data*, size_t>;
122 static_assert(std::is_convertible_v<WriterRet, ErrorCode>,
123 "PushWithWriter writer return type must be convertible to ErrorCode");
124
125 Writer& writer_ref = writer;
127 size, [&](void* buffer, size_t count) -> ErrorCode
128 { return writer_ref(static_cast<Data*>(buffer), count); });
129 }
130
146 template <typename Writer>
147 size_t ProduceWithWriter(size_t limit, Writer&& writer)
148 {
149 static_assert(std::is_trivially_copyable_v<Data>);
150 static_assert(std::is_trivially_destructible_v<Data>);
152 limit,
153 [&](void* first, size_t first_size, void* second, size_t second_size) -> size_t
154 {
155 return writer(static_cast<Data*>(first), first_size, static_cast<Data*>(second),
156 second_size);
157 });
158 }
159
173 template <typename Reader>
174 ErrorCode PopWithReader(Reader&& reader)
175 {
176 return PopWithReader(1, std::forward<Reader>(reader));
177 }
178
193 template <typename Reader>
194 ErrorCode PopWithReader(size_t size, Reader&& reader)
195 {
196 static_assert(
197 std::is_trivially_copyable_v<Data>,
198 "batched SPSCQueue::PopWithReader requires trivially copyable payloads");
199 static_assert(
200 std::is_trivially_destructible_v<Data>,
201 "batched SPSCQueue::PopWithReader requires trivially destructible payloads");
202 static_assert(std::is_invocable_v<Reader&, const Data*, size_t>,
203 "PopWithReader reader must be callable as "
204 "ErrorCode(const Data* buffer, size_t count)");
205 using ReaderRet = std::invoke_result_t<Reader&, const Data*, size_t>;
206 static_assert(std::is_convertible_v<ReaderRet, ErrorCode>,
207 "PopWithReader reader return type must be convertible to ErrorCode");
208
209 Reader& reader_ref = reader;
211 size, [&](const void* buffer, size_t count) -> ErrorCode
212 { return reader_ref(static_cast<const Data*>(buffer), count); });
213 }
214
230 template <typename Reader>
231 size_t ConsumeWithReader(size_t limit, Reader&& reader)
232 {
233 static_assert(std::is_trivially_copyable_v<Data>);
234 static_assert(std::is_trivially_destructible_v<Data>);
236 limit,
237 [&](const void* first, size_t first_size, const void* second,
238 size_t second_size) -> size_t
239 {
240 return reader(static_cast<const Data*>(first), first_size,
241 static_cast<const Data*>(second), second_size);
242 });
243 }
244
253 ErrorCode PopBatch(Data* data, size_t size)
254 {
255 return SPSCQueueBase::PopBatchBytes(data, size);
256 }
257
266 ErrorCode PeekBatch(Data* data, size_t size)
267 {
268 return SPSCQueueBase::PeekBatchBytes(data, size);
269 }
270
276};
277} // namespace LibXR
强类型队列的公共薄包装 / Common thin wrapper for typed queues.
单生产者单消费者字节队列内核 / Single-producer single-consumer byte-queue core
void Reset()
从 consumer 侧丢弃当前可见的全部 payload / Discard all currently available payloads from the consumer side
ErrorCode PeekBytes(void *value)
按字节查看一个队头 payload 但不出队 / Peek one front payload by bytes without dequeuing it
ErrorCode PeekBatchBytes(void *data, size_t count)
按字节批量查看多个 payload 但不出队 / Peek multiple payloads by bytes without dequeuing them
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
ErrorCode PushBatchBytes(const void *data, size_t count)
按字节批量入队多个 payload / Enqueue multiple payloads by bytes
ErrorCode PopBytesWithReader(size_t count, Reader &&reader)
通过读取器回调批量出队 payload / Dequeue payloads through a reader callback
size_t ConsumeWithReader(size_t limit, Reader &&reader)
通过一次双 span 回调消费 payload 前缀 / Consume a payload prefix through one two-span reader callback.
ErrorCode PushBytesWithWriter(size_t count, Writer &&writer)
通过写入器回调批量入队 payload / Enqueue payloads through a writer callback
单生产者单消费者无锁队列 / Single-producer single-consumer lock-free queue.
void Reset()
从 consumer 侧丢弃当前可见的全部 payload / Discard currently available payloads from the consumer side
ErrorCode PopWithReader(size_t size, Reader &&reader)
通过读取器回调批量弹出 payload / Pop multiple payloads via a reader callback.
ErrorCode PeekBatch(Data *data, size_t size)
批量查看多个 payload 但不出队 / Peek multiple payloads without dequeuing them.
ErrorCode PopBatch(Data *data, size_t size)
批量弹出多个 payload / Pop multiple payloads from the queue.
SPSCQueue(size_t length)
构造一个 SPSC 队列 / Construct one SPSC queue.
~SPSCQueue()=default
析构一个 SPSC 队列 / Destroy one SPSC queue.
size_t ProduceWithWriter(size_t limit, Writer &&writer)
通过一次双 span 回调生产 payload 前缀 / Produce a payload prefix through one two-span writer callback.
ErrorCode Peek(Data &item)
查看一个队头 payload 但不出队 / Peek one front payload without dequeuing it.
ErrorCode PopWithReader(Reader &&reader)
通过读取器回调弹出一个 payload / Pop one payload via a reader callback.
ErrorCode PushWithWriter(size_t size, Writer &&writer)
通过写入器回调批量推入 payload / Push multiple payloads via a writer callback.
ErrorCode PushWithWriter(Writer &&writer)
通过写入器回调推入一个 payload / Push one payload via a writer callback.
size_t ConsumeWithReader(size_t limit, Reader &&reader)
通过一次双 span 回调消费 payload 前缀 / Consume a payload prefix through one two-span reader callback.
ErrorCode PushBatch(const Data *data, size_t size)
批量推入多个 payload / Push multiple payloads into the queue.
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes