# stagefuture **Repository Path**: DGuco/stagefuture ## Basic Information - **Project Name**: stagefuture - **Description**: 基于c++11的可串行并行的future类 - **Primary Language**: C++ - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-02-26 - **Last Updated**: 2026-07-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # StageFuture 项目 Code Wiki > 仓库路径:`stagefuture` > 作者:DGuco (1139140929@qq.com) > 文档生成日期:2026-07-15 --- ## 目录 1. [项目概述](#1-项目概述) 2. [整体架构](#2-整体架构) 3. [模块职责](#3-模块职责) 4. [文件清单](#4-文件清单) 5. [关键类与函数说明](#5-关键类与函数说明) 6. [核心流程](#6-核心流程) 7. [依赖关系](#7-依赖关系) 8. [并发与同步原语](#8-并发与同步原语) 9. [项目运行方式](#9-项目运行方式) 10. [设计要点与注意事项](#10-设计要点与注意事项) --- ## 1. 项目概述 `stagefuture` 是一个**跨平台、基于任务(Task)抽象的 C++11 线程调度库**。它提供: - **跨平台线程封装**(Windows `CreateThread` / Linux `pthread`)。 - **互斥锁、读写锁、自旋锁**等多种同步原语。 - **任务(Task)抽象**:把可执行单元封装为带状态、可组合的对象,支持返回值模板化。 - **任务调度器(CTaskScheduler)**:单线程驱动的任务队列。 - **线程调度器(CThreadScheduler)**:多线程工作池,基于调度器扩展。 - **任务链式编排(CTaskHelper)**:类似 Future 的 `ThenAccept` / `ThenApply` 与 `AcceptAll` / `AcceptAny` / `ApplyAll` / `ApplyAny` 组合语义。 - **安全指针(CSafePtr)**:带魔数校验的侵入式智能指针。 - **时间工具类(CTimeHelper)**:单例时间管理器,支持线程本地缓存时间。 整体定位是为游戏服务器或高性能网络服务提供统一的异步任务执行与编排能力。 --- ## 2. 整体架构 ``` ┌──────────────────────────────────────────────────────┐ │ 上层业务 (Scene/Server) │ └───────────────────────┬──────────────────────────────┘ │ Schedule / ThenAccept / AcceptAll ... ▼ ┌──────────────────────────────────────────────────────────────────┐ │ core 模块 (任务调度核心) │ │ │ │ ┌───────────────────┐ ┌────────────────────────────┐ │ │ │ CThreadScheduler │ ─────▶ │ CTaskScheduler │ │ │ │ (多线程工作池) │ 继承 │ (单线程任务队列 + 模板API) │ │ │ └─────────┬─────────┘ └──────────┬─────────────────┘ │ │ │ 持有 │ 持有 / 调度 │ │ ▼ ▼ │ │ ┌───────────────────┐ ┌────────────────────────────┐ │ │ │ CTaskThread │ ─────▶ │ CTask (任务基类) │ │ │ │ (CMyThread 子类) │ Run │ ├─ CCombineTask │ │ │ └─────────┬─────────┘ │ ├─ CWithReturnTask<...> │ │ │ │ 继承 │ └─ CNoReturnTask<...> │ │ │ ▼ └──────────┬─────────────────┘ │ │ ┌───────────────────┐ │ 由 TaskHelper 编排 │ │ │ CMyThread │ ▼ │ │ │ (跨平台线程) │ ┌────────────────────────────┐ │ │ └───────────────────┘ │ CTaskHelper │ │ │ │ CAcceptCombineTaskHelper │ │ │ ┌──────────────────────────┐ │ CApplyCombineTaskHelper │ │ │ │ 锁原语 │ └────────────────────────────┘ │ │ │ CMyLock/CSafeLock │ │ │ │ CSpinLock/CSafeSpLock │ │ │ │ CSpinRWLock/... │ │ │ └──────────────────────────┘ │ └──────────────────────────────────────────────────────────────────┘ │ ▼ 依赖 ┌──────────────────────────────────────────────────────┐ │ base 模块 (基础工具) │ │ base.h, log.h, time_helper.h, platform_def.h, │ │ my_assert.h, safe_pointer.h, singleton.h, t_array.h │ └──────────────────────────────────────────────────────┘ ``` **核心设计思路**: - **线程 = 执行载体**:`CMyThread` / `CTaskThread` 只负责跑循环、调用调度器。 - **任务 = 工作单元**:`CTask` 体系把函数+参数+返回值+状态机+子任务链打包。 - **调度器 = 队列 + 线程池**:`CTaskScheduler` 维护一个 `std::queue`;`CThreadScheduler` 持有 N 个 `CTaskThread` 消费同一个队列。 - **链式调用 = Future 风格**:`CTaskHelper` 通过子任务队列实现 `Then*` 与 `Accept/Apply *`。 --- ## 3. 模块职责 ### 3.1 base 模块(基础工具库) | 模块/文件 | 职责 | |-----------|------| | [base.h](file:///e:/workspace/github/stagefuture/base/base.h) | 基础类型定义、常用宏(MIN/MAX/SAFE_DELETE)、原子内存序辅助函数 `load_acquire`/`store_release`。 | | [platform_def.h](file:///e:/workspace/github/stagefuture/base/platform_def.h) / [platform_def.cpp](file:///e:/workspace/github/stagefuture/base/platform_def.cpp) | 跨平台宏定义(`__LINUX__`/`__WINDOWS__`)、socket/线程类型抽象、缓存行对齐宏、`SLEEP` 宏、Windows 错误消息获取函数。 | | [log.h](file:///e:/workspace/github/stagefuture/base/log.h) | 日志系统单例 `CLog`,支持类 Python `{}` 风格格式化输出,分为磁盘日志(DISK_LOG)和缓存日志(CACHE_LOG)。 | | [my_assert.h](file:///e:/workspace/github/stagefuture/base/my_assert.h) | 断言宏 `ASSERT` / `ASSERT_EX`,断言失败时记录日志并抛出 `std::logic_error`。 | | [time_helper.h](file:///e:/workspace/github/stagefuture/base/time_helper.h) / [time_helper.cpp](file:///e:/workspace/github/stagefuture/base/time_helper.cpp) | 时间管理单例 `CTimeHelper`(线程本地缓存时间)、定时器 `CMyTimer`。 | | [safe_pointer.h](file:///e:/workspace/github/stagefuture/base/safe_pointer.h) | 安全智能指针 `CSafePtr`,通过魔数位交错存储检测野指针/坏指针。 | | [singleton.h](file:///e:/workspace/github/stagefuture/base/singleton.h) | 单例模板 `CSingleton`,使用函数局部静态变量(C++11 线程安全)。 | | [t_array.h](file:///e:/workspace/github/stagefuture/base/t_array.h) | 定长数组模板 `TArray`,带边界检查,要求类型为 standard layout。 | ### 3.2 core 模块(任务调度核心) | 模块/文件 | 职责 | |-----------|------| | [my_thread.h](file:///e:/workspace/github/stagefuture/core/my_thread.h) / [my_thread.cpp](file:///e:/workspace/github/stagefuture/core/my_thread.cpp) | 跨平台线程抽象基类 `CMyThread`,封装线程创建、退出、状态机、线程局部数据、init/tick 回调。 | | [my_lock.h](file:///e:/workspace/github/stagefuture/core/my_lock.h) | 互斥锁 `CMyLock`(Linux 原生 `pthread_mutex`,Windows 退化为 `std::mutex`)及其 RAII 包装类。 | | [spin_lock.h](file:///e:/workspace/github/stagefuture/core/spin_lock.h) | 自旋锁 `CSpinLock`、自旋读写锁 `CSpinRWLock` 及 RAII 包装类,基于 `std::atomic` 实现。 | | [task.h](file:///e:/workspace/github/stagefuture/core/task.h) / [task.cpp](file:///e:/workspace/github/stagefuture/core/task.cpp) | 任务体系:`CTask` 基类、`CCombineTask` 组合任务、`CWithReturnTask` / `CNoReturnTask` 模板任务、`TaskCaller` 调用辅助、`IndexSequence` 实现。 | | [task_helper.h](file:///e:/workspace/github/stagefuture/core/task_helper.h) | 任务创建工厂 `TaskCreater` / `CombineTaskCreater`、链式 API `CTaskHelper`、组合 API `CAcceptCombineTaskHelper` / `CApplyCombineTaskHelper`、参数类型信息 `IArgsTypeInfo` / `CArgsTypeList`。 | | [task_scheduler.h](file:///e:/workspace/github/stagefuture/core/task_scheduler.h) / [task_scheduler.cpp](file:///e:/workspace/github/stagefuture/core/task_scheduler.cpp) | 任务调度器 `CTaskScheduler`(队列消费 + 模板调度 API)。 | | [task_thread.h](file:///e:/workspace/github/stagefuture/core/task_thread.h) / [task_thread.cpp](file:///e:/workspace/github/stagefuture/core/task_thread.cpp) | 调度工作线程 `CTaskThread`,`CMyThread` 的子类。 | | [thread_scheduler.h](file:///e:/workspace/github/stagefuture/core/thread_scheduler.h) / [thread_scheduler.cpp](file:///e:/workspace/github/stagefuture/core/thread_scheduler.cpp) | 多线程调度器 `CThreadScheduler`,持有多个 `CTaskThread` 组成工作线程池。 | ### 3.3 test 模块(测试代码) | 文件 | 职责 | |------|------| | [Scene.h](file:///e:/workspace/github/stagefuture/test/Scene.h) | 示例场景类 `Scene`(继承 `CTaskScheduler`)、`Obj_Human` 游戏对象示例。 | | [main.cpp](file:///e:/workspace/github/stagefuture/test/main.cpp) | 测试入口:`schedler_test()` 调度器压力测试、`scene_test()` 场景跨线程任务链测试。 | --- ## 4. 文件清单 ``` stagefuture/ ├── CMakeLists.txt # CMake 构建配置 ├── LICENSE # MIT 许可证 ├── README.md # 旧版说明文档 ├── CodeWiki.md # 本文档 ├── .gitignore ├── .vscode/ # VS Code 配置 │ ├── launch.json │ └── settings.json ├── base/ # 基础工具模块 │ ├── base.h │ ├── log.h │ ├── my_assert.h │ ├── platform_def.h │ ├── platform_def.cpp │ ├── safe_pointer.h │ ├── singleton.h │ ├── t_array.h │ ├── time_helper.h │ └── time_helper.cpp ├── core/ # 任务调度核心模块 │ ├── my_lock.h │ ├── spin_lock.h │ ├── my_thread.h │ ├── my_thread.cpp │ ├── task.h │ ├── task.cpp │ ├── task_helper.h │ ├── task_scheduler.h │ ├── task_scheduler.cpp │ ├── task_thread.h │ ├── task_thread.cpp │ ├── thread_scheduler.h │ └── thread_scheduler.cpp ├── test/ # 测试代码 │ ├── Scene.h │ └── main.cpp ├── build/ # CMake 构建输出目录 └── run/ # 可执行文件输出目录 └── stagefuture_test.exe ``` --- ## 5. 关键类与函数说明 ### 5.1 `CSafePtr`(安全智能指针) 文件:[safe_pointer.h](file:///e:/workspace/github/stagefuture/base/safe_pointer.h#L36-L218) **设计原理**:将指针地址的奇偶位分别交错存储到两个 `SPO_DATA_TYPE`(64位平台为 `unsigned long long`)变量中,并在固定位设置魔数标志位。访问时检查魔数标志是否完整,可检测野指针、越界写入导致的指针损坏。 **关键成员/方法**: | 成员 | 说明 | |------|------| | `CSafePtr()` | 默认构造,初始化为空指针 | | `CSafePtr(Tp* pointer)` | 从原始指针构造,进行位交错编码 | | `Tp* operator->()` / `Tp& operator*()` | 解引用,先校验魔数再返回指针 | | `bool IsPointerBad()` | 检查指针是否损坏(魔数标志不完整) | | `void Reset()` / `void Reset(const Tp* pointer)` | 重置指针 | | `Tp* Get()` | 获取原始指针(带校验) | | `void Free()` | 释放指针指向的对象并重置 | | `template CSafePtr DynamicCastTo()` | 动态类型转换 | **Debug 额外检查**:在 `_DEBUG_` 模式下额外保存一份原始指针 `m_pPointer`,解引用时比对解码出的指针与保存的指针是否一致。 --- ### 5.2 `CSingleton`(单例模板) 文件:[singleton.h](file:///e:/workspace/github/stagefuture/base/singleton.h#L15-L37) 使用 C++11 函数局部静态变量实现线程安全的单例: ```cpp static CSafePtr GetSingletonPtr() { static T instance; return &instance; } ``` > 利用 C++11 标准保证:函数局部静态变量的初始化是线程安全的,只会被一个线程执行一次。 --- ### 5.3 `CLog`(日志系统) 文件:[log.h](file:///e:/workspace/github/stagefuture/base/log.h#L162-L195) 单例日志类,支持类 Python `{}` 风格的格式化输出。 **日志类型**: | 类型 | 枚举值 | 前缀 | |------|--------|------| | ASSERT_DISK | 0 | `[assert]` | | DEBUG_DISK | 1 | `[debug_disk]` | | ERROR_DISK | 2 | `[error_disk]` | | DEBUG_CACHE | 0 | `[debug]` | | ERROR_CACHE | 1 | `[error]` | | THREAD_ERROR | 2 | `[thread_error]` | **格式化实现**:`build_fmt_string` 函数遍历格式串,将每个 `{}` 替换为对应参数的 `%s`(字符串)或 `%ld`(整数/指针),最终通过 `printf` 输出。 **宏定义**: - `DISK_LOG` → `CLog::GetSingletonPtr()->DiskLog` - `CACHE_LOG` → `CLog::GetSingletonPtr()->CacheLog` --- ### 5.4 `CTimeHelper`(时间管理) 文件:[time_helper.h](file:///e:/workspace/github/stagefuture/base/time_helper.h#L18-L54) / [time_helper.cpp](file:///e:/workspace/github/stagefuture/base/time_helper.cpp) 单例时间管理器,使用 `thread_local` 数据 `g_thread_data` 缓存时间,避免频繁系统调用。 **关键成员/方法**: | 方法 | 说明 | |------|------| | `void SetTime()` | 刷新线程本地缓存时间(`system_clock::now()`),worker 线程每轮循环调用 | | `uint64 GetMSTime(bool realTime=false)` | 获取毫秒级时间戳(使用缓存,`realTime=true` 强制刷新) | | `time_t GetMicroTime(bool realTime=false)` | 获取微秒级时间戳 | | `time_t GetANSITime(bool realTime=false)` | 获取 ANSI 时间(`time_t`) | | `int GetYear/GetMonth/GetDay/GetHour/GetMinute/GetSecond()` | 获取缓存时间的各分量 | | `int GetWeek()` | 获取星期几(0=周日) | | `int GetDayOfYear()` | 获取一年中的第几天 | | `unsigned int Time2Day()` | 返回当前日期的整数格式 YYYYMMDD | | `unsigned int Time2DayAfter(unsigned int time2day, int diffDay)` | 计算偏移后的日期 | | `static std::tm LocalTime(std::time_t&)` | 跨平台线程安全的 localtime(Windows `localtime_s` / Linux `localtime_r`) | **`CMyTimer` 定时器**([time_helper.h:57-116](file:///e:/workspace/github/stagefuture/base/time_helper.h#L57-L116)): - `BeginTimer(uNow, vDuration)`:启动定时器 - `IsTimeout(tNow)`:检查是否超时,超时后自动推进到下次触发时间 - `ResetTimeout(tNow)`:重置定时器 - `StopTimer()`:停止定时器 --- ### 5.5 `thread_data`(线程本地数据) 文件:[my_thread.h:23-38](file:///e:/workspace/github/stagefuture/core/my_thread.h#L23-L38) ```cpp struct thread_data { std::tm m_CacheTime; // 缓存的本地时间结构 TimePoint m_CacheTimePoint; // 缓存的时间点 TID m_OwnerThreadID; // 所属线程ID(懒加载) TID getOwnerThreadID() { if(m_OwnerThreadID == 0) m_OwnerThreadID = MyGetCurrentThreadID(); return m_OwnerThreadID; } }; extern thread_local thread_data g_thread_data; ``` 每个线程有独立的 `g_thread_data` 实例,用于缓存时间等线程本地数据。 --- ### 5.6 `CMyThread`(线程基类) 文件:[my_thread.h:58-102](file:///e:/workspace/github/stagefuture/core/my_thread.h#L58-L102) 跨平台线程封装,定义线程生命周期模板方法。 **状态机** `ThreadStatus`: ``` READY → RUNNING → EXITING → EXIT ``` **关键成员/方法**: | 成员 | 说明 | |------|------| | `virtual bool PrepareToRun() = 0` | 纯虚,子类在线程启动后、`Run` 前调用,做初始化 | | `virtual bool PrepareEnd() = 0` | 纯虚,子类在 `Run` 退出后调用,做清理 | | `virtual void Run() = 0` | 纯虚,线程主循环 | | `bool CreateThread()` | 创建底层线程(Linux `pthread_create` / Windows `CreateThread`) | | `void Stop()` | 设置 `m_bStoped = true`,通知线程退出循环 | | `void Join()` | 等待线程结束 | | `void Exit()` | 退出当前线程(Linux `pthread_exit` / Windows `CloseHandle`) | | `void SetThreadInitFunc(ThreadFuncParamWrapper)` | 设置线程启动时的 init 回调 | | `void SetThreadTickFunc(ThreadFuncParamWrapper)` | 设置每轮循环前的 tick 回调 | | `bool IsStoped()` | 检查停止标志 | | `TID getTID()` | 获取线程 ID | **线程入口** `ThreadProc`([my_thread.cpp:93-137](file:///e:/workspace/github/stagefuture/core/my_thread.cpp#L93-L137)): ``` SetThreadData(&g_thread_data) → SetStatus(RUNNING) → PrepareToRun() → Run() → SetStatus(EXITING) → PrepareEnd() → Exit() → SetStatus(EXIT) ``` --- ### 5.7 锁原语 #### `CMyLock` / `CSafeLock`([my_lock.h](file:///e:/workspace/github/stagefuture/core/my_lock.h)) - Linux:原生 `pthread_mutex_t` 封装(`Lock`/`Unlock`) - Windows:直接 `#define CMyLock std::mutex`、`#define CSafeLock std::lock_guard` - `CSafeLock` 是 RAII 自动加解锁 #### `CMyRWLock` / `CSafeRLock` / `CSafeWLock`([my_lock.h:59-124](file:///e:/workspace/github/stagefuture/core/my_lock.h#L59-L124)) - Linux:`pthread_rwlock_t` 读写锁 - Windows:退化为 `std::lock_guard`(不区分读写,无读写分离语义) #### `CSpinLock` / `CSafeSpLock`([spin_lock.h:7-49](file:///e:/workspace/github/stagefuture/core/spin_lock.h#L7-L49)) - 基于 `std::atomic_flag` + `test_and_set(acquire)` / `clear(release)` - `TryLock()` 非阻塞尝试 - `CSafeSpLock` RAII 包装 #### `CSpinRWLock` / `CSafeSpinRLock` / `CSafeSpinWLock`([spin_lock.h:51-145](file:///e:/workspace/github/stagefuture/core/spin_lock.h#L51-L145)) - 单个 `std::atomic state` 位编码: - 最高位(`0x80000000`)= 写标志 - 低 31 位 = 读计数 - `RLock`:CAS 自旋,等待写标志清除后读计数 +1 - `WLock`:先 CAS 置写标志(自旋),再自旋等待所有读者释放 - `CACHE_LINE_ALIGN` 填充避免 false sharing - 注意:`WLock` 等待读者释放为纯自旋,读者长时间持锁会忙等浪费 CPU --- ### 5.8 `CTask` 任务体系 #### 任务状态 `enTaskState`([task.h:26-33](file:///e:/workspace/github/stagefuture/core/task.h#L26-L33)) ``` eTaskInit → eTaskWaitingFoDoing → eTaskDoing → eTaskDone └→ eTaskFailed ``` #### 组合类型 `enCombineType`([task.h:35-40](file:///e:/workspace/github/stagefuture/core/task.h#L35-L40)) - `eCombineNone`:普通任务 - `eCombineAll`:所有父任务完成后触发 - `eCombineAny`:任一父任务完成后触发 #### `CTask` 基类([task.h:129-189](file:///e:/workspace/github/stagefuture/core/task.h#L129-L189)) | 方法 | 说明 | |------|------| | `void Run()` | 核心入口:设置执行状态→记录开始时间→调用 `Execute()`→`OnFinish()`;捕获异常→`OnFailed()` | | `virtual void Execute() = 0` | 子类实现真正逻辑 | | `virtual void ExecuteChildTask(TaskPtr) = 0` | 把父任务结果传给子任务并触发 | | `virtual void ExecuteFromParent(void* pRes, bool success) = 0` | 作为子任务,被父任务回调 | | `virtual void* GetRes() = 0` | 获取返回值地址 | | `void AddChildTask(TaskPtr)` | 加入子任务队列(加锁) | | `void RunChildTask()` | 遍历子任务队列,普通任务调 `ExecuteChildTask`,组合任务调 `CombineTaskDone` | | `void OnFinish()` / `OnFailed()` | 设置终态并触发子任务 | | `enTaskState GetState()` / `SetState()` | 原子读写状态(acquire/release) | | `void SetAcceptCombineInfo(CSafePtr)` | 设置组合任务参数填充信息 | | `void FillCombineTaskArgs(TaskPtr)` | 将本任务返回值填充到组合子任务的参数元组对应位置 | **`Run()` 执行逻辑**([task.cpp:54-68](file:///e:/workspace/github/stagefuture/core/task.cpp#L54-L68)): ```cpp void CTask::Run() { try { SetState(eTaskDoing); SetStartTime(CTimeHelper::GetSingletonPtr()->GetMSTime()); Execute(); // 在当前线程同步执行 OnFinish(); } catch (std::exception& e) { CACHE_LOG(THREAD_ERROR, "..."); OnFailed(); } } ``` > **注意**:当前版本任务直接在调用 `Run()` 的线程执行,不自动跨线程投递。任务通过 `PushTask` 入队后由 worker 线程消费时才在 worker 线程执行。 #### `CCombineTask`([task.h:191-293](file:///e:/workspace/github/stagefuture/core/task.h#L191-L293)) - 模板参数 `combine_count` = 父任务数量 - `CombineTaskDone(pParentTask)`:父任务完成回调,用 `std::atomic_int m_combineDone.fetch_add(1, acq_rel)` 计数: - `eCombineAll`:计数 == `combine_count` 时 `m_pScheduler->PushTask(GetShared())` 入队执行 - `eCombineAny`:计数 == 1 时通过 `pParentTask->ExecuteChildTask(this)` 立即触发 - 任一父任务失败则整个组合任务失败 #### `CWithReturnTask` / `CNoReturnTask` 特化 按返回值类型与参数个数特化的任务模板: | 特化 | 参数 | 说明 | |------|------|------| | `CWithReturnTask` | 多参数 | 用 `std::tuple` 存参,`TaskCaller` 展开;不支持 `ExecuteFromParent`(直接 ASSERT) | | `CWithReturnTask` | 单参数 | 直接存 `Par m_Param`,可从父任务结果填充后入队执行 | | `CWithReturnTask` | 无参数 | 无参数,父任务成功后直接入队执行 | | `CNoReturnTask<...>` | 同上三种 | `return_type = void` 版本 | #### `TaskCaller` 调用辅助([task.h:71-113](file:///e:/workspace/github/stagefuture/core/task.h#L71-L113)) - 自实现 `IndexSequence` / `MakeIndexSequence`(C++11 兼容,不依赖 C++14 `std::index_sequence`) - `invoke(func, tuple)` 通过 index 展开元组调用 `func` - 对 `arity=0`、`arity=1` 做特化优化 #### `are_all_same` 类型萃取([task.h:43-51](file:///e:/workspace/github/stagefuture/core/task.h#L43-L51)) 递归模板判断所有类型参数是否相同,用于 `AcceptAny` 静态断言检查。 --- ### 5.9 `CTaskHelper` 与组合 API 文件:[task_helper.h](file:///e:/workspace/github/stagefuture/core/task_helper.h) #### `CTaskHelper`([task_helper.h:83-126](file:///e:/workspace/github/stagefuture/core/task_helper.h#L83-L126)) Future 风格的链式句柄,持有 `TaskPtr`。 | 方法 | 说明 | |------|------| | `ThenAccept(scheduler, func)` | `Res != void` 版:注册接收父任务返回值(`Res`)的回调,返回新的 `CTaskHelper` | | `TaskPtr GetTask()` | 取底层 `TaskPtr` | #### `CTaskHelper` 特化([task_helper.h:128-160](file:///e:/workspace/github/stagefuture/core/task_helper.h#L128-L160)) | 方法 | 说明 | |------|------| | `ThenApply(scheduler, func)` | 父任务无返回值,注册续作回调,返回新的 `CTaskHelper` | **关键容错**:添加子任务后,若父任务已完成/失败,会再次调用 `RunChildTask()` 防止子任务丢失。 #### `CAcceptCombineTaskHelper`([task_helper.h:183-255](file:///e:/workspace/github/stagefuture/core/task_helper.h#L183-L255)) 收集多个 `TaskHelper`,提供: - `AcceptAll(scheduler, func)`:所有父任务完成,把各返回值作为参数传入 `func` - `AcceptAny(scheduler, func)`:任一父任务完成,`func` 接收其返回值(要求所有父任务返回类型相同,`static_assert are_all_same`) #### `CApplyCombineTaskHelper`([task_helper.h:257-301](file:///e:/workspace/github/stagefuture/core/task_helper.h#L257-L301)) - `ApplyAll(scheduler, func)` / `ApplyAny(scheduler, func)`:与 Accept 系列类似,但 `func` 不接收父任务返回值(`void` 参数) #### `IArgsTypeInfo` / `CArgsTypeList`([task_helper.h:303-373](file:///e:/workspace/github/stagefuture/core/task_helper.h#L303-L373)) - `IArgsTypeInfo`:多态基类,定义 `FillWaitTaskParm` 接口 - `CArgsTypeList`:实现类,在运行时把第 N 个父任务返回值填入子任务的参数元组 `std::tuple` 的第 N 位 - 这是实现 `AcceptAll`(多父任务返回值组装)的类型擦除桥梁 > **已知问题**:`CArgsTypeList` 特化([task_helper.h:360-373](file:///e:/workspace/github/stagefuture/core/task_helper.h#L360-L373))没有继承 `IArgsTypeInfo`,这会导致当子任务返回值为 void 时类型不匹配。 #### 工厂 `TaskCreater` / `CombineTaskCreater`([task_helper.h:15-81](file:///e:/workspace/github/stagefuture/core/task_helper.h#L15-L81)) 根据 `return_type` 是否为 `void` 选择 `CWithReturnTask` 或 `CNoReturnTask`。 --- ### 5.10 `CTaskScheduler`(任务调度器) 文件:[task_scheduler.h](file:///e:/workspace/github/stagefuture/core/task_scheduler.h) / [task_scheduler.cpp](file:///e:/workspace/github/stagefuture/core/task_scheduler.cpp) 任务调度器,**单线程语义**的任务队列 + 模板调度入口。 | 方法 | 说明 | |------|------| | `CTaskScheduler(signature)` | 构造,初始化 debug timer(`THREAD_TASK_DEBUG_TIME = 20s`) | | `void ScheduleTask(TaskPtr)` | 校验状态为 `eTaskInit`,置 `eTaskWaitingFoDoing`,加锁入队 | | `void PushTask(TaskPtr)` | 加锁入队(供跨线程投递) | | `void ConsumeTask()` | 循环取出并 `pTask->Run()`,直至队列空;每轮调 `DebugTask()` | | `void DebugTask()` | 每 20 秒打印一次队列长度(CACHE_LOG) | | `template Schedule(signature, f)` | 便捷模板:创建无参任务并调度,返回 `CTaskHelper` | | `static Schedule(pScheduler, signature, f)` | 静态版本 | | `static ApplyCombine(args...)` | 构造 `CApplyCombineTaskHelper` | | `static AcceptAllCombine(tasks...)` / `AcceptAnyCombine(tasks...)` | 构造 `CAcceptCombineTaskHelper`,并通过 `CombineArgs<0, RT...>` 给每个父任务设置 `CArgsTypeList` 参数类型信息 | | `void StopScheduler()` | 声明但未实现 | | `void Join()` | 声明但未实现(由子类 `CThreadScheduler` 实现) | 私有模板 `CombineArgs`([task_scheduler.h:112-130](file:///e:/workspace/github/stagefuture/core/task_scheduler.h#L112-L130)):递归可变参数展开,为第 N 个父任务 `new CArgsTypeList` 并 `SetAcceptCombineInfo`。 **保护成员**: - `std::queue m_Tasks`:任务队列 - `CMyLock m_queue_mutex`:队列互斥锁 - `std::string m_Signature`:调度器名称 - `CMyTimer debug_timer`:调试打印定时器 - `bool stop`:停止标志 --- ### 5.11 `CTaskThread`(调度工作线程) 文件:[task_thread.h](file:///e:/workspace/github/stagefuture/core/task_thread.h) / [task_thread.cpp](file:///e:/workspace/github/stagefuture/core/task_thread.cpp) `CMyThread` 子类,调度器的工作线程。 ```cpp bool PrepareToRun() { m_funcInit(); // 用户 init 回调 return true; } void Run() { while (!IsStoped()) { CTimeHelper::GetSingletonPtr()->SetTime(); // 刷新缓存时间 m_funcTick(); // 用户 tick 回调 m_pScheduler->ConsumeTask(); // 消费队列 SLEEP(1); // 让出 CPU(1毫秒) } } ``` --- ### 5.12 `CThreadScheduler`(多线程调度器/线程池) 文件:[thread_scheduler.h](file:///e:/workspace/github/stagefuture/core/thread_scheduler.h) / [thread_scheduler.cpp](file:///e:/workspace/github/stagefuture/core/thread_scheduler.cpp) `CTaskScheduler` 的多线程扩展:**线程池 + 共享队列**。 | 方法 | 说明 | |------|------| | `Init(threads, initFunc, tickFunc, initFuncArgs, tickFuncArgs)` | 创建 `threads` 个 `CTaskThread`,分别设置 init/tick 回调与参数,`CreateThread` 启动,存入 `m_Workers` | | `void StopScheduler()` | 对所有 worker 调 `Stop()` | | `void Join()` | 对所有 worker 调 `Join()` | | `int ThreadCount()` | 返回 worker 数量 | | 析构 | 逐个 `Stop` + `Join` + `Free` | > 注意:所有 worker 共享同一个 `CTaskScheduler` 队列与 `m_queue_mutex`,因此**多个 worker 之间是竞争消费**同一队列,任务由加锁互斥取出。 --- ## 6. 核心流程 ### 6.1 线程启动与运行循环 ``` CreateThread └─ ThreadProc ├─ SetThreadData(CSafePtr(&g_thread_data)) // 绑定 thread_local ├─ SetStatus(RUNNING) ├─ PrepareToRun() // CTaskThread: 调 init 回调 ├─ Run() // 主循环: SetTime → tick → ConsumeTask → SLEEP(1) ├─ SetStatus(EXITING) ├─ PrepareEnd() ├─ Exit() └─ SetStatus(EXIT) ``` ### 6.2 任务调度流程 ``` 用户调用 CTaskScheduler::Schedule(sig, []{...}) ├─ TaskCreater::CreateTask → TaskPtr (eTaskInit) ├─ ScheduleTask → 状态置 eTaskWaitingFoDoing → PushTask 入队 └─ 返回 CTaskHelper worker 线程 ConsumeTask └─ 加锁从 m_Tasks 取队首任务 → 解锁 └─ pTask->Run() ├─ SetState(eTaskDoing) ├─ SetStartTime(now) ├─ Execute() // 真正执行(在当前 worker 线程) └─ OnFinish() // 置 eTaskDone → RunChildTask ``` ### 6.3 链式任务 `ThenAccept` ``` taskA.ThenAccept(schedulerB, [](A_Res){ return B_Res; }) ├─ 创建 CWithReturnTask<0, Func, A_Res> 作为子任务 B(归属 schedulerB) ├─ taskA.AddChildTask(B) ├─ 若 taskA 已 Done/Failed → 立即 RunChildTask (防丢失) └─ 返回 CTaskHelper(B) taskA 完成后 OnFinish → RunChildTask └─ 对子任务 B 调 ExecuteChildTask(B) └─ B.ExecuteFromParent(&taskA.m_Res) ├─ B.m_Param = *(A_Res*)pRes └─ schedulerB->PushTask(B) // B 入队到 schedulerB,由 schedulerB 的 worker 执行 ``` ### 6.4 组合任务 `AcceptAll` ``` CTaskScheduler::AcceptAllCombine(taskA, taskB, taskC) ├─ CombineArgs<0, RA,RB,RC>(taskA,taskB,taskC) │ ├─ taskA.SetAcceptCombineInfo(new CArgsTypeList<0,RA,RB,RC>) │ ├─ taskB.SetAcceptCombineInfo(new CArgsTypeList<1,RA,RB,RC>) │ └─ taskC.SetAcceptCombineInfo(new CArgsTypeList<2,RA,RB,RC>) └─ 返回 CAcceptCombineTaskHelper .AcceptAll(scheduler, [](RA,RB,RC){...}) ├─ 创建 CCombineTask<3> 子任务 combineTask (eCombineAll,归属 scheduler) ├─ taskA/B/C 各自 AddChildTask(combineTask) └─ 返回 CTaskHelper(combineTask) 每个父任务完成 → RunChildTask → combineTask.CombineTaskDone(parent) ├─ parent.FillCombineTaskArgs(combineTask) │ └─ CArgsTypeList.FillWaitTaskParm: 写入 combineTask 参数元组第 N 位 ├─ m_combineDone.fetch_add(1) └─ if newValue == 3 → scheduler->PushTask(combineTask) // 入队执行 ``` ### 6.5 Scene 跨线程任务链测试 测试代码 [main.cpp:198-305](file:///e:/workspace/github/stagefuture/test/main.cpp#L198-L305) 演示了典型用法: 1. 创建多个 Scene(继承 CTaskScheduler)和对应的工作线程 2. 工作线程 tick 回调中调用 `Scene::Tick()` → `ConsumeTask()` 3. 任务链跨多个 Scene 依次传递:`Scene0` 执行 → 结果传给 `Scene1` → ... → `Scene9` 最终停止所有调度器 --- ## 7. 依赖关系 ### 7.1 模块内依赖(include 关系图) ``` thread_scheduler.h ──> task_scheduler.h ──> task.h ──> my_thread.h ──> my_lock.h │ │ └──> task_helper.h ───┘ │ spin_lock.h my_thread.h ──> base.h ├──> time_helper.h └──> safe_pointer.h base 模块内部依赖: log.h ──> singleton.h ──> safe_pointer.h ──> base.h ──> platform_def.h my_assert.h ──> base.h, log.h time_helper.h ──> base.h, singleton.h t_array.h ──> my_assert.h ``` ### 7.2 头文件依赖矩阵 | 文件 | 依赖的 base 头文件 | 依赖的 core 头文件 | 依赖的标准库 | |------|-------------------|-------------------|-------------| | safe_pointer.h | base.h | - | stdexcept, stdio.h | | singleton.h | safe_pointer.h | - | - | | log.h | singleton.h | - | string, type_traits | | my_assert.h | base.h, log.h | - | - | | time_helper.h | base.h, singleton.h | (cpp 引用 my_thread.h 仅 for g_thread_data) | chrono, ctime, ratio, map | | t_array.h | my_assert.h | - | string, type_traits, cstring | | my_lock.h | base.h | - | mutex | | spin_lock.h | base.h | - | atomic | | my_thread.h | base.h, my_lock.h, time_helper.h, safe_pointer.h | - | mutex, atomic, functional, memory | | task.h | base.h, log.h, t_array.h | my_thread.h | functional, type_traits, string, tuple, memory, atomic, queue | | task_helper.h | my_assert.h, safe_pointer.h | task.h | - | | task_scheduler.h | safe_pointer.h, time_helper.h, my_lock.h | task.h, task_helper.h | queue, thread, functional, list | | task_thread.h | - | my_thread.h, task_scheduler.h | - | | thread_scheduler.h | safe_pointer.h, time_helper.h, my_lock.h, my_thread.h | task.h, task_helper.h, task_scheduler.h | queue, thread, functional, list | ### 7.3 标准库依赖 ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, `` Linux 额外:``、各种 POSIX sys/socket 头文件 Windows 额外:``, ``, ``, `` --- ## 8. 并发与同步原语 | 原语 | 实现 | 适用场景 | |------|------|----------| | `CMyLock` | Linux `pthread_mutex` / Win `std::mutex` | 一般互斥,如 `CTaskScheduler::m_queue_mutex`、`CTask::m_childTaskLock` | | `CSafeLock` | RAII 包装 `CMyLock` | 作用域自动解锁 | | `CMyRWLock` | Linux `pthread_rwlock` / Win 退化 | 读多写少(Windows 下无读写分离) | | `CSafeRLock` / `CSafeWLock` | RAII 包装 | 读写作用域 | | `CSpinLock` | `std::atomic_flag` | 临界区极短、不可睡眠场景 | | `CSafeSpLock` | RAII 包装 | 自旋作用域 | | `CSpinRWLock` | `std::atomic` 位编码 | 高并发读、短写场景 | | `std::atomic` | acquire/release | `CTask::m_nState` 跨线程状态可见性 | | `std::atomic_int` | `acq_rel` | `CCombineTask::m_combineDone` 组合计数 | | `std::atomic_bool` | - | `CMyThread::m_bStoped` 停止标志 | **内存序约定**: - `release` store:保证此前的读写对其他线程可见 - `acquire` load:保证此后的读写看到最新数据 - `acq_rel`(fetch_add):同时具有 acquire 和 release 语义 --- ## 9. 项目运行方式 ### 9.1 环境要求 - **编译器**:支持 C++11(GCC 4.8+ / MSVC 2015+ / VS2019) - **构建系统**:CMake 3.6+ - **平台**:Windows(当前主要支持)/ Linux ### 9.2 构建步骤 使用 CMake 构建: ```bash # 在项目根目录创建 build 目录 mkdir build cd build # 生成构建文件 cmake .. # 编译(Windows 可打开 stagefuture.sln 用 Visual Studio 编译) cmake --build . --config Debug # 或在 VS 开发者命令行中直接编译 Release 版本 cmake --build . --config Release ``` **MSVC 编译选项**(来自 [CMakeLists.txt](file:///e:/workspace/github/stagefuture/CMakeLists.txt)): - 定义 `__WINDOWS__` 和 `_DEBUG_` 宏 - Debug:`/MTd`(静态链接 CRT 调试版) - Release:`/MT`(静态链接 CRT 发布版) - 链接 `psapi` 库 **GCC/Clang 编译选项**(Linux): - `-std=c++11 -O2 -fPIC -Wall -pipe -rdynamic -fno-omit-frame-pointer -ldl` - 定义 `__LINUX__`(需在编译时手动 `-D__LINUX__`,CMakeLists.txt 中默认未启用) **输出目录**:可执行文件输出到 `${CMAKE_SOURCE_DIR}/run/` 目录。 ### 9.3 运行 构建成功后,在 `run/` 目录下生成 `stagefuture_test.exe`(Windows),直接运行即可: ```bash cd run ./stagefuture_test.exe ``` 默认执行 `scene_test()`,演示跨 Scene 的链式任务传递。若要执行调度器压力测试 `schedler_test()`,需修改 [main.cpp:309-310](file:///e:/workspace/github/stagefuture/test/main.cpp#L309-L310) 取消注释。 ### 9.4 使用示例 #### 多线程工作池基本用法 ```cpp #include "thread_scheduler.h" // 创建线程池(4个worker线程) CSafePtr pool = new CThreadScheduler("worker-pool"); pool->Init(4, nullptr, nullptr, nullptr, nullptr); // 提交无参任务,返回 TaskHelper auto t1 = CTaskScheduler::Schedule(pool, "task1", []{ return 1; }); // 链式:t1 完成后在 pool 上执行 t2 auto t2 = t1.ThenAccept(pool, [](int value){ return value + 1; }); // 停止并等待 pool->StopScheduler(); pool->Join(); ``` #### 组合任务:AcceptAll(等待所有任务完成) ```cpp auto a = pool->Schedule("a", []{ return 1; }); auto b = pool->Schedule("b", []{ return 2; }); auto c = pool->Schedule("c", []{ return 3; }); CTaskScheduler::AcceptAllCombine(a, b, c) .AcceptAll(pool, [](int ra, int rb, int rc){ // 所有任务完成后执行,ra=1, rb=2, rc=3 int sum = ra + rb + rc; }); ``` #### 组合任务:AcceptAny(任一任务完成即触发) ```cpp CTaskScheduler::AcceptAnyCombine(a, b, c) .AcceptAny(pool, [](int r){ // 任一任务完成即执行,r 为最先完成任务的返回值 }); ``` #### 继承 CTaskScheduler 实现自定义调度器(如 Scene) ```cpp class Scene : public CTaskScheduler { public: Scene() : CTaskScheduler("Scene") {} void Tick() { ConsumeTask(); } // ... }; // 使用 CThreadScheduler 驱动 Scene 的 tick CSafePtr driver = new CThreadScheduler("driver"); Scene* scene = new Scene(); driver->Init(1, nullptr, [](void* arg){ ((Scene*)arg)->Tick(); }, nullptr, (void**)&scene); ``` ### 9.5 运行时注意事项 - `CTaskScheduler::DebugTask()` 每 20 秒打印一次队列长度。 - Worker 每轮 `SLEEP(1)` 毫秒让出 CPU,**非高吞吐设计**。 - `CTask` 析构时若已 Done/Failed 会再次 `RunChildTask()`,确保子任务被触发。 - `g_thread_data` 是 `thread_local`,每个线程需调用 `SetTime()` 刷新缓存时间。 - `CSafePtr` 在 Debug 模式下有额外指针校验,Release 模式仅检查魔数标志。 --- ## 10. 设计要点与注意事项 ### 10.1 设计亮点 1. **跨平台抽象**:`#if defined(__LINUX__)` 分支覆盖 `pthread`/Win32,业务代码无感。 2. **Future 风格链式 API**:`ThenAccept` / `ThenApply` / `AcceptAll` / `AcceptAny` / `ApplyAll` / `ApplyAny`,语义接近 `std::future` / Java `CompletableFuture`。 3. **类型擦除的组合参数填充**:`IArgsTypeInfo` + 模板 `CArgsTypeList` 实现多父任务返回值按位置注入子任务元组。 4. **自实现 `IndexSequence`**:兼容 C++11 旧编译器,不依赖 C++14 `std::index_sequence`。 5. **自旋读写锁位编码**:单原子变量同时管理读计数与写标志,`CACHE_LINE_ALIGN` 防 false sharing。 6. **CSafePtr 魔数位交错**:创新的指针损坏检测机制,通过奇偶位分离存储和魔数标志位检测野指针/越界写。 7. **线程本地时间缓存**:`CTimeHelper` 通过 `thread_local` 缓存时间,避免高频系统调用。 8. **单例的线程安全实现**:利用 C++11 函数局部静态变量初始化的线程安全保证。 9. **类 Python 格式化日志**:`CLog` 支持 `{}` 占位符,自动推导 `%s`/`%ld`。 ### 10.2 已知问题与潜在坑点 1. **[task_scheduler.h:108-110](file:///e:/workspace/github/stagefuture/core/task_scheduler.h#L108-L110)**:`CTaskScheduler` 声明了 `StopScheduler()` 和 `Join()` 但未实现,仅在子类 `CThreadScheduler` 中实现。基类指针调用这两个方法会链接错误。 2. **[task_helper.h:360-373](file:///e:/workspace/github/stagefuture/core/task_helper.h#L360-L373)**:`CArgsTypeList` 特化没有继承 `IArgsTypeInfo`,也没有 `override` 关键字,这是一个 bug——当组合任务的某个返回类型为 void 时,`SetAcceptCombineInfo` 传入的指针类型不匹配。 3. **[task.h:352-356](file:///e:/workspace/github/stagefuture/core/task.h#L352-L356)**:多参版 `CWithReturnTask::ExecuteFromParent` 直接 `ASSERT_EX(false)`,即**多参任务不能作为组合子任务**接收父返回值;只有单参/无参特化可参与 `AcceptAll`/`AcceptAny` 链式组合。 4. **[task.cpp:12-33](file:///e:/workspace/github/stagefuture/core/task.cpp#L12-L33)**:`CTask` 析构调用 `RunChildTask()`,若子任务在此刻又被其他路径触发,需注意重复执行风险(依赖子任务自身幂等性)。 5. **[task_thread.cpp:32](file:///e:/workspace/github/stagefuture/core/task_thread.cpp#L32)**:`CTaskThread::Run` 每轮 `SLEEP(1)` 固定睡眠 1 毫秒,延迟敏感场景需调整或改为条件变量唤醒(会引入约 1ms 的任务调度延迟)。 6. **[my_lock.h:126-130](file:///e:/workspace/github/stagefuture/core/my_lock.h#L126-L130)**:Windows 下 `CMyRWLock` 退化为普通互斥,**无读写分离语义**;Windows 高并发读场景应改用 SRWLock。 7. **[spin_lock.h:92](file:///e:/workspace/github/stagefuture/core/spin_lock.h#L92)**:`CSpinRWLock::WLock` 等待读者释放为纯自旋,读者长时间持锁会**忙等浪费 CPU**。 8. **[my_thread.cpp:33](file:///e:/workspace/github/stagefuture/core/my_thread.cpp#L33)**:`Exit()` 方法中 `catch (std::exception e)` 是值捕获,会切片异常对象,建议改为 `const std::exception&`。 9. **[time_helper.cpp:2](file:///e:/workspace/github/stagefuture/base/time_helper.cpp#L2)**:`time_helper.cpp` 直接 include 了 `core/my_thread.h`,这造成 base 模块反向依赖 core 模块(为了访问 `g_thread_data`),破坏了模块层次结构。 10. **任务返回值通过 `void* GetRes()` 传递**:类型安全依赖调用方正确推导,误用易崩溃。 11. **`CArgsTypeList` 在 `CombineArgs` 中 `new` 出来**:依赖 `CSafePtr` 托管释放(`m_pArgsTypeList.Free()`),需确认无泄漏路径。 12. **[safe_pointer.h:158-169](file:///e:/workspace/github/stagefuture/base/safe_pointer.h#L158-L169)**:`StaticCastTo` 方法返回值类型错误(`return CSafePtr(static_cast(pPointer))` 中 `static_cast` 应是 `static_cast`),且函数返回类型为 `void`,应为 `CSafePtr`。 ### 10.3 扩展建议 - 用 `std::condition_variable` 替换 `SLEEP(1)` 轮询,降低空转延迟与 CPU 占用,实现任务到来时即时唤醒。 - Windows 读写锁改用 `SRWLOCK`(`AcquireSRWLockExclusive/Shared`),获得真正的读写分离性能。 - `catch` 改为引用捕获(`const std::exception&`),保留异常类型信息。 - 实现多参任务的 `ExecuteFromParent`,支持多参任务参与 `AcceptAll` 组合。 - 给 `CTask` 增加取消(cancel)与超时语义。 - 修复 `CTaskScheduler::StopScheduler()/Join()` 的缺失实现,使用纯虚函数或提供默认实现。 - 修复 `CArgsTypeList` 继承问题,确保类型一致性。 - 修复 `safe_pointer.h` 中 `StaticCastTo` 的返回类型 bug。 - 将 `g_thread_data` 或其时间缓存部分移到 base 模块,消除 time_helper 对 core 的反向依赖。 --- ## 附录:关键宏与类型速查 | 宏/类型 | 来源 | 含义 | |---------|------|------| | `__LINUX__` / `__WINDOWS__` | platform_def.h / CMakeLists.txt | 平台编译宏(Windows 默认定义,Linux 需手动加) | | `TID` | platform_def.h | 线程 ID 类型(Linux `pthread_t` / Win `DWORD`) | | `CACHE_LINE_SIZE` | platform_def.h | 缓存行大小 = 64 字节 | | `CACHE_LINE_ALIGN` | platform_def.h | 缓存行对齐(防 false sharing) | | `SLEEP(ms)` | platform_def.h | 跨平台睡眠(Linux `sleep` 秒级/Win `Sleep` 毫秒级,注意精度差异) | | `SAFE_DELETE(ptr)` | base.h | 安全 delete 并置 NULL | | `SAFE_DELETE_ARR(ptr)` | base.h | 安全 delete[] 并置 NULL | | `MIN(a,b)` / `MAX(a,b)` | base.h | 最小/最大值宏 | | `CSafePtr` | safe_pointer.h | 安全智能指针(魔数校验) | | `CSingleton` | singleton.h | 单例模板 | | `TaskPtr` | task.h | `std::shared_ptr` | | `WeakTaskPtr` | task.h | `std::weak_ptr` | | `ThreadFuncParam` | my_thread.h | `std::function` | | `ThreadFuncParamWrapper` | my_thread.h | 函数+参数包装,可直接调用 | | `DISK_LOG` / `CACHE_LOG` | log.h | 日志宏 | | `ASSERT` / `ASSERT_EX` | my_assert.h | 断言宏(失败抛异常) | | `THREAD_TASK_DEBUG_TIME` | task_scheduler.h | 调试打印间隔 = 20000ms (20s) | | `TimePoint` | time_helper.h | `std::chrono::time_point` | --- *本文档基于 `stagefuture` 仓库源码生成,涵盖 2 个模块共 22 个文件(base: 10个文件,core: 12个文件,test: 2个文件),约 2500 行 C++ 代码。*