libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
LibXR::ReadPort Class Reference

ReadPort class for handling read operations. More...

#include <libxr_rw.hpp>

Inheritance diagram for LibXR::ReadPort:
[legend]
Collaboration diagram for LibXR::ReadPort:
[legend]

Public Types

enum class  BusyState : uint32_t {
  IDLE = 0 , PENDING = 1 , BLOCK_CLAIMED = 2 , BLOCK_DETACHED = 3 ,
  EVENT = UINT32_MAX
}
 

Public Member Functions

 ReadPort (size_t buffer_size=128)
 Constructs a ReadPort with queue sizes.
 
size_t EmptySize ()
 获取队列的剩余可用空间。 Gets the remaining available space in the queue.
 
size_t Size ()
 获取当前队列的已使用大小。 Gets the currently used size of the queue.
 
bool Readable ()
 Checks if read operations are supported.
 
ReadPortoperator= (ReadFun fun)
 赋值运算符重载,用于设置读取函数。 Overloaded assignment operator to set the read function.
 
void Finish (bool in_isr, ErrorCode ans, ReadInfoBlock &info)
 更新读取操作的状态。 Updates the status of the read operation.
 
void MarkAsRunning (ReadInfoBlock &info)
 标记读取操作为运行中。 Marks the read operation as running.
 
ErrorCode operator() (RawData data, ReadOperation &op, bool in_isr=false)
 读取操作符重载,用于执行读取操作。 Overloaded function call operator to perform a read operation.
 
virtual void OnRxDequeue (bool)
 RX 数据从软件队列成功出队后的通知。 Notification after bytes are popped from RX data queue.
 
void ProcessPendingReads (bool in_isr)
 Processes pending reads.
 
void Reset ()
 Resets the ReadPort.
 

Data Fields

ReadFun read_fun_ = nullptr
 
LockFreeQueue< uint8_t > * queue_data_ = nullptr
 
ReadInfoBlock info_
 
std::atomic< BusyStatebusy_ {BusyState::IDLE}
 
ErrorCode block_result_ = ErrorCode::OK
 Final status for the current BLOCK read.
 

Detailed Description

ReadPort class for handling read operations.

处理读取操作的ReadPort类。

Definition at line 378 of file libxr_rw.hpp.

Member Enumeration Documentation

◆ BusyState

enum class LibXR::ReadPort::BusyState : uint32_t
strong
Enumerator
IDLE 

No active waiter and no pending completion. 无等待者、无挂起完成。

PENDING 

Driver accepted the request; completion still owns progress. 请求已交给底层推进。

BLOCK_CLAIMED 

BLOCK wakeup already belongs to the current waiter. 当前 BLOCK 唤醒已被本次等待者认领。

BLOCK_DETACHED 

Timeout/reset detached the waiter; completion must stay silent. 超时或 Reset 已分离等待者,完成侧不得再唤醒。

EVENT 

Data arrived before a waiter was armed; next caller must re-check queue. 数据先到,后续调用者要重查队列。

Definition at line 392 of file libxr_rw.hpp.

393 {
394 IDLE = 0,
395 PENDING = 1,
397 BLOCK_CLAIMED = 2,
399 BLOCK_DETACHED = 3,
401 EVENT = UINT32_MAX
403 };
@ IDLE
No active waiter and no pending completion. 无等待者、无挂起完成。

Constructor & Destructor Documentation

◆ ReadPort()

ReadPort::ReadPort ( size_t buffer_size = 128)

Constructs a ReadPort with queue sizes.

以指定队列大小构造ReadPort。

Parameters
queue_sizeNumber of queued operations.
buffer_sizeSize of each buffer.
Note
包含动态内存分配。 Contains dynamic memory allocation.

Definition at line 11 of file libxr_rw.cpp.

12 : queue_data_(buffer_size > 0 ? new (std::align_val_t(LIBXR_CACHE_LINE_SIZE))
13 LockFreeQueue<uint8_t>(buffer_size)
14 : nullptr)
15{
16}
无锁队列实现 / Lock-free queue implementation

Member Function Documentation

◆ EmptySize()

size_t ReadPort::EmptySize ( )

获取队列的剩余可用空间。 Gets the remaining available space in the queue.

该函数返回 queue_block_ 中当前可用的空闲空间大小。 This function returns the size of the available empty space in queue_block_.

Returns
返回队列的空闲大小(单位:字节)。 Returns the empty size of the queue (in bytes).

Definition at line 18 of file libxr_rw.cpp.

