libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
libxr_rw.cpp
1#include "libxr_rw.hpp"
2
3using namespace LibXR;
4
7
8ReadPort::ReadPort(size_t buffer_size)
9 : queue_data_(buffer_size > 0 ? new(std::align_val_t(LIBXR_CACHE_LINE_SIZE))
10 LockFreeQueue<uint8_t>(buffer_size)
11 : nullptr)
12{
13}
14
16{
17 ASSERT(queue_data_ != nullptr);
18 return queue_data_->EmptySize();
19}
20
22{
23 ASSERT(queue_data_ != nullptr);
24 return queue_data_->Size();
25}
26
27bool ReadPort::Readable() { return read_fun_ != nullptr; }
28
30{
31 read_fun_ = fun;
32 return *this;
33}
34
35void ReadPort::Finish(bool in_isr, ErrorCode ans, ReadInfoBlock& info, uint32_t size)
36{
37 read_size_ = size;
38 busy_.store(BusyState::Idle, std::memory_order_release);
39 info.op.UpdateStatus(in_isr, std::forward<ErrorCode>(ans));
40}
41
43
45{
46 if (Readable())
47 {
48 mutex_.Lock();
49
50 BusyState is_busy = busy_.load(std::memory_order_relaxed);
51
52 if (is_busy == BusyState::Pending)
53 {
54 mutex_.Unlock();
55 return ErrorCode::BUSY;
56 }
57
58 while (true)
59 {
60 busy_.store(BusyState::Idle, std::memory_order_release);
61
62 if (queue_data_ != nullptr)
63 {
64 auto readable_size = queue_data_->Size();
65
66 if (readable_size >= data.size_ && readable_size != 0)
67 {
68 auto ans =
69 queue_data_->PopBatch(reinterpret_cast<uint8_t*>(data.addr_), data.size_);
70 UNUSED(ans);
71 read_size_ = data.size_;
72 ASSERT(ans == ErrorCode::OK);
73 if (op.type != ReadOperation::OperationType::BLOCK)
74 {
75 op.UpdateStatus(false, ErrorCode::OK);
76 }
77 mutex_.Unlock();
78 return ErrorCode::OK;
79 }
80 }
81
82 info_ = ReadInfoBlock{data, op};
83
84 op.MarkAsRunning();
85
86 auto ans = read_fun_(*this);
87
88 if (ans != ErrorCode::OK)
89 {
90 BusyState expected = BusyState::Idle;
91 if (busy_.compare_exchange_strong(expected, BusyState::Pending,
92 std::memory_order_acq_rel,
93 std::memory_order_acquire))
94 {
95 break;
96 }
97 else
98 {
99 expected = BusyState::Pending;
100 continue;
101 }
102 }
103 else
104 {
105 read_size_ = data.size_;
106 if (op.type != ReadOperation::OperationType::BLOCK)
107 {
108 op.UpdateStatus(false, ErrorCode::OK);
109 }
110 mutex_.Unlock();
111 return ErrorCode::OK;
112 }
113 }
114
115 mutex_.Unlock();
116
117 if (op.type == ReadOperation::OperationType::BLOCK)
118 {
119 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
120 }
121 else
122 {
123 return ErrorCode::OK;
124 }
125 }
126 else
127 {
128 return ErrorCode::NOT_SUPPORT;
129 }
130}
131
133{
134 ASSERT(queue_data_ != nullptr);
135
136 if (in_isr)
137 {
138 auto is_busy = busy_.load(std::memory_order_relaxed);
139
140 if (is_busy == BusyState::Pending)
141 {
142 if (queue_data_->Size() >= info_.data.size_)
143 {
144 if (info_.data.size_ > 0)
145 {
146 auto ans = queue_data_->PopBatch(reinterpret_cast<uint8_t*>(info_.data.addr_),
147 info_.data.size_);
148 UNUSED(ans);
149 ASSERT(ans == ErrorCode::OK);
150 }
151 Finish(in_isr, ErrorCode::OK, info_, info_.data.size_);
152 }
153 }
154 else if (is_busy == BusyState::Idle)
155 {
156 busy_.store(BusyState::Event, std::memory_order_release);
157 }
158 }
159 else
160 {
161 LibXR::Mutex::LockGuard lock_guard(mutex_);
162 if (busy_.load(std::memory_order_relaxed) == BusyState::Pending)
163 {
164 if (queue_data_->Size() >= info_.data.size_)
165 {
166 if (info_.data.size_ > 0)
167 {
168 auto ans = queue_data_->PopBatch(reinterpret_cast<uint8_t*>(info_.data.addr_),
169 info_.data.size_);
170 UNUSED(ans);
171 ASSERT(ans == ErrorCode::OK);
172 }
173 Finish(in_isr, ErrorCode::OK, info_, info_.data.size_);
174 }
175 }
176 }
177}
178
180{
181 ASSERT(queue_data_ != nullptr);
182 Mutex::LockGuard lock_guard(mutex_);
183 queue_data_->Reset();
184 read_size_ = 0;
185}
186
187WritePort::WritePort(size_t queue_size, size_t buffer_size)
188 : queue_info_(new(std::align_val_t(LIBXR_CACHE_LINE_SIZE))
189 LockFreeQueue<WriteInfoBlock>(queue_size)),
190 queue_data_(buffer_size > 0 ? new(std::align_val_t(LIBXR_CACHE_LINE_SIZE))
191 LockFreeQueue<uint8_t>(buffer_size)
192 : nullptr)
193{
194}
195
197{
198 ASSERT(queue_data_ != nullptr);
199 return queue_data_->EmptySize();
200}
201
203{
204 ASSERT(queue_data_ != nullptr);
205 return queue_data_->Size();
206}
207
208bool WritePort::Writable() { return write_fun_ != nullptr; }
209
211{
212 write_fun_ = fun;
213 return *this;
214}
215
216void WritePort::Finish(bool in_isr, ErrorCode ans, WriteInfoBlock& info, uint32_t size)
217{
218 write_size_ = size;
219 info.op.UpdateStatus(in_isr, std::forward<ErrorCode>(ans));
220}
221
223
225{
226 if (Writable())
227 {
228 if (data.size_ == 0)
229 {
230 write_size_ = 0;
231 if (op.type != WriteOperation::OperationType::BLOCK)
232 {
233 op.UpdateStatus(false, ErrorCode::OK);
234 }
235 return ErrorCode::OK;
236 }
237
238 mutex_.Lock();
239
240 if (queue_info_->EmptySize() < 1)
241 {
242 mutex_.Unlock();
243 return ErrorCode::FULL;
244 }
245
246 if (queue_data_)
247 {
248 if (queue_data_->EmptySize() < data.size_)
249 {
250 mutex_.Unlock();
251 return ErrorCode::FULL;
252 }
253
254 auto ans = queue_data_->PushBatch(reinterpret_cast<const uint8_t*>(data.addr_),
255 data.size_);
256 UNUSED(ans);
257 ASSERT(ans == ErrorCode::OK);
258
259 WriteInfoBlock info{data, op};
260 ans = queue_info_->Push(info);
261
262 ASSERT(ans == ErrorCode::OK);
263
264 op.MarkAsRunning();
265
266 ans = write_fun_(*this);
267
268 mutex_.Unlock();
269
270 if (ans == ErrorCode::OK)
271 {
272 write_size_ = data.size_;
273 if (op.type != WriteOperation::OperationType::BLOCK)
274 {
275 op.UpdateStatus(false, ErrorCode::OK);
276 }
277 return ErrorCode::OK;
278 }
279
280 if (op.type == WriteOperation::OperationType::BLOCK)
281 {
282 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
283 }
284
285 return ErrorCode::OK;
286 }
287 else
288 {
289 WriteInfoBlock info{data, op};
290 auto ans = queue_info_->Push(info);
291
292 ASSERT(ans == ErrorCode::OK);
293
294 op.MarkAsRunning();
295
296 ans = write_fun_(*this);
297
298 mutex_.Unlock();
299
300 if (ans == ErrorCode::OK)
301 {
302 write_size_ = data.size_;
303 if (op.type != WriteOperation::OperationType::BLOCK)
304 {
305 op.UpdateStatus(false, ErrorCode::OK);
306 }
307 return ErrorCode::OK;
308 }
309
310 if (op.type == WriteOperation::OperationType::BLOCK)
311 {
312 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
313 }
314 else
315 {
316 return ErrorCode::OK;
317 }
318 }
319 }
320 else
321 {
322 return ErrorCode::NOT_SUPPORT;
323 }
324}
325
327{
328 ASSERT(queue_data_ != nullptr);
329 Mutex::LockGuard lock_guard(mutex_);
330 queue_info_->Reset();
331 queue_data_->Reset();
332 write_size_ = 0;
334
335int STDIO::Printf(const char* fmt, ...)
336{
337#if LIBXR_PRINTF_BUFFER_SIZE > 0
338 if (!STDIO::write_ || !STDIO::write_->Writable())
339 {
340 return -1;
341 }
342
343 static LibXR::Mutex mutex; // NOLINT
344
345 LibXR::Mutex::LockGuard lock_guard(mutex);
346
347 va_list args;
348 va_start(args, fmt);
349 int len = vsnprintf(STDIO::printf_buff_, LIBXR_PRINTF_BUFFER_SIZE, fmt, args);
350 va_end(args);
351
352 // Check result and limit length
353 if (len < 0)
354 {
355 return -1;
356 }
357 if (static_cast<size_t>(len) >= LIBXR_PRINTF_BUFFER_SIZE)
358 {
359 len = LIBXR_PRINTF_BUFFER_SIZE - 1;
360 }
361
362 ConstRawData data = {reinterpret_cast<const uint8_t*>(STDIO::printf_buff_),
363 static_cast<size_t>(len)};
364
365 static WriteOperation op; // NOLINT
366 return static_cast<int>(STDIO::write_->operator()(data, op));
367#else
368 UNUSED(fmt);
369 return 0;
370#endif
371}
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
无锁队列实现 / Lock-free queue implementation
void Reset()
重置队列 / Resets the queue
ErrorCode PushBatch(const Data *data, size_t size)
批量推入数据 / Pushes multiple elements into the queue
size_t EmptySize()
计算队列剩余可用空间 / Calculates the remaining available space in the queue
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
互斥锁的 RAII 机制封装 (RAII-style mechanism for automatic mutex management).
Definition mutex.hpp:65
互斥锁类,提供线程同步机制 (Mutex class providing thread synchronization mechanisms).
Definition mutex.hpp:18
ErrorCode Lock()
加锁,如果锁已被占用,则阻塞等待 (Lock the mutex, blocking if it is already locked).
Definition mutex.cpp:14
void Unlock()
解锁互斥锁 (Unlock the mutex).
Definition mutex.cpp:28
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:202
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
Definition libxr_rw.hpp:171
union LibXR::Operation::@4 data
OperationType type
Definition libxr_rw.hpp:225
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
ReadPort class for handling read operations.
Definition libxr_rw.hpp:268
bool Readable()
Checks if read operations are supported.
Definition libxr_rw.cpp:27
ReadPort(size_t buffer_size=128)
Constructs a ReadPort with queue sizes.
Definition libxr_rw.cpp:8
void Finish(bool in_isr, ErrorCode ans, ReadInfoBlock &info, uint32_t size)
更新读取操作的状态。 Updates the status of the read operation.
Definition libxr_rw.cpp:35
virtual void Reset()
Resets the ReadPort.
Definition libxr_rw.cpp:179
virtual size_t EmptySize()
获取队列的剩余可用空间。 Gets the remaining available space in the queue.
Definition libxr_rw.cpp:15
ErrorCode operator()(RawData data, ReadOperation &op)
读取操作符重载,用于执行读取操作。 Overloaded function call operator to perform a read operation.
Definition libxr_rw.cpp:44
virtual void ProcessPendingReads(bool in_isr)
Processes pending reads.
Definition libxr_rw.cpp:132
ReadPort & operator=(ReadFun fun)
赋值运算符重载,用于设置读取函数。 Overloaded assignment operator to set the read function.
Definition libxr_rw.cpp:29
virtual size_t Size()
获取当前队列的已使用大小。 Gets the currently used size of the queue.
Definition libxr_rw.cpp:21
void MarkAsRunning(ReadInfoBlock &info)
标记读取操作为运行中。 Marks the read operation as running.
Definition libxr_rw.cpp:42
static int Printf(const char *fmt,...)
Prints a formatted string to the write port (like printf).
Definition libxr_rw.cpp:335
static WritePort * write_
Write port instance. 写入端口。
Definition libxr_rw.hpp:531
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:25
WritePort class for handling write operations.
Definition libxr_rw.hpp:403
virtual size_t EmptySize()
获取数据队列的剩余可用空间。 Gets the remaining available space in the data queue.
Definition libxr_rw.cpp:196
virtual size_t Size()
获取当前数据队列的已使用大小。 Gets the used size of the current data queue.
Definition libxr_rw.cpp:202
ErrorCode operator()(ConstRawData data, WriteOperation &op)
执行写入操作。 Performs a write operation.
Definition libxr_rw.cpp:224
WritePort(size_t queue_size=3, size_t buffer_size=128)
构造一个新的 WritePort 对象。 Constructs a new WritePort object.
Definition libxr_rw.cpp:187
WritePort & operator=(WriteFun fun)
赋值运算符重载,用于设置写入函数。 Overloaded assignment operator to set the write function.
Definition libxr_rw.cpp:210
bool Writable()
判断端口是否可写。 Checks whether the port is writable.
Definition libxr_rw.cpp:208
void MarkAsRunning(WriteOperation &op)
标记写入操作为运行中。 Marks the write operation as running.
Definition libxr_rw.cpp:222
virtual void Reset()
Resets the WritePort.
Definition libxr_rw.cpp:326
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.cpp:216
LibXR 命名空间
Definition ch32_gpio.hpp:9
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:245
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:241
Read information block structure.
Definition libxr_rw.hpp:252
RawData data
Data buffer. 数据缓冲区。
Definition libxr_rw.hpp:253
ReadOperation op
Read operation instance. 读取操作实例。
Definition libxr_rw.hpp:254