libxr 1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
libxr_rw.hpp
1#pragma once
2
3#include <cstdarg>
4#include <cstddef>
5#include <cstdint>
6#include <cstdio>
7#include <utility>
8
9#include "chunk_queue.hpp"
10#include "libxr_cb.hpp"
11#include "libxr_def.hpp"
12#include "libxr_type.hpp"
13#include "lockfree_queue.hpp"
14#include "mutex.hpp"
15#include "semaphore.hpp"
16
17namespace LibXR
18{
19
27template <typename... Args>
29{
30 public:
34 {
35 CALLBACK,
36 BLOCK,
37 POLLING,
38 NONE
39 };
40
44 {
45 READY,
46 RUNNING,
47 DONE
48 };
49
53
61 {
62 data.sem_info.sem = &sem;
63 data.sem_info.timeout = timeout;
64 }
65
72 {
73 data.callback = &callback;
74 }
75
82 {
83 data.status = &status;
84 }
85
93 {
94 if (this != &op)
95 {
96 type = op.type;
97 switch (type)
98 {
99 case OperationType::CALLBACK:
100 data.callback = op.data.callback;
101 break;
102 case OperationType::BLOCK:
103 data.sem_info.sem = op.data.sem_info.sem;
104 data.sem_info.timeout = op.data.sem_info.timeout;
105 break;
106 case OperationType::POLLING:
107 data.status = op.data.status;
108 break;
109 case OperationType::NONE:
110 break;
111 }
112 }
113 return *this;
114 }
115
123 {
124 if (this != &op)
125 {
126 type = op.type;
127 switch (type)
128 {
129 case OperationType::CALLBACK:
130 data.callback = op.data.callback;
131 break;
132 case OperationType::BLOCK:
133 data.sem_info.sem = op.data.sem_info.sem;
134 data.sem_info.timeout = op.data.sem_info.timeout;
135 break;
136 case OperationType::POLLING:
137 data.status = op.data.status;
138 break;
139 case OperationType::NONE:
140 break;
141 }
142 }
143 return *this;
144 }
145
146 Operation(const Operation &op) : type(op.type)
147 {
148 switch (type)
149 {
150 case OperationType::CALLBACK:
151 data.callback = op.data.callback;
152 break;
153 case OperationType::BLOCK:
154 data.sem = op.data.sem;
155 data.timeout = op.data.timeout;
156 break;
157 case OperationType::POLLING:
158 data.status = op.data.status;
159 break;
160 case OperationType::NONE:
161 break;
162 }
163 }
164
181 {
182 switch (type)
183 {
184 case OperationType::CALLBACK:
185 data.callback = op.data.callback;
186 break;
187 case OperationType::BLOCK:
188 data.sem_info.sem = op.data.sem_info.sem;
189 data.sem_info.timeout = op.data.sem_info.timeout;
190 break;
191 case OperationType::POLLING:
192 data.status = op.data.status;
193 break;
194 case OperationType::NONE:
195 break;
196 }
197 }
198
205 void UpdateStatus(bool in_isr, Args &&...args)
206 {
207 switch (type)
208 {
209 case OperationType::CALLBACK:
210 data.callback->Run(in_isr, std::forward<Args>(args)...);
211 break;
212 case OperationType::BLOCK:
213 data.sem_info.sem->PostFromCallback(in_isr);
214 break;
215 case OperationType::POLLING:
216 *data.status = OperationPollingStatus::DONE;
217 break;
218 case OperationType::NONE:
219 break;
220 }
221 }
222
237 {
238 if (type == OperationType::POLLING)
239 {
240 *data.status = OperationPollingStatus::RUNNING;
241 }
242 }
243
246 union
247 {
248 Callback<Args...> *callback;
249 struct
250 {
251 Semaphore *sem;
252 uint32_t timeout;
253 } sem_info;
256
260};
261
262class ReadPort;
263class WritePort;
264
268
272
275typedef ErrorCode (*WriteFun)(WritePort &port);
276
279typedef ErrorCode (*ReadFun)(ReadPort &port);
280
286{
287 public:
290
297 ReadInfoBlock(RawData data, ReadOperation &&op) : data_(data), op_(std::move(op)) {}
298
302};
303
309{
310 public:
311 ReadFun read_fun_ = nullptr;
312 LockFreeQueue<ReadInfoBlock> *queue_block_ = nullptr;
313 BaseQueue *queue_data_ = nullptr;
314 size_t read_size_ = 0;
315 Mutex mutex_;
316
323 ReadPort(size_t queue_size = 3, size_t buffer_size = 128)
324 : queue_block_(new LockFreeQueue<ReadInfoBlock>(queue_size)),
325 queue_data_(new BaseQueue(1, buffer_size))
326 {
327 }
328
339 size_t EmptySize() { return queue_data_->EmptySize(); }
340
351 size_t Size() { return queue_data_->Size(); }
352
355 bool Readable() { return read_fun_ != nullptr; }
356
371 {
372 read_fun_ = fun;
373 return *this;
374 }
375
393 void UpdateStatus(bool in_isr, ErrorCode ans, ReadInfoBlock &info, uint32_t size)
394 {
395 read_size_ = size;
396 info.op_.UpdateStatus(in_isr, std::forward<ErrorCode>(ans));
397 }
398
409 void UpdateStatus(ReadInfoBlock &info) { info.op_.MarkAsRunning(); }
410
427 ErrorCode operator()(RawData data, ReadOperation &op)
428 {
429 if (Readable())
430 {
431 if (data.size_ == 0)
432 {
433 op.UpdateStatus(false, ErrorCode::OK);
434 if (op.type == ReadOperation::OperationType::BLOCK)
435 {
436 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
437 }
438 return ErrorCode::OK;
439 }
440
442
443 ReadInfoBlock block = {data, std::move(op)};
444 if (queue_block_->Push(block) != ErrorCode::OK)
445 {
446 return ErrorCode::FULL;
447 }
448
449 auto ans = read_fun_(*this);
450 if (op.type == ReadOperation::OperationType::BLOCK)
451 {
452 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
453 }
454 else
455 {
456 return ans;
457 }
458 }
459 else
460 {
461 return ErrorCode::NOT_SUPPORT;
462 }
463 }
464
470 {
472 while (queue_block_->Peek(block) == ErrorCode::OK)
473 {
474 if (queue_data_->Size() >= block.data_.size_)
475 {
476 queue_data_->PopBatch(block.data_.addr_, block.data_.size_);
477 read_size_ = block.data_.size_;
478 block.op_.UpdateStatus(true, ErrorCode::OK);
479 queue_block_->Pop();
480 }
481 else
482 {
483 break;
484 }
485 }
486 }
487
490 void Reset()
491 {
492 queue_block_->Reset();
493 queue_data_->Reset();
494 read_size_ = 0;
495 }
496};
497
503{
504 public:
505 typedef struct
506 {
508 uint32_t size;
509 } WriteInfo;
510 WriteFun write_fun_ = nullptr;
511 LockFreeQueue<WriteInfo> *queue_info_;
512 LockFreeQueue<uint8_t> *queue_data_;
513 Mutex mutex_;
514 size_t write_size_ = 0;
515
529 WritePort(size_t queue_size = 3, size_t block_size = 128)
530 : queue_info_(new LockFreeQueue<WriteInfo>(queue_size)),
531 queue_data_(new LockFreeQueue<uint8_t>(block_size))
532 {
533 }
534
542 size_t EmptySize() { return queue_data_->EmptySize(); }
543
551 size_t Size() { return queue_data_->Size(); }
552
560 bool Writable() { return write_fun_ != nullptr; }
561
576 {
577 write_fun_ = fun;
578 return *this;
579 }
580
598 void UpdateStatus(bool in_isr, ErrorCode ans, WriteOperation &op, uint32_t size)
599 {
600 write_size_ = size;
601 op.UpdateStatus(in_isr, std::forward<ErrorCode>(ans));
602 }
603
615
633 {
634 if (Writable())
635 {
636 if (data.size_ == 0)
637 {
638 op.UpdateStatus(false, ErrorCode::OK);
639 if (op.type == WriteOperation::OperationType::BLOCK)
640 {
641 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
642 }
643 return ErrorCode::OK;
644 }
645
647
648 if (queue_data_->EmptySize() < data.size_ || queue_info_->EmptySize() < 1)
649 {
650 return ErrorCode::FULL;
651 }
652
653 auto ans = queue_data_->PushBatch(reinterpret_cast<const uint8_t *>(data.addr_),
654 data.size_);
655
656 ans = queue_info_->Push(
657 WriteInfo{std::forward<WriteOperation>(op), static_cast<uint32_t>(data.size_)});
658
659 ans = write_fun_(*this);
660 if (op.type == WriteOperation::OperationType::BLOCK)
661 {
662 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
663 }
664 else
665 {
666 return ans;
667 }
668 }
669 else
670 {
671 return ErrorCode::NOT_SUPPORT;
672 }
673 }
674
677 void Reset()
678 {
679 queue_info_->Reset();
680 queue_data_->Reset();
681 write_size_ = 0;
682 }
683};
684
689class STDIO
690{
691 public:
692 // NOLINTBEGIN
693 static inline ReadPort *read_ = nullptr;
694 static inline WritePort *write_ = nullptr;
695#if LIBXR_PRINTF_BUFFER_SIZE > 0
696 static inline char
698#endif
699 // NOLINTEND
700
710 static int Printf(const char *fmt, ...) // NOLINT
711 {
712#if LIBXR_PRINTF_BUFFER_SIZE > 0
713 if (!STDIO::write_ || !STDIO::write_->Writable())
714 {
715 return -1;
716 }
717
718 static LibXR::Mutex mutex; // NOLINT
719
721
723 va_start(args, fmt);
724 int len = vsnprintf(STDIO::printf_buff_, LIBXR_PRINTF_BUFFER_SIZE, fmt, args);
725 va_end(args);
726
727 // Check result and limit length
728 if (len < 0)
729 {
730 return -1;
731 }
732 if (static_cast<size_t>(len) >= LIBXR_PRINTF_BUFFER_SIZE)
733 {
735 }
736
737 ConstRawData data = {reinterpret_cast<const uint8_t *>(STDIO::printf_buff_),
738 static_cast<size_t>(len)};
739
740 static WriteOperation op; // NOLINT
741 return static_cast<int>(STDIO::write_->operator()(data, op));
742#else
743 UNUSED(fmt);
744 return 0;
745#endif
746 }
747};
748} // namespace LibXR
基础队列类,提供固定大小的循环缓冲区 (Base queue class providing a fixed-size circular buffer).
Definition queue.hpp:20
size_t Size()
获取队列中的元素个数 (Get the number of elements in the queue).
Definition queue.hpp:305
ErrorCode PopBatch(void *data, size_t size)
批量移除多个元素 (Pop multiple elements from the queue).
Definition queue.hpp:208
void Reset()
重置队列,清空所有数据 (Reset the queue and clear all data).
Definition queue.hpp:295
size_t EmptySize()
获取队列的空闲空间 (Get the available space in the queue).
Definition queue.hpp:325
提供一个通用的回调包装,支持动态参数传递。 Provides a generic callback wrapper, supporting dynamic argument passing.
Definition libxr_cb.hpp:124
常量原始数据封装类。 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 Pop(ElementData &item)
从队列中弹出数据 / Pops data from the queue
ErrorCode PushBatch(const Data *data, size_t size)
批量推入数据 / Pushes multiple elements into the queue
ErrorCode Push(ElementData &&item)
向队列中推入数据 / Pushes data 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 Peek(Data &item)
获取队列头部数据但不弹出 / Retrieves the front data of the queue without popping
互斥锁的 RAII 机制封装 (RAII-style mechanism for automatic mutex management).
Definition mutex.hpp:95
互斥锁类,提供线程同步机制 (Mutex class providing thread synchronization mechanisms).
Definition mutex.hpp:18
Defines an operation with different execution modes.
Definition libxr_rw.hpp:29
Operation & operator=(const Operation &op)
Copy assignment operator.
Definition libxr_rw.hpp:92
void UpdateStatus(bool in_isr, Args &&...args)
Updates operation status based on type.
Definition libxr_rw.hpp:205
Operation(Semaphore &sem, uint32_t timeout=UINT32_MAX)
Constructs a blocking operation with a semaphore and timeout.
Definition libxr_rw.hpp:60
Operation & operator=(Operation &&op) noexcept
Move assignment operator.
Definition libxr_rw.hpp:122
Operation()
Default constructor, initializes with NONE type.
Definition libxr_rw.hpp:52
Operation(Callback< Args... > &callback)
Constructs a callback-based operation.
Definition libxr_rw.hpp:71
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:236
union LibXR::Operation::@4 data
OperationType type
Definition libxr_rw.hpp:259
Operation(OperationPollingStatus &status)
Constructs a polling operation.
Definition libxr_rw.hpp:81
Operation(Operation &&op) noexcept
构造一个新的 Operation 对象(移动构造函数)。 Constructs a new Operation object (move constructor).
Definition libxr_rw.hpp:180
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
Read information block structure.
Definition libxr_rw.hpp:286
ReadOperation op_
Read operation instance. 读取操作实例。
Definition libxr_rw.hpp:289
ReadInfoBlock()
Default constructor.
Definition libxr_rw.hpp:301
ReadInfoBlock(RawData data, ReadOperation &&op)
Constructs a ReadInfoBlock.
Definition libxr_rw.hpp:297
RawData data_
Data buffer. 数据缓冲区。
Definition libxr_rw.hpp:288
ReadPort class for handling read operations.
Definition libxr_rw.hpp:309
ReadPort & operator=(ReadFun fun)
赋值运算符重载,用于设置读取函数。 Overloaded assignment operator to set the read function.
Definition libxr_rw.hpp:370
void ProcessPendingReads()
Processes pending reads.
Definition libxr_rw.hpp:469
size_t Size()
获取当前队列的已使用大小。 Gets the currently used size of the queue.
Definition libxr_rw.hpp:351
void Reset()
Resets the ReadPort.
Definition libxr_rw.hpp:490
bool Readable()
Checks if read operations are supported.
Definition libxr_rw.hpp:355
void UpdateStatus(ReadInfoBlock &info)
标记读取操作为运行中。 Marks the read operation as running.
Definition libxr_rw.hpp:409
size_t EmptySize()
获取队列的剩余可用空间。 Gets the remaining available space in the queue.
Definition libxr_rw.hpp:339
ReadPort(size_t queue_size=3, size_t buffer_size=128)
Constructs a ReadPort with queue sizes.
Definition libxr_rw.hpp:323
void UpdateStatus(bool in_isr, ErrorCode ans, ReadInfoBlock &info, uint32_t size)
更新读取操作的状态。 Updates the status of the read operation.
Definition libxr_rw.hpp:393
ErrorCode operator()(RawData data, ReadOperation &op)
读取操作符重载,用于执行读取操作。 Overloaded function call operator to perform a read operation.
Definition libxr_rw.hpp:427
STDIO interface for read/write ports.
Definition libxr_rw.hpp:690
static ReadPort * read_
Read port instance. 读取端口。
Definition libxr_rw.hpp:693
static WritePort * write_
Write port instance. 写入端口。
Definition libxr_rw.hpp:694
static int Printf(const char *fmt,...)
Prints a formatted string to the write port (like printf).
Definition libxr_rw.hpp:710
信号量类,实现线程同步机制 Semaphore class implementing thread synchronization
Definition semaphore.hpp:23
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:15
WritePort class for handling write operations.
Definition libxr_rw.hpp:503
size_t EmptySize()
获取数据队列的剩余可用空间。 Gets the remaining available space in the data queue.
Definition libxr_rw.hpp:542
void UpdateStatus(WriteOperation &op)
标记写入操作为运行中。 Marks the write operation as running.
Definition libxr_rw.hpp:614
WritePort(size_t queue_size=3, size_t block_size=128)
构造一个新的 WritePort 对象。 Constructs a new WritePort object.
Definition libxr_rw.hpp:529
ErrorCode operator()(ConstRawData data, WriteOperation &op)
执行写入操作。 Performs a write operation.
Definition libxr_rw.hpp:632
WritePort & operator=(WriteFun fun)
赋值运算符重载,用于设置写入函数。 Overloaded assignment operator to set the write function.
Definition libxr_rw.hpp:575
size_t Size()
获取当前数据队列的已使用大小。 Gets the used size of the current data queue.
Definition libxr_rw.hpp:551
bool Writable()
判断端口是否可写。 Checks whether the port is writable.
Definition libxr_rw.hpp:560
void UpdateStatus(bool in_isr, ErrorCode ans, WriteOperation &op, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.hpp:598
void Reset()
Resets the WritePort.
Definition libxr_rw.hpp:677
LibXR Color Control Library / LibXR终端颜色控制库
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:279
Operation< ErrorCode > ReadOperation
Read operation type.
Definition libxr_rw.hpp:267
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:275
constexpr auto min(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最小值
Operation< ErrorCode > WriteOperation
Write operation type.
Definition libxr_rw.hpp:271