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

基于 SPSC 字节队列的读端口 / Read endpoint backed by an SPSC byte queue. More...

#include <read_port.hpp>

Inheritance diagram for LibXR::ReadPort:
[legend]

Classes

class  ReadQueue
 接收队列的短期写入接口 / Short-lived producer interface for the RX queue. More...
 

Public Member Functions

 ReadPort (size_t buffer_size=128U)
 构造读端口并分配接收队列 / Construct a read port and allocate its RX queue.
 
virtual ~ReadPort ()=default
 析构读端口 / Destroy the read port.
 
ReadQueue GetReadQueue (bool in_isr=false)
 获取后端接收入队接口 / Obtain the backend RX producer interface.
 
size_t EmptySize () const
 获取当前空闲空间 / Get current free space.
 
size_t Size () const
 获取当前排队的数据量 / Get the current queued data size.
 
size_t Capacity () const
 获取接收队列容量 / Get the RX queue capacity.
 
bool Readable () const
 检查端口是否支持读取 / Check whether the port supports reads.
 
ErrorCode operator() (RawData data, ReadOperation &op, bool in_isr=false)
 提交读请求 / Submit a read request.
 
ErrorCode ClearQueuedData (bool in_isr=false)
 丢弃当前已排队的接收字节 / Discard currently queued RX bytes.
 

Protected Member Functions

virtual void OnReadQueueSpaceAvailable (bool)
 接收队列空间可用通知 / RX queue space-available notification.
 

Friends

class Pipe
 

Detailed Description

基于 SPSC 字节队列的读端口 / Read endpoint backed by an SPSC byte queue.

后端持续向队列写入数据并通知端口;端口最多保存一个尚未满足的读请求。 The backend feeds the queue and notifies the port, which retains at most one pending read request.

Precondition
后端负责串行化接收生产者。同一端口的 BLOCK 与非 BLOCK 操作不得重叠或嵌套。 The backend serializes RX production. BLOCK and non-BLOCK operations on the same port must not overlap or nest.
Note
端口、所属后端和通知对象须在所有可能访问它们的调用与回调返回前保持有效。 The port, its backend, and notification targets must outlive all calls and callbacks that may access them.

Definition at line 29 of file read_port.hpp.

Constructor & Destructor Documentation

◆ ReadPort()

ReadPort::ReadPort ( size_t buffer_size = 128U)
explicit

构造读端口并分配接收队列 / Construct a read port and allocate its RX queue.

Parameters
buffer_size队列容量,单位为字节;为零时不分配,端口保持未绑定。 Queue capacity in bytes; zero leaves the port unbound without allocating.
Note
Pipe 在构造时将未绑定的读端口绑定到共享队列。 Pipe binds its initially unbound read port to the shared queue at construction.

Definition at line 7 of file read_port.cpp.

8 : queue_data_(buffer_size != 0U ? new (std::align_val_t(LibXR::CONCURRENCY_ALIGNMENT))
9 SPSCQueue<uint8_t>(buffer_size)
10 : nullptr)
11{
12}
单生产者单消费者无锁队列 / Single-producer single-consumer lock-free queue.
constexpr size_t CONCURRENCY_ALIGNMENT
并发结构对齐粒度(用于降低多核伪共享) / Alignment policy used by concurrency-oriented structures
Definition libxr_def.hpp:61

◆ ~ReadPort()

virtual LibXR::ReadPort::~ReadPort ( )
virtualdefault

析构读端口 / Destroy the read port.

Precondition
相关请求、调用和回调已结束 / All related requests, calls, and callbacks ended.
Note
不取消请求,也不释放队列存储 / Does not cancel requests or free queue storage.

Member Function Documentation

◆ Capacity()

size_t ReadPort::Capacity ( ) const
nodiscard

获取接收队列容量 / Get the RX queue capacity.

Returns
队列总字节数,未绑定时为零 / Total capacity in bytes, or zero when unbound.

Definition at line 62 of file read_port.cpp.

63{
64 return queue_data_ == nullptr ? 0U : queue_data_->MaxSize();
65}
size_t MaxSize() const
获取队列最大容量 / Get the maximum queue capacity

◆ ClearQueuedData()

ErrorCode ReadPort::ClearQueuedData ( bool in_isr = false)
nodiscard

丢弃当前已排队的接收字节 / Discard currently queued RX bytes.

Parameters
in_isr当前调用是否位于中断 / Whether this call is in an ISR.
Returns
成功返回 OK,未绑定返回 NOT_SUPPORT,存在活动请求或出队处理时返回 BUSY。 OK on success, NOT_SUPPORT when unbound, BUSY during an active request or dequeue operation.
Precondition
同一端口的 BLOCK 调用已返回 / Any same-port BLOCK call has returned.
Note
只推进消费者位置,可与唯一生产者并发。并发到达的数据可能保留或被丢弃。 不取消挂起请求;成功后释放处理权并通知队列空间可用。 Advances only the consumer index and may overlap the sole producer. Racing data may survive or be discarded. Does not cancel pending reads; releases request processing and notifies available space on success.

Definition at line 410 of file read_port.cpp.

