|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +AI 编程助手在本 C++20 协程库中的开发指南。 |
| 4 | + |
| 5 | +## 项目概述 |
| 6 | + |
| 7 | +**coro** 是一个轻量级、仅头文件的 C++20 协程库,提供异步任务、同步原语和并发控制。设计目标:简洁、跨平台(包括嵌入式/MCU)、可选的无异常模式。 |
| 8 | + |
| 9 | +## 构建命令 |
| 10 | + |
| 11 | +```bash |
| 12 | +# 标准构建 |
| 13 | +cmake -S . -B build && cmake --build build -j |
| 14 | + |
| 15 | +# 启用 AddressSanitizer |
| 16 | +cmake -S . -B build -DCORO_ENABLE_SANITIZE_ADDRESS=ON && cmake --build build |
| 17 | + |
| 18 | +# 启用 ThreadSanitizer |
| 19 | +cmake -S . -B build -DCORO_ENABLE_SANITIZE_THREAD=ON && cmake --build build |
| 20 | + |
| 21 | +# 禁用异常(用于嵌入式平台) |
| 22 | +cmake -S . -B build -DCORO_DISABLE_EXCEPTION=ON && cmake --build build |
| 23 | +``` |
| 24 | + |
| 25 | +默认使用`build`文件夹,特殊构建时,可使用`build_asan`,`build_release`文件夹。 |
| 26 | + |
| 27 | +## 运行测试 |
| 28 | + |
| 29 | +每个测试是独立的可执行文件,在 build 目录下运行: |
| 30 | + |
| 31 | +```bash |
| 32 | +./coro_task # 核心异步任务测试 |
| 33 | +./coro_mutex # 互斥锁测试 |
| 34 | +./coro_channel # 通道测试 |
| 35 | +./coro_when # when_all/when_any 测试 |
| 36 | +./coro_semaphore # 信号量测试 |
| 37 | +./coro_condition_variable # 条件变量测试 |
| 38 | +./coro_wait_group # 等待组测试 |
| 39 | +./coro_latch # 闩锁测试 |
| 40 | +./coro_event # 事件测试 |
| 41 | +./coro_broadcast # 通道广播测试 |
| 42 | +./coro_task_verbose # 带生命周期日志的任务测试 |
| 43 | +./coro_multi_thread # 多线程测试 |
| 44 | +./coro_multi_thread_st # 多线程测试(单线程模式) |
| 45 | +``` |
| 46 | + |
| 47 | +**无测试框架** - 测试使用自定义 `ASSERT()` 宏和 `LOG()` 输出。测试通过的标志是退出码为 0。 |
| 48 | + |
| 49 | +## 代码风格 |
| 50 | + |
| 51 | +### 格式化 |
| 52 | + |
| 53 | +- **clang-format**:基于 Google 风格,150 列宽限制 |
| 54 | +- 提交前运行:`clang-format -i <文件>` |
| 55 | +- 短函数/lambda:仅空函数体可单行 |
| 56 | + |
| 57 | +### 命名规范 |
| 58 | + |
| 59 | +- **命名空间**:`coro`,内部实现用 `coro::detail` |
| 60 | +- **类型**:`snake_case`(如 `mutex_t`、`awaitable_promise`、`counting_semaphore_t`) |
| 61 | +- **类型别名**:`snake_case`(如 `using mutex = mutex_t;`) |
| 62 | +- **函数/方法**:`snake_case`(如 `scoped_lock()`、`await_ready()`) |
| 63 | +- **成员变量**:`snake_case_` 带尾部下划线(如 `counter_`、`mutex_`) |
| 64 | +- **模板参数**:`UPPER_CASE`(如 `MUTEX`、`T`) |
| 65 | +- **宏**:`UPPER_CASE` 带前缀(如 `CORO_DEBUG_PROMISE_LEAK`) |
| 66 | + |
| 67 | +### 头文件包含顺序 |
| 68 | + |
| 69 | +1. 配置/调试宏(在库头文件之前) |
| 70 | +2. 标准库头文件(`<coroutine>`、`<atomic>` 等) |
| 71 | +3. 项目头文件(`"coro/coro.hpp"`、`"coro/executor.hpp"`) |
| 72 | + |
| 73 | +### 类型设计模式 |
| 74 | + |
| 75 | +- **模板互斥锁参数**:使用 `typename MUTEX = std::mutex` 控制线程安全 |
| 76 | +- **类型别名**:提供 `_mt`(多线程)和 `_st`(单线程)变体 |
| 77 | +- **可等待类型**:嵌套结构体命名为 `*_awaitable`(如 `lock_awaitable`、`send_awaitable`) |
| 78 | + |
| 79 | +### 协程模式 |
| 80 | + |
| 81 | +- 返回类型:`async<T>`(`awaitable<T>` 的别名) |
| 82 | +- 使用 `co_await`、`co_return` 关键字 |
| 83 | +- 延迟启动:协程在 `initial_suspend()` 处挂起 |
| 84 | +- 执行器继承:子协程继承父协程的执行器 |
| 85 | +- **协程 lambda 禁止捕获引用**:lambda 立即调用后销毁,捕获的引用会悬空,需用参数传递 |
| 86 | + |
| 87 | +```cpp |
| 88 | +async<int> example_coro() { |
| 89 | + co_await sleep(100ms); |
| 90 | + co_return 42; |
| 91 | +} |
| 92 | + |
| 93 | +// 错误:lambda 销毁后捕获的引用悬空 |
| 94 | +spawn(exec, [&counter]() -> async<void> { |
| 95 | + counter++; // 未定义行为 |
| 96 | +}()); |
| 97 | + |
| 98 | +// 正确:通过参数传递 |
| 99 | +spawn(exec, [](int& cnt) -> async<void> { |
| 100 | + cnt++; |
| 101 | +}(counter)); |
| 102 | +``` |
| 103 | +
|
| 104 | +### 错误处理 |
| 105 | +
|
| 106 | +- **启用异常**(默认):在 promise 中使用 `std::exception_ptr` |
| 107 | +- **禁用异常**(`CORO_DISABLE_EXCEPTION`):返回值使用 `std::optional` |
| 108 | +- 两种路径都需要用 `#ifndef CORO_DISABLE_EXCEPTION` 保护 |
| 109 | +
|
| 110 | +### 内存与生命周期 |
| 111 | +
|
| 112 | +- 禁用拷贝,启用移动 |
| 113 | +- 使用 RAII 守卫(如 `lock_guard`)管理资源 |
| 114 | +- 使用侵入式链表管理等待队列(避免堆分配) |
| 115 | +
|
| 116 | +### 测试文件结构 |
| 117 | +
|
| 118 | +```cpp |
| 119 | +#define CORO_DEBUG_PROMISE_LEAK |
| 120 | +#include "log.h" |
| 121 | +#include "TimeCount.hpp" |
| 122 | +#include "assert_def.h" |
| 123 | +#include "coro/coro.hpp" |
| 124 | +#include "utils.hpp" |
| 125 | +
|
| 126 | +using namespace coro; |
| 127 | +
|
| 128 | +async<void> test_feature() { |
| 129 | + ASSERT(condition); |
| 130 | + LOG("Test passed"); |
| 131 | +} |
| 132 | +
|
| 133 | +int main() { |
| 134 | + LOG("Test init"); |
| 135 | + executor_loop executor; |
| 136 | + test_feature().detach_with_callback(executor, [&] { |
| 137 | + executor.stop(); |
| 138 | + }); |
| 139 | + executor.run_loop(); |
| 140 | + check_coro_leak(); // 验证无协程泄漏 |
| 141 | + return 0; |
| 142 | +} |
| 143 | +``` |
| 144 | + |
| 145 | +## 核心 API |
| 146 | + |
| 147 | +| 组件 | 用法 | |
| 148 | +|------------------------------|-----------------------------| |
| 149 | +| `async<T>` | 协程返回类型 | |
| 150 | +| `spawn(executor, coro)` | 启动分离的协程 | |
| 151 | +| `co_await mtx.scoped_lock()` | RAII 互斥锁 | |
| 152 | +| `co_await ch.send(val)` | 通道发送 | |
| 153 | +| `co_await ch.recv()` | 通道接收(返回 `std::optional<T>`) | |
| 154 | +| `co_await sem.acquire()` | 信号量获取 | |
| 155 | +| `sem.release()` | 信号量释放(非阻塞) | |
| 156 | +| `when_all(...)` | 等待所有可等待对象 | |
| 157 | +| `when_any(...)` | 等待任意一个完成 | |
| 158 | + |
| 159 | +## 调试宏 |
| 160 | + |
| 161 | +```cpp |
| 162 | +#define CORO_DEBUG_PROMISE_LEAK // 启用泄漏追踪 |
| 163 | +#define CORO_DEBUG_LEAK_LOG LOG // 泄漏日志函数 |
| 164 | +#define CORO_DEBUG_LIFECYCLE LOG // 协程生命周期日志 |
| 165 | +``` |
| 166 | +
|
| 167 | +测试结束时调用 `check_coro_leak()` 验证无泄漏。 |
| 168 | +
|
| 169 | +## 添加新功能 |
| 170 | +
|
| 171 | +添加新功能时需要同时更新三个文件: |
| 172 | +
|
| 173 | +### 1. CMakeLists.txt |
| 174 | +
|
| 175 | +在 `if (CORO_BUILD_TEST)` 块中添加: |
| 176 | +
|
| 177 | +```cmake |
| 178 | +set(TARGET_NAME ${PROJECT_NAME}_new_feature) |
| 179 | +add_executable(${TARGET_NAME} test/coro_new_feature.cpp) |
| 180 | +``` |
| 181 | + |
| 182 | +### 2. .github/workflows/ci.yml |
| 183 | + |
| 184 | +在测试步骤部分添加: |
| 185 | + |
| 186 | +```yaml |
| 187 | +- name: Test new_feature |
| 188 | + if: always() |
| 189 | + working-directory: build |
| 190 | + run: | |
| 191 | + ./coro_new_feature${{ matrix.env.BIN_SUFFIX }} |
| 192 | +``` |
| 193 | +
|
| 194 | +### 3. 创建测试文件 test/coro_new_feature.cpp |
| 195 | +
|
| 196 | +使用上述"测试文件结构"模板。 |
| 197 | +
|
| 198 | +### 4. 补充文档,更新README.md和README_CN.md,放到同类功能后面 |
| 199 | +
|
| 200 | +## 平台说明 |
| 201 | +
|
| 202 | +- **编译器**:GCC、Clang、MSVC(需 `/Zc:preprocessor`) |
| 203 | +- **Windows**:添加 `-DNOMINMAX` 避免宏冲突 |
| 204 | +- **嵌入式**:定义 `CORO_DISABLE_EXCEPTION` 用于不支持异常的平台 |
0 commit comments