libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
read_port.hpp
1#pragma once
2
3#include <atomic>
4#include <cstddef>
5#include <cstdint>
6
7#include "operation.hpp"
8#include "queue.hpp"
9
10namespace LibXR
11{
12
13class Pipe;
14
30{
31 private:
33 enum class Phase : uint32_t
34 {
35 IDLE = 0U,
36 CLAIMED = 1U,
37 PENDING = 2U,
38 CLAIMED_WITH_WAITER = 3U,
39 BLOCK_CLAIMED = 4U,
40 };
41
43 static constexpr uint32_t EVENT_BIT = 1U << 31U;
45 static constexpr uint32_t PHASE_MASK = EVENT_BIT - 1U;
46
48 struct Request
49 {
50 RawData data;
51 ReadOperation op;
52 };
53
55 static Phase GetPhase(uint32_t state) { return static_cast<Phase>(state & PHASE_MASK); }
56
58 static uint32_t WithPhase(uint32_t state, Phase phase)
59 {
60 return (state & EVENT_BIT) | static_cast<uint32_t>(phase);
61 }
62
64 static bool HasEvent(uint32_t state) { return (state & EVENT_BIT) != 0U; }
65
67 [[nodiscard]] bool TryClaimIdle();
69 [[nodiscard]] bool HasEnough(size_t available, size_t requested) const;
71 void ReleaseClaimed(bool in_isr);
73 [[nodiscard]] bool ClaimBlockCompletion();
75 void ReleaseBlockCompletion(bool in_isr);
77 void PublishProduced(bool in_isr);
79 void NotifyDataAvailable(bool in_isr);
81 void ProcessPendingReads(bool in_isr);
83 void CompleteClaimedRead(bool in_isr);
85 void CompleteClaimedBlock(bool in_isr);
87 [[nodiscard]] ErrorCode WaitForBlock(ReadOperation& op);
89 void BindQueue(SPSCQueue<uint8_t>* queue);
90
91 friend class Pipe;
92
93 public:
108 {
109 public:
110 ReadQueue(const ReadQueue&) = delete;
111 ReadQueue& operator=(const ReadQueue&) = delete;
112 ReadQueue(ReadQueue&&) = delete;
113 ReadQueue& operator=(ReadQueue&&) = delete;
115 ~ReadQueue();
116
126 [[nodiscard]] ErrorCode PushBatch(const uint8_t* data, size_t size);
127
144 template <typename Writer>
145 [[nodiscard]] size_t PushWithWriter(size_t limit, Writer&& writer)
146 {
147 ASSERT_FROM_CALLBACK(!finished_, in_isr_);
148
149 const size_t produced = port_.queue_data_->ProduceWithWriter(
150 limit,
151 [&](void* first, size_t first_size, void* second, size_t second_size) -> size_t
152 {
153 const size_t produced = writer(static_cast<uint8_t*>(first), first_size,
154 static_cast<uint8_t*>(second), second_size);
155 ASSERT_FROM_CALLBACK(produced <= first_size + second_size, in_isr_);
156 return produced;
157 });
158 dirty_ = dirty_ || (produced != 0U);
159 return produced;
160 }
161
166 [[nodiscard]] size_t EmptySize() const;
167
172 [[nodiscard]] size_t Capacity() const;
173
183 void Publish();
184
185 private:
186 friend class ReadPort;
187
188 ReadQueue(ReadPort& port, bool in_isr) : port_(port), in_isr_(in_isr) {}
189
190 ReadPort& port_;
191 const bool in_isr_;
192 bool dirty_ = false;
193 bool finished_ = false;
194 };
195
203 explicit ReadPort(size_t buffer_size = 128U);
204
210 virtual ~ReadPort() = default;
211
221 [[nodiscard]] ReadQueue GetReadQueue(bool in_isr = false);
222
228 [[nodiscard]] size_t EmptySize() const;
229
236 [[nodiscard]] size_t Size() const;
237
242 [[nodiscard]] size_t Capacity() const;
243
249 [[nodiscard]] bool Readable() const;
250
289 ErrorCode operator()(RawData data, ReadOperation& op, bool in_isr = false);
290
291 protected:
305 virtual void OnReadQueueSpaceAvailable(bool) {}
306
307 public:
321 [[nodiscard]] ErrorCode ClearQueuedData(bool in_isr = false);
322
323 private:
325 SPSCQueue<uint8_t>* queue_data_ = nullptr;
327 std::atomic<uint32_t> state_{static_cast<uint32_t>(Phase::IDLE)};
329 Request info_{};
331 ErrorCode block_result_ = ErrorCode::OK;
332};
333
334} // namespace LibXR
由读写端口组成的单向管道 / Unidirectional pipe connecting read and write ports.
可写原始数据视图 / Mutable raw data view
接收队列的短期写入接口 / Short-lived producer interface for the RX queue.
size_t PushWithWriter(size_t limit, Writer &&writer)
通过回调直接写入接收队列 / Fill the RX queue through a writer callback.
void Publish()
结束本次写入并通知挂起读 / End production and notify a pending read.
Definition read_port.cpp:42
size_t EmptySize() const
获取接收队列当前空闲空间 / Get current RX queue free space.
Definition read_port.cpp:38
~ReadQueue()
开发期检查是否已 Publish / Check for Publish in development builds.
Definition read_port.cpp:20
ErrorCode PushBatch(const uint8_t *data, size_t size)
批量复制字节到接收队列 / Copy a batch of bytes into the RX queue.
Definition read_port.cpp:22
size_t Capacity() const
获取接收队列容量 / Get the RX queue capacity.
Definition read_port.cpp:40
基于 SPSC 字节队列的读端口 / Read endpoint backed by an SPSC byte queue.
Definition read_port.hpp:30
virtual void OnReadQueueSpaceAvailable(bool)
接收队列空间可用通知 / RX queue space-available notification.
ReadPort(size_t buffer_size=128U)
构造读端口并分配接收队列 / Construct a read port and allocate its RX queue.
Definition read_port.cpp:7
virtual ~ReadPort()=default
析构读端口 / Destroy the read port.
size_t EmptySize() const
获取当前空闲空间 / Get current free space.
Definition read_port.cpp:52
ErrorCode ClearQueuedData(bool in_isr=false)
丢弃当前已排队的接收字节 / Discard currently queued RX bytes.
size_t Size() const
获取当前排队的数据量 / Get the current queued data size.
Definition read_port.cpp:57
bool Readable() const
检查端口是否支持读取 / Check whether the port supports reads.
Definition read_port.cpp:67
size_t Capacity() const
获取接收队列容量 / Get the RX queue capacity.
Definition read_port.cpp:62
ErrorCode operator()(RawData data, ReadOperation &op, bool in_isr=false)
提交读请求 / Submit a read request.
ReadQueue GetReadQueue(bool in_isr=false)
获取后端接收入队接口 / Obtain the backend RX producer interface.
Definition read_port.cpp:14
单生产者单消费者无锁队列 / Single-producer single-consumer lock-free queue.
size_t ProduceWithWriter(size_t limit, Writer &&writer)
通过一次双 span 回调生产 payload 前缀 / Produce a payload prefix through one two-span writer callback.
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ PENDING
等待中 / Pending
@ OK
操作成功 / Operation successful