411{
412 if (!Readable())
413 {
415 }
416 if (!TryClaimIdle())
417 {
418 return ErrorCode::BUSY;
419 }
420
421 queue_data_->Reset();
422 ReleaseClaimed(in_isr);
424 return ErrorCode::OK;
425}
virtual void OnReadQueueSpaceAvailable(bool)
接收队列空间可用通知 / RX queue space-available notification.
bool Readable() const
检查端口是否支持读取 / Check whether the port supports reads.
Definition read_port.cpp:67
void Reset()
从 consumer 侧丢弃当前可见的全部 payload / Discard currently available payloads from the consumer side
@ BUSY
忙碌 / Busy
@ NOT_SUPPORT
不支持 / Not supported
@ OK
操作成功 / Operation successful

◆ EmptySize()

size_t ReadPort::EmptySize ( ) const
nodiscard

获取当前空闲空间 / Get current free space.

Returns
空闲字节数,未绑定时为零;并发消费或生产可使结果变化。 Free bytes, or zero when unbound; concurrent progress may change the value.

Definition at line 52 of file read_port.cpp.

53{
54 return queue_data_ == nullptr ? 0U : queue_data_->EmptySize();
55}
size_t EmptySize() const
获取剩余空槽数 / Get the current free-slot count

◆ GetReadQueue()

ReadPort::ReadQueue ReadPort::GetReadQueue ( bool in_isr = false)
nodiscard

获取后端接收入队接口 / Obtain the backend RX producer interface.

Parameters
in_isr是否在中断中调用;该值用于本次 Publish 引起的通知。 Whether called in an ISR; used for notifications caused by this Publish.
Returns
本次接收入队接口 / Producer interface for this RX operation.
Precondition
队列已绑定,由唯一接收生产者调用;Pipe 的借用读端口不可使用此接口。 A bound queue and the sole RX producer are required; not for a Pipe's borrowed read endpoint.

Definition at line 14 of file read_port.cpp.

15{
16 ASSERT_FROM_CALLBACK(queue_data_ != nullptr, in_isr);
17 return ReadQueue(*this, in_isr);
18}

◆ OnReadQueueSpaceAvailable()

virtual void LibXR::ReadPort::OnReadQueueSpaceAvailable ( bool )
inlineprotectedvirtual

接收队列空间可用通知 / RX queue space-available notification.

正长度出队后、完成通知前调用;ClearQueuedData 成功时也调用,包括空队列。 bool 参数表示本次调用是否在中断中;默认实现为空。 Called after positive dequeue and before completion notification, or after a successful ClearQueuedData even for an empty queue. The bool argument indicates ISR context; the default implementation does nothing.

Note
派生实现负责恢复接收,或保留通知供当前生产者再次处理;需与其他接收入口串行化。 Overrides resume RX or retain a hint for the producer to recheck, serialized with other RX entry points.

Reimplemented in LibXR::Detail::LinuxUARTReadPort, LibXR::ESP32CDCJtagReadPort, LibXR::ESP32UARTReadPort, LibXR::MSPM0UARTReadPort, and LibXR::USB::CDCUartReadPort.

Definition at line 305 of file read_port.hpp.

305{}

◆ operator()()

ErrorCode ReadPort::operator() ( RawData data,
ReadOperation & op,
bool in_isr = false )

提交读请求 / Submit a read request.

Parameters
data接收地址和字节数。正长度请求须有有效地址,数据足够时才一次性复制; 零长度请求等待队列非空,不消费字节,地址可为空。 Destination and byte count. Positive reads require a valid address and copy only when the full request is available. Zero size waits for a nonempty queue without consuming bytes and permits a null address.
op完成通知方式;其回调、轮询状态或信号量在操作结束前须保持有效。 Completion descriptor; its callback, polling state, or semaphore must remain valid until the operation ends.
in_isr当前调用是否位于中断 / Whether this call is in an ISR.
Returns
非 BLOCK 的 OK 表示请求已接纳,可能同步完成,也可能等待后续数据; BLOCK 的 OK 表示读取完成,超时取消返回 TIMEOUT。未绑定返回 NOT_SUPPORT, 请求处理状态被占用返回 BUSY,正长度超过队列容量返回 SIZE_ERR。 Non-BLOCK OK means admitted, with inline or deferred completion. BLOCK OK means completed; timeout cancellation returns TIMEOUT. NOT_SUPPORT when unbound, BUSY when request processing is occupied, SIZE_ERR above capacity.
Precondition
BLOCK 只能在线程中调用;返回前不可在同一端口再 Read 或 ClearQueuedData, 也不可与尚未结束的非 BLOCK 操作重叠。每个信号量只服务一个活动 BLOCK 调用。 BLOCK is task-only; no same-port Read or ClearQueuedData before it returns, and no overlap with a live non-BLOCK operation. Use a dedicated semaphore.
Note
接收缓冲区须保持有效直到完成或取消;BLOCK 缓冲区须保持到调用返回。 超时与处理方竞争时,须等处理方停止访问缓冲区后才返回,可能超过指定时间; 若完成方赢得交接则返回完成结果。 Keep the destination valid until completion or cancellation, and through return for BLOCK. A timeout racing progress waits until buffer access ends, possibly exceeding the requested duration; completion wins if already claimed.
非 BLOCK 回调可提交后续非 BLOCK 读;跨线程回调顺序不保证。立即满足的 BLOCK 直接返回,不释放信号量;拒绝接纳的请求不发送完成通知。 Non-BLOCK callbacks may submit another non-BLOCK read; cross-thread callback order is not guaranteed. Immediate BLOCK completion does not post a semaphore; rejected requests emit no completion notification.
回调在实际完成读取的上下文执行,可能位于本次调用或后端 Publish 内; 轮询状态应以 acquire 读取。不可阻塞等待依赖当前调用返回才能推进的操作。 Callbacks run in the context completing the read, possibly inside this call or backend Publish. Load polling status with acquire ordering. Do not block on progress that requires the current call to return.

