Skip to content

Commit a1386a0

Browse files
committed
Update structure.
1 parent bf8837d commit a1386a0

File tree

16 files changed

+1113
-2
lines changed

16 files changed

+1113
-2
lines changed

docs/basic_coding/structure/README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,23 @@ sidebar_position: 2
66

77
# 数据结构
88

9-
本模块汇总了 LibXR 中的数据结构,涵盖队列、栈、链表、红黑树、双缓冲区等,适用于嵌入式系统中的任务调度、数据通信与资源管理。每个数据结构根据用途和平台约束设计,有的具备线程安全性,有的为性能优化采用无锁机制,具体信息请查阅各子页面说明。
9+
本模块汇总了 LibXR 中用于任务调度、数据通信、资源管理等场景的通用数据结构,设计充分考虑嵌入式系统中的内存限制、并发访问与平台差异,涵盖如下内容:
10+
11+
## 模块特性
12+
13+
- **平台独立**:所有接口均采用平台无关的抽象,支持移植。
14+
- **内存可控**:多数结构支持外部缓冲或固定容量,避免运行时分配。
15+
- **线程/中断安全**:部分结构使用互斥锁或无锁算法设计,适配多线程/中断上下文。
16+
- **结构清晰**:每种结构均封装基础节点、模板节点与核心操作接口,易于扩展。
17+
18+
## 快速导航
19+
20+
- [Queue(队列)](./queue.md)
21+
- [LockFreeQueue(无锁队列)](./lockfree_queue.md)
22+
- [Stack(栈)](./stack.md)
23+
- [List(链表)](./list.md)
24+
- [LockFreeList(无锁链表)](./lockfree_list.md)
25+
- [RBTree(红黑树)](./rbt.md)
26+
- [DoubleBuffer(双缓冲区)](./double_buffer.md)
27+
28+
更多使用方式、性能差异与适用场景,请参考各页面的详细说明及设计思想。
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
id: double_buffer
3+
title: 双缓冲区
4+
sidebar_position: 7
5+
---
6+
7+
# 双缓冲区(DoubleBuffer)
8+
9+
`LibXR::DoubleBuffer` 是一个嵌入式场景下的双缓冲数据结构,主要用于 DMA、USB 等高速传输中数据的无缝切换与填充控制。支持主动与备用缓冲的数据管理机制,在性能要求高的数据发送任务中尤为适用。
10+
11+
## 核心特性
12+
13+
- 将一块连续内存分为两个缓冲区。
14+
- 支持主动缓冲(active)与备用缓冲(pending)之间切换。
15+
- 提供对两个缓冲区的直接访问与数据填充接口。
16+
- 支持手动切换与自动有效性检测。
17+
- 可查询备用区是否准备好、已填充长度。
18+
19+
## 接口概览
20+
21+
### 构造函数
22+
23+
```cpp
24+
explicit DoubleBuffer(const LibXR::RawData& raw_data);
25+
```
26+
27+
- 接收一段连续内存,并自动划分为两个缓冲区。
28+
29+
### 数据操作接口
30+
31+
- `uint8_t* ActiveBuffer()`:获取当前使用的缓冲区。
32+
- `uint8_t* PendingBuffer()`:获取备用缓冲区。
33+
- `bool FillActive(const uint8_t* data, size_t len)`:写入当前缓冲区。
34+
- `bool FillPending(const uint8_t* data, size_t len)`:写入备用缓冲区。
35+
- `void EnablePending()`:手动标记备用区为有效(与 FillActive 配合使用)。
36+
- `bool HasPending() const`:是否存在准备切换的缓冲区。
37+
- `void Switch()`:切换 active/pending 缓冲。
38+
- `size_t PendingLength() const`:获取备用缓冲中的有效数据长度。
39+
- `size_t Size() const`:每个缓冲区的容量。
40+
41+
## 使用示例
42+
43+
```cpp
44+
LibXR::RawData mem{malloc(512), 512};
45+
LibXR::DoubleBuffer buf(mem);
46+
47+
// 第一次写入备用缓冲区
48+
buf.FillPending(data1, len1);
49+
if (buf.HasPending()) {
50+
buf.Switch(); // 切换为新的 active 缓冲
51+
}
52+
53+
// 填充当前 active 区用于初始传输
54+
buf.FillActive(data2, len2);
55+
buf.EnablePending(); // 标记当前 active 将作为 pending 切换
56+
```
57+
58+
## 注意事项
59+
60+
- 填充备用区后需调用 `Switch()` 才能激活其数据。
61+
- 不支持动态分配,内存必须在构造前准备。
62+
- `FillPending` 不可重入,调用前应确认 pending 状态为 false。
63+
- `EnablePending()``FillActive()` 配合实现主动缓存切换。
64+
65+
## 应用场景
66+
67+
- USB CDC / Audio 数据发送
68+
- DMA 数据流优化
69+
- 双缓存 ping-pong 通信机制