19{
20 ASSERT(queue_data_ != nullptr);
21 return queue_data_->EmptySize();
22}
size_t EmptySize()
计算队列剩余可用空间 / Calculates the remaining available space in the queue

◆ Finish()

void ReadPort::Finish ( bool in_isr,
ErrorCode ans,
ReadInfoBlock & info )

更新读取操作的状态。 Updates the status of the read operation.

Parameters
in_isr指示是否在中断上下文中执行。 Indicates whether the operation is executed in an interrupt context.
ans错误码,用于指示操作的结果。 Error code indicating the result of the operation.
info需要更新状态的 ReadInfoBlock 引用。 Reference to the ReadInfoBlock whose status needs to be updated.

Definition at line 38 of file libxr_rw.cpp.

39{
40 if (info.op.type == ReadOperation::OperationType::BLOCK)
41 {
42 // Read completion must come from ProcessPendingReads(); drivers are not
43 // allowed to finish a BLOCK read directly.
44 // BLOCK 读完成只能来自 ProcessPendingReads();驱动不能直接 Finish。
46 if (busy_.compare_exchange_strong(expected, BusyState::IDLE,
47 std::memory_order_acq_rel,
48 std::memory_order_acquire))
49 {
50 return;
51 }
52
53 ASSERT(expected == BusyState::BLOCK_CLAIMED);
54 if (expected == BusyState::BLOCK_CLAIMED)
55 {
56 block_result_ = ans;
57 info.op.data.sem_info.sem->PostFromCallback(in_isr);
58 }
59 return;
60 }
61
62 busy_.store(BusyState::IDLE, std::memory_order_release);
63 info.op.UpdateStatus(in_isr, ans);
64}
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
Definition libxr_rw.hpp:178
OperationType type
Definition libxr_rw.hpp:237
ErrorCode block_result_
Final status for the current BLOCK read.
Definition libxr_rw.hpp:409
void PostFromCallback(bool in_isr)
从中断回调中释放(增加)信号量 Releases (increments) the semaphore from an ISR (Interrupt Service Routine)
ReadOperation op
Read operation instance. 读取操作实例。
Definition libxr_rw.hpp:365

◆ MarkAsRunning()

void ReadPort::MarkAsRunning ( ReadInfoBlock & info)

标记读取操作为运行中。 Marks the read operation as running.

该函数用于将 info.op_ 标记为运行状态,以指示当前正在进行读取操作。 This function marks info.op_ as running to indicate an ongoing read operation.

Parameters
info需要更新状态的 ReadInfoBlock 引用。 Reference to the ReadInfoBlock whose status needs to be updated.

Definition at line 66 of file libxr_rw.cpp.

66{ info.op.MarkAsRunning(); }
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:213

◆ OnRxDequeue()

virtual void LibXR::ReadPort::OnRxDequeue ( bool )
inlinevirtual

RX 数据从软件队列成功出队后的通知。 Notification after bytes are popped from RX data queue.

Parameters
in_isr指示是否在中断上下文中执行。 Indicates whether the operation is executed in an interrupt context.

Reimplemented in LibXR::USB::CDCUartReadPort.

Definition at line 517 of file libxr_rw.hpp.

517{}

◆ operator()()

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

读取操作符重载,用于执行读取操作。 Overloaded function call operator to perform a read operation.

该函数检查端口是否可读,并根据 data.size_op 的类型执行不同的操作。 This function checks if the port is readable and performs different actions based on data.size_ and the type of op.

Parameters
data包含要读取的数据。 Contains the data to be read.
op读取操作对象,包含操作类型和同步机制。 Read operation object containing the operation type and synchronization mechanism.
in_isr指示是否在中断上下文中执行。 Indicates whether the operation is executed in an interrupt context.
Returns
返回操作的 ErrorCode,指示操作结果。 Returns an ErrorCode indicating the result of the operation.

Definition at line 68 of file libxr_rw.cpp.