Definition at line 159 of file read_port.cpp.

160{
161 if (!Readable())
162 {
164 }
165
166 if (!TryClaimIdle())
167 {
168 return ErrorCode::BUSY;
169 }
170
171 const bool is_block = op.type == ReadOperation::OperationType::BLOCK;
172
173 if (data.size_ != 0U)
174 {
175 ASSERT_FROM_CALLBACK(data.addr_ != nullptr, in_isr);
176 if (data.size_ > Capacity())
177 {
178 ReleaseClaimed(in_isr);
179 return ErrorCode::SIZE_ERR;
180 }
181 }
182
183 if (HasEnough(queue_data_->Size(), data.size_))
184 {
185 if (data.size_ != 0U)
186 {
187 [[maybe_unused]] const auto pop_batch_result =
188 queue_data_->PopBatch(reinterpret_cast<uint8_t*>(data.addr_), data.size_);
189 DEV_ASSERT_FROM_CALLBACK(pop_batch_result == ErrorCode::OK, in_isr);
190 }
191
192 Request completed{data, op};
193 ReleaseClaimed(in_isr);
194 if (data.size_ != 0U)
195 {
197 }
198 if (completed.op.type != ReadOperation::OperationType::BLOCK)
199 {
200 completed.op.UpdateStatus(in_isr, ErrorCode::OK);
201 }
202 return ErrorCode::OK;
203 }
204
205 info_ = Request{data, op};
206 info_.op.MarkAsRunning();
207
208 for (;;)
209 {
210 uint32_t observed = state_.load(std::memory_order_acquire);
211 DEV_ASSERT_FROM_CALLBACK(GetPhase(observed) == Phase::CLAIMED, in_isr);
212
213 if (HasEvent(observed))
214 {
215 if (!state_.compare_exchange_weak(observed, static_cast<uint32_t>(Phase::CLAIMED),
216 std::memory_order_acq_rel,
217 std::memory_order_acquire))
218 {
219 continue;
220 }
221
222 if (HasEnough(queue_data_->Size(), data.size_))
223 {
224 if (info_.op.type == ReadOperation::OperationType::BLOCK)
225 {
226 CompleteClaimedBlock(in_isr);
227 return WaitForBlock(op);
228 }
229 CompleteClaimedRead(in_isr);
230 return ErrorCode::OK;
231 }
232 continue;
233 }
234
235 uint32_t expected = observed;
236 if (state_.compare_exchange_weak(expected, static_cast<uint32_t>(Phase::PENDING),
237 std::memory_order_acq_rel,
238 std::memory_order_acquire))
239 {
240 break;
241 }
242 }
243
244 return is_block ? WaitForBlock(op) : ErrorCode::OK;
245}
void MarkAsRunning()
标记轮询操作正在执行 / Mark a polling operation as running.
OperationType type
当前通知方式 / Current notification mode.
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
size_t Capacity() const
获取接收队列容量 / Get the RX queue capacity.
Definition read_port.cpp:62
size_t Size() const
获取当前已用元素数 / Get the current element count
ErrorCode PopBatch(Data *data, size_t size)
批量弹出多个 payload / Pop multiple payloads from the queue.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ SIZE_ERR
尺寸错误 / Size error

◆ Readable()

bool ReadPort::Readable ( ) const
nodiscard

检查端口是否支持读取 / Check whether the port supports reads.

Returns
已绑定队列时为 true,不表示队列非空或端口空闲。 True when a queue is bound; does not indicate available data or an idle port.

Definition at line 67 of file read_port.cpp.

67{ return queue_data_ != nullptr; }

◆ Size()

size_t ReadPort::Size ( ) const
nodiscard

获取当前排队的数据量 / Get the current queued data size.

Returns
已排队字节数,未绑定时为零;查询不预留数据,并发进展可使结果变化。 Queued bytes, or zero when unbound; the query reserves no data and concurrent progress may change the value.

Definition at line 57 of file read_port.cpp.

58{
59 return queue_data_ == nullptr ? 0U : queue_data_->Size();
60}

Friends And Related Symbol Documentation

◆ Pipe

friend class Pipe
friend

Definition at line 91 of file read_port.hpp.


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