docs/basic_coding/structure/list.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
id: list
3+
title: 链表
4+
sidebar_position: 4
5+
---
6+
7+
# 链表(List)
8+
9+
`LibXR::List` 是一个线程安全的通用链表容器,支持动态添加、删除和遍历节点。每个节点均继承自 `BaseNode`,可以通过模板 `Node<T>` 封装任意数据类型。适用于事件回调、资源管理等灵活数据结构需求。
10+
11+
## 核心特性
12+
13+
- 所有节点继承自 `BaseNode`,统一结构。
14+
- 提供 `Node<T>` 模板类封装数据。
15+
- 支持线程安全的添加、删除和遍历。
16+
- 内部使用循环链表结构,避免空指针问题。
17+
- 遍历时支持结构大小校验,保障类型安全。
18+
19+
## 类结构
20+
21+
- `BaseNode`:所有节点基类,记录大小与指针。
22+
- `Node<T>`:模板节点类,封装用户数据。
23+
- `List`:容器本体,提供 Add / Delete / Foreach 接口。
24+
25+
## 接口说明
26+
27+
### 节点类
28+
29+
```cpp
30+
class BaseNode {
31+
BaseNode* next_;
32+
size_t size_;
33+
};
34+
35+
template <typename T>
36+
class Node : public BaseNode {
37+
T data_;
38+
};
39+
```
40+
41+
### 构造与析构
42+
43+
- `List()`:初始化循环链表头。
44+
- `~List()`:销毁链表并清空所有节点指针。
45+
46+
### 插入与删除
47+
48+
- `void Add(BaseNode& node)`:将节点加入链表头部。
49+
- `ErrorCode Delete(BaseNode& node)`:从链表中移除指定节点。
50+
51+
### 查询与遍历
52+
53+
- `uint32_t Size()`:获取链表中节点数。
54+
- `ErrorCode Foreach(Func func)`:遍历所有节点并调用函数。
55+
- lambda中返回 `ErrorCode::OK` 时继续遍历,返回 `ErrorCode::ERROR` 时中断遍历。
56+
57+
### Foreach 使用示例
58+
59+
```cpp
60+
LibXR::List list;
61+
LibXR::List::Node<int> node1(42);
62+
list.Add(node1);
63+
64+
list.Foreach<int>([](int& data) {
65+
// 访问每个节点数据
66+
return LibXR::ErrorCode::OK;
67+
});
68+
```
69+
70+
## 注意事项
71+
72+
- 节点由用户申请与释放,`List` 不负责内存管理。
73+
- 每个节点只能同时存在于一个链表中。
74+
- `Foreach` 支持结构校验,确保类型匹配。
75+
76+
## 典型应用
77+
78+
- 动态注册的回调列表
79+
- 插件或模块管理
80+
- 系统资源追踪
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
id: lockfree_list
3+
title: 无锁链表
4+
sidebar_position: 5
5+
---
6+
7+
# LockFreeList(无锁链表)
8+
9+
`LibXR::LockFreeList` 是一个线程安全的无锁链表容器,基于原子操作实现,适用于高并发场景下的事件注册、回调管理、资源追踪等。
10+
11+
## 核心特性
12+
13+
- 使用 C++11 原子操作实现的单向链表。
14+
- 所有节点继承自 `BaseNode`,具有统一结构与大小标识。
15+
- 支持任意数据类型节点:通过模板 `Node<T>` 封装。
16+
- 支持无锁添加与安全遍历(不可删除)。
17+
- 遍历时自动进行结构大小检查,确保类型安全。
18+
- 不涉及动态内存分配,节点由用户管理。
19+
20+
## 类结构
21+
22+
- `BaseNode`:抽象节点类型,提供 `next_` 原子指针和 `size_` 成员。
23+
- `Node<T>`:模板节点类,内嵌用户数据成员 `data_`
24+
- `LockFreeList`:容器本体,提供 `Add``Foreach` 接口。
25+
26+
## 接口说明
27+
28+
### 添加节点
29+
30+
```cpp
31+
void Add(BaseNode& node);
32+
```
33+
34+
- 将新节点插入链表头部(LIFO 顺序),线程安全。
35+
36+
### 遍历节点
37+
38+
```cpp
39+
template <typename Data, typename Func, SizeLimitMode LimitMode = MORE>
40+
ErrorCode Foreach(Func func);
41+
```
42+
43+
- 遍历链表中所有节点,对数据调用回调 `func(Data&)`
44+
- 使用 `SizeLimitMode` 模式检查节点数据类型。
45+
- lambda中返回 `ErrorCode::OK` 时继续遍历,返回 `ErrorCode::ERROR` 时中断遍历。
46+
47+
### 获取大小
48+
49+
```cpp
50+
uint32_t Size();
51+
```
52+
53+
- 返回链表中当前节点个数。
54+
55+
### 使用示例
56+
57+
```cpp
58+
LibXR::LockFreeList list;
59+
LibXR::LockFreeList::Node<int> node1(123);
60+
list.Add(node1);
61+
62+
list.Foreach<int>([](int& val) {
63+
// 访问 val
64+
return LibXR::ErrorCode::OK;
65+
});
66+
```
67+
68+
## 注意事项
69+
70+
- 本链表不支持删除节点,适合“只增不删”的注册场景。
71+
- 节点生命周期由用户控制,需避免重复添加或早期析构。
72+
- 遍历过程中不可修改链表结构。
73+
74+
## 典型应用
75+
76+
- 中断/任务中注册的异步回调
77+
- 模块注册与状态追踪
78+
- 不可变注册表或只增表结构
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
id: lockfree_queue
3+
title: 无锁队列
4+
sidebar_position: 2
5+
---
6+
7+
# LockFreeQueue(无锁队列)
8+
9+
`LibXR::LockFreeQueue<T>` 是一个高性能单生产者多消费者(SPMC)无锁队列,适用于实时性要求高、并发访问频繁的嵌入式系统中。
10+
11+
## 类结构与原理
12+
13+
- 使用原子变量 `head_``tail_` 管理队列索引。
14+
- 所有操作使用 C++11 原子内存序保证线程安全。
15+
- 环形缓冲结构支持批量读写,避免频繁中断。
16+
- 多个消费者可以并发 Pop,生产者唯一。
17+
18+
## 特性概览
19+
20+
| 特性 | 支持 |
21+
|------|------|
22+
| 单生产者 ||
23+
| 多消费者 ||
24+
| 批量操作 ||
25+
| Peek/Pop 分离 ||
26+
| 动态容量 | ❌(固定容量) |
27+
| 无锁保证 | ✅(C++11 atomic) |
28+
29+
## 接口函数
30+
31+
### 构造与销毁
32+
33+
- `LockFreeQueue(size_t length)`
34+
- `~LockFreeQueue()`
35+
36+
### 数据操作
37+
38+
- `ErrorCode Push(const T&)`
39+
- `ErrorCode Pop(T&)`
40+
- `ErrorCode Pop()`(丢弃头部元素)
41+
- `ErrorCode Peek(T&)`
42+
43+
### 批量操作
44+
45+
- `PushBatch(const T* data, size_t size)`
46+
- `PopBatch(T* data, size_t size)`
47+
- `PeekBatch(T* data, size_t size)`
48+
49+
### 工具接口
50+
51+
- `Size()`:当前元素数量
52+
- `EmptySize()`:剩余空间
53+
- `Reset()`:重置队列为空
54+
55+
## 使用示例
56+
57+
```cpp
58+
LibXR::LockFreeQueue<int> q(128);
59+
q.Push(10);
60+
61+
int value;
62+
if (q.Pop(value) == LibXR::ErrorCode::OK) {
63+
// 使用 value
64+
}
65+
```
66+
67+
## 注意事项
68+
69+
- 仅适用于 **单生产者** 场景,多生产者需使用外部同步或其他队列方案。
70+
- 容量固定,构造时需明确所需大小。
71+
- 数据结构对齐至 cache line,可减少伪共享带来的性能损失。
72+
73+
## 适用场景
74+
75+
- 中断与任务线程间的数据通信
76+
- 实时日志收集
77+
- 多线程传感器数据采样

0 commit comments

Comments
 (0)