69{
70 if (Readable())
71 {
72 BusyState is_busy = busy_.load(std::memory_order_acquire);
73
74 if (is_busy != BusyState::IDLE && is_busy != BusyState::EVENT)
75 {
76 return ErrorCode::BUSY;
77 }
78
79 while (true)
80 {
81 busy_.store(BusyState::IDLE, std::memory_order_release);
82
83 auto readable_size = queue_data_->Size();
84
85 if (readable_size >= data.size_ && readable_size != 0)
86 {
87 if (data.size_ > 0)
88 {
89 auto ans =
90 queue_data_->PopBatch(reinterpret_cast<uint8_t*>(data.addr_), data.size_);
91 ASSERT(ans == ErrorCode::OK);
92 }
93
94 OnRxDequeue(in_isr);
95
96 if (op.type != ReadOperation::OperationType::BLOCK)
97 {
98 op.UpdateStatus(in_isr, ErrorCode::OK);
99 }
100 return ErrorCode::OK;
101 }
102
103 info_ = ReadInfoBlock{data, op};
104
105 op.MarkAsRunning();
106
107 auto ans = read_fun_(*this, in_isr);
108
109 if (ans == ErrorCode::PENDING)
110 {
111 BusyState expected = BusyState::IDLE;
112 if (busy_.compare_exchange_weak(expected, BusyState::PENDING,
113 std::memory_order_acq_rel,
114 std::memory_order_acquire))
115 {
116 break;
117 }
118 else
119 {
120 continue;
121 }
122 }
123 else
124 {
125 if (op.type == ReadOperation::OperationType::BLOCK)
126 {
127 return ans;
128 }
129 op.UpdateStatus(in_isr, ans);
130 return ErrorCode::OK;
131 }
132 }
133
134 if (op.type == ReadOperation::OperationType::BLOCK)
135 {
136 ASSERT(!in_isr);
137 auto wait_ans = op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
138 if (wait_ans == ErrorCode::OK)
139 {
140 // BLOCK_CLAIMED is always released by the waiter itself.
141 // BLOCK_CLAIMED 始终由 waiter 自己释放。
142#ifdef LIBXR_DEBUG_BUILD
143 auto state = busy_.load(std::memory_order_acquire);
144 ASSERT(state == BusyState::BLOCK_CLAIMED);
145#endif
146 busy_.store(BusyState::IDLE, std::memory_order_release);
147 return block_result_;
148 }
149
150 // Timeout won before completion claimed the waiter.
151 // 超时先赢,完成侧还没 claim 当前 waiter。
152 BusyState expected = BusyState::PENDING;
153 if (busy_.compare_exchange_strong(expected, BusyState::IDLE,
154 std::memory_order_acq_rel,
155 std::memory_order_acquire))
156 {
157 return ErrorCode::TIMEOUT;
158 }
159
160 if (expected != BusyState::BLOCK_CLAIMED)
161 {
162 // A detached late completion may already have cleared BLOCK_DETACHED
163 // back to IDLE before this waiter wakes from timeout.
164 // 分离后的迟到完成可能会在当前 waiter 超时醒来前,先把
165 // BLOCK_DETACHED 清回 IDLE。
166 ASSERT(expected == BusyState::BLOCK_DETACHED || expected == BusyState::IDLE);
167 if (expected == BusyState::BLOCK_DETACHED)
168 {
169 busy_.store(BusyState::IDLE, std::memory_order_release);
170 }
171 return ErrorCode::TIMEOUT;
172 }
173
174 // Timeout lost after completion had already claimed the waiter.
175 // 超时发生得太晚,完成侧已经 claim 了当前 waiter。
176 auto finish_wait_ans = op.data.sem_info.sem->Wait(UINT32_MAX);
177 UNUSED(finish_wait_ans);
178 ASSERT(finish_wait_ans == ErrorCode::OK);
179 busy_.store(BusyState::IDLE, std::memory_order_release);
180 return block_result_;
181 }
182 else
183 {
184 return ErrorCode::OK;
185 }
186 }
187 else
188 {
190 }
191}
size_t Size() const
获取当前队列中的元素数量 / Returns the number of elements currently in the queue
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
bool Readable()
Checks if read operations are supported.
Definition libxr_rw.cpp:30
virtual void OnRxDequeue(bool)
RX 数据从软件队列成功出队后的通知。 Notification after bytes are popped from RX data queue.
Definition libxr_rw.hpp:517
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:53
@ TIMEOUT
超时 | Timeout
@ BUSY
忙碌 | Busy
@ NOT_SUPPORT
不支持 | Not supported
@ PENDING
等待中 | Pending
@ OK
操作成功 | Operation successful
Read information block structure.
Definition libxr_rw.hpp:363

◆ operator=()

ReadPort & ReadPort::operator= ( ReadFun fun)

赋值运算符重载,用于设置读取函数。 Overloaded assignment operator to set the read function.

该函数允许使用 ReadFun 类型的函数对象赋值给 ReadPort,从而设置 read_fun_。 This function allows assigning a ReadFun function object to ReadPort, setting read_fun_.

Parameters
fun要分配的读取函数。 The read function to be assigned.
Returns
返回自身的引用,以支持链式调用。 Returns a reference to itself for chaining.

Definition at line 32 of file libxr_rw.cpp.

33{
34 read_fun_ = fun;
35 return *this;
36}

◆ ProcessPendingReads()

void ReadPort::ProcessPendingReads ( bool in_isr)

Processes pending reads.

处理挂起的读取请求。

Parameters
in_isr指示是否在中断上下文中执行。 Indicates whether the operation is executed in an interrupt context.

Definition at line 193 of file libxr_rw.cpp.

194{
195 ASSERT(queue_data_ != nullptr);
196
197 auto is_busy = busy_.load(std::memory_order_relaxed);
198
199 if (is_busy == BusyState::PENDING)
200 {
201 auto size = queue_data_->Size();
202 if (size > 0 && size >= info_.data.size_)
203 {
204 if (info_.op.type == ReadOperation::OperationType::BLOCK)
205 {
206 // Read BLOCK completion is claimed here before copying data.
207 // BLOCK 读完成在这里先 claim,再拷数据。
208 BusyState expected = BusyState::PENDING;
209 if (!busy_.compare_exchange_strong(expected, BusyState::BLOCK_CLAIMED,
210 std::memory_order_acq_rel,
211 std::memory_order_acquire))
212 {
213 return;
214 }
215 }
216
217 if (info_.data.size_ > 0)
218 {
219 auto ans = queue_data_->PopBatch(reinterpret_cast<uint8_t*>(info_.data.addr_),
220 info_.data.size_);
221 UNUSED(ans);
222 ASSERT(ans == ErrorCode::OK);
223 }
224
225 Finish(in_isr, ErrorCode::OK, info_);
226 OnRxDequeue(in_isr);
227 }
228 }
229 else if (is_busy == BusyState::IDLE)
230 {
231 busy_.store(BusyState::EVENT, std::memory_order_release);
232 }
233}
void Finish(bool in_isr, ErrorCode ans, ReadInfoBlock &info)
更新读取操作的状态。 Updates the status of the read operation.
Definition libxr_rw.cpp:38
RawData data
Data buffer. 数据缓冲区。
Definition libxr_rw.hpp:364

◆ Readable()

bool ReadPort::Readable ( )

Checks if read operations are supported.

检查是否支持读取操作。

Definition at line 30 of file libxr_rw.cpp.

30{ return read_fun_ != nullptr; }

◆ Reset()

void ReadPort::Reset ( )

Resets the ReadPort.

重置ReadPort。

Definition at line 235 of file libxr_rw.cpp.

236{
237 ASSERT(queue_data_ != nullptr);
238 queue_data_->Reset();
239
240 auto state = busy_.load(std::memory_order_acquire);
241 if (state == BusyState::PENDING && info_.op.type == ReadOperation::OperationType::BLOCK)
242 {
243 // Reset detaches the BLOCK waiter instead of reopening the port directly.
244 // Reset 先分离 BLOCK waiter,不直接重开端口。
245 BusyState expected = BusyState::PENDING;
246 if (busy_.compare_exchange_strong(expected, BusyState::BLOCK_DETACHED,
247 std::memory_order_acq_rel,
248 std::memory_order_acquire))
249 {
250 return;
251 }
252
253 state = busy_.load(std::memory_order_acquire);
254 }
255
257 {
258 return;
259 }
260
262 busy_.store(BusyState::IDLE, std::memory_order_release);
263}
void Reset()
重置队列 / Resets the queue

◆ Size()

size_t ReadPort::Size ( )

获取当前队列的已使用大小。 Gets the currently used size of the queue.

该函数返回 queue_block_ 当前已占用的空间大小。 This function returns the size of the space currently used in queue_block_.

Returns
返回队列的已使用大小(单位:字节)。 Returns the used size of the queue (in bytes).

Definition at line 24 of file libxr_rw.cpp.

25{
26 ASSERT(queue_data_ != nullptr);
27 return queue_data_->Size();
28}

Field Documentation

◆ block_result_

ErrorCode LibXR::ReadPort::block_result_ = ErrorCode::OK

Final status for the current BLOCK read.

Definition at line 409 of file libxr_rw.hpp.

◆ busy_

std::atomic<BusyState> LibXR::ReadPort::busy_ {BusyState::IDLE}

Definition at line 408 of file libxr_rw.hpp.

◆ info_

ReadInfoBlock LibXR::ReadPort::info_

Definition at line 407 of file libxr_rw.hpp.

◆ queue_data_

LockFreeQueue<uint8_t>* LibXR::ReadPort::queue_data_ = nullptr

Definition at line 406 of file libxr_rw.hpp.

◆ read_fun_

ReadFun LibXR::ReadPort::read_fun_ = nullptr

Definition at line 405 of file libxr_rw.hpp.


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