diff --git a/docs/api/XCEngine/Threading/LambdaTask/Constructor.md b/docs/api/XCEngine/Threading/LambdaTask/Constructor.md index 2ebf3668..8d232b20 100644 --- a/docs/api/XCEngine/Threading/LambdaTask/Constructor.md +++ b/docs/api/XCEngine/Threading/LambdaTask/Constructor.md @@ -1,30 +1,28 @@ -# LambdaTask::LambdaTask() +# LambdaTask::Constructor -构造对象。 +构造一个 lambda 任务。 ```cpp -explicit LambdaTask(Func&& func, TaskPriority priority = TaskPriority::Normal) : ITask(priority), m_func(std::move(func)); +explicit LambdaTask(Func&& func, TaskPriority priority = TaskPriority::Normal); ``` -该方法声明于 `XCEngine/Threading/LambdaTask.h`,当前页面用于固定 `LambdaTask` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `func` - 参数语义详见头文件声明。 -- `priority` - 参数语义详见头文件声明。 +当前构造函数会: -**返回:** `void` - 无返回值。 +- 通过 `ITask(priority)` 初始化基类优先级 +- 用 `std::move(func)` 初始化成员 `m_func` -**示例:** +## 参数 -```cpp -#include +- `func` - 要保存的可调用对象。 +- `priority` - 任务优先级;默认值为 `TaskPriority::Normal`。 -void Example() { - XCEngine::Threading::LambdaTask object; -} -``` +## 返回值 + +- 无。 ## 相关文档 -- [返回类总览](LambdaTask.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](LambdaTask.md) +- [Execute](Execute.md) diff --git a/docs/api/XCEngine/Threading/LambdaTask/Execute.md b/docs/api/XCEngine/Threading/LambdaTask/Execute.md index b84ed064..6aef9b3b 100644 --- a/docs/api/XCEngine/Threading/LambdaTask/Execute.md +++ b/docs/api/XCEngine/Threading/LambdaTask/Execute.md @@ -1,30 +1,24 @@ # LambdaTask::Execute -公开方法,详见头文件声明。 +执行保存的可调用对象。 ```cpp void Execute() override; ``` -该方法声明于 `XCEngine/Threading/LambdaTask.h`,当前页面用于固定 `LambdaTask` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 - -**返回:** `void` - 无返回值。 - -**示例:** +当前实现只有一行: ```cpp -#include - -void Example() { - XCEngine::Threading::LambdaTask object; - // 根据上下文补齐参数后调用 LambdaTask::Execute(...)。 - (void)object; -} +m_func(); ``` +## 返回值 + +- 无。 + ## 相关文档 -- [返回类总览](LambdaTask.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](LambdaTask.md) +- [ITask::Execute](../Task/Execute.md) diff --git a/docs/api/XCEngine/Threading/LambdaTask/LambdaTask.md b/docs/api/XCEngine/Threading/LambdaTask/LambdaTask.md index 86e8d028..ec1ab2a5 100644 --- a/docs/api/XCEngine/Threading/LambdaTask/LambdaTask.md +++ b/docs/api/XCEngine/Threading/LambdaTask/LambdaTask.md @@ -2,30 +2,32 @@ **命名空间**: `XCEngine::Threading` -**类型**: `class` +**类型**: `class template` **头文件**: `XCEngine/Threading/LambdaTask.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `LambdaTask` public API。 +**描述**: 把任意可调用对象包装成 `ITask` 的模板适配器。 ## 概述 -`LambdaTask.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`LambdaTask` 是最轻量的任务实现之一:它不额外引入调度语义,只负责保存一个可调用对象,并在 [Execute](Execute.md) 中直接执行它。 -## 声明概览 +这类模板任务在商业引擎里很常见,因为上层常常想直接把一段 lambda 提交给任务系统,而不是每次都手写一个派生类。 -| 声明 | 类型 | 说明 | -|------|------|------| -| `LambdaTask` | `class` | 继承自 `ITask` 的公开声明。 | +## 当前实现边界 -## 公共方法 +- 可调用对象按值保存在 `m_func` 中。 +- [Execute](Execute.md) 不做异常处理;异常会交给调用它的调度器决定怎么处理。 +- 当前模板没有覆盖 `OnComplete()` / `OnCancel()`,因此沿用 `ITask` 基类默认空实现。 -| 方法 | 描述 | +## 公开方法 + +| 方法 | 说明 | |------|------| -| [LambdaTask()](Constructor.md) | 构造对象。 | -| [Execute](Execute.md) | 公开方法,详见头文件声明。 | +| [Constructor](Constructor.md) | 构造 lambda 任务。 | +| [Execute](Execute.md) | 执行保存的可调用对象。 | ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [ITask](../Task/Task.md) diff --git a/docs/api/XCEngine/Threading/Mutex/Constructor.md b/docs/api/XCEngine/Threading/Mutex/Constructor.md index 0847bca8..8b897ede 100644 --- a/docs/api/XCEngine/Threading/Mutex/Constructor.md +++ b/docs/api/XCEngine/Threading/Mutex/Constructor.md @@ -1,28 +1,19 @@ -# Mutex::Mutex() +# Mutex::Constructor -构造对象。 +默认构造一个互斥锁。 ```cpp Mutex() = default; ``` -该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前构造函数是编译器生成的默认实现,唯一实质状态是内部的 `std::mutex`。 -**返回:** `void` - 无返回值。 +## 返回值 -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::Mutex object; -} -``` +- 无。 ## 相关文档 -- [返回类总览](Mutex.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Mutex.md) diff --git a/docs/api/XCEngine/Threading/Mutex/Destructor.md b/docs/api/XCEngine/Threading/Mutex/Destructor.md index 602e0147..739c1244 100644 --- a/docs/api/XCEngine/Threading/Mutex/Destructor.md +++ b/docs/api/XCEngine/Threading/Mutex/Destructor.md @@ -1,29 +1,23 @@ -# Mutex::~Mutex() +# Mutex::Destructor -销毁对象并释放相关资源。 +销毁互斥锁对象。 ```cpp ~Mutex() = default; ``` -该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前析构函数是默认实现,析构行为由内部 `std::mutex` 决定。 -**返回:** `void` - 无返回值。 +## 返回值 -**示例:** +- 无。 -```cpp -#include +## 注意事项 -void Example() { - XCEngine::Threading::Mutex object; - // 对象离开作用域时会自动触发析构。 -} -``` +- 和标准库一样,销毁一个仍在被使用的互斥锁属于未定义行为。 ## 相关文档 -- [返回类总览](Mutex.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Mutex.md) diff --git a/docs/api/XCEngine/Threading/Mutex/Lock.md b/docs/api/XCEngine/Threading/Mutex/Lock.md new file mode 100644 index 00000000..64dfceb3 --- /dev/null +++ b/docs/api/XCEngine/Threading/Mutex/Lock.md @@ -0,0 +1,31 @@ +# Mutex::Lock + +阻塞直到获得互斥锁。 + +```cpp +void Lock(); +void lock() const; +``` + +## 行为说明 + +当前实现有两套入口: + +- `Lock()`:引擎风格命名。 +- `lock()`:标准 Lockable 风格别名。 + +两者都直接转发到底层 `std::mutex::lock()`。 + +## 返回值 + +- 无。 + +## 注意事项 + +- 如果当前线程已经持有这把锁,再次调用会死锁。 +- `lock()` 的存在使 `Mutex` 可以直接配合 `std::lock_guard` 等标准库工具使用。 + +## 相关文档 + +- [返回类型总览](Mutex.md) +- [Unlock](Unlock.md) diff --git a/docs/api/XCEngine/Threading/Mutex/Mutex.md b/docs/api/XCEngine/Threading/Mutex/Mutex.md index 2f9fc3c8..8df7b339 100644 --- a/docs/api/XCEngine/Threading/Mutex/Mutex.md +++ b/docs/api/XCEngine/Threading/Mutex/Mutex.md @@ -6,32 +6,36 @@ **头文件**: `XCEngine/Threading/Mutex.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `Mutex` public API。 +**描述**: 对 `std::mutex` 的薄封装,同时提供引擎风格和 STL Lockable 风格接口。 ## 概述 -`Mutex.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`Mutex` 的实现非常直接:内部只有一个 `mutable std::mutex m_mutex`,所有公开接口都是对它的转发。 -## 声明概览 +这类包装在引擎里常见的原因不是为了改变 `std::mutex` 的行为,而是为了: -| 声明 | 类型 | 说明 | -|------|------|------| -| `Mutex` | `class` | 头文件中的公开声明。 | +- 统一命名空间与 include 路径。 +- 同时支持 `Lock()` 这种引擎风格接口。 +- 也支持 `lock()` / `unlock()` / `try_lock()` 这种标准库 Lockable 习惯用法。 -## 公共方法 +## 当前实现边界 -| 方法 | 描述 | +- 它不是递归锁;同一线程重复加锁会死锁。 +- 没有超时锁接口。 +- 没有显式的 owner 检查或调试断言。 +- 小写接口之所以能声明成 `const`,是因为底层 `std::mutex` 被保存为 `mutable`。 + +## 公开方法 + +| 方法 | 说明 | |------|------| -| [Mutex()](Constructor.md) | 构造对象。 | -| [~Mutex()](Destructor.md) | 销毁对象并释放相关资源。 | -| [Lock](Lock.md) | 公开方法,详见头文件声明。 | -| [Unlock](Unlock.md) | 公开方法,详见头文件声明。 | -| [TryLock](TryLock.md) | 公开方法,详见头文件声明。 | -| [lock](lock.md) | 公开方法,详见头文件声明。 | -| [unlock](unlock.md) | 公开方法,详见头文件声明。 | -| [try_lock](try_lock.md) | 公开方法,详见头文件声明。 | +| [Constructor](Constructor.md) | 默认构造互斥锁。 | +| [Destructor](Destructor.md) | 销毁互斥锁。 | +| [Lock](Lock.md) | 阻塞直到获得锁;同页也说明 `lock()` 别名。 | +| [Unlock](Unlock.md) | 释放锁;同页也说明 `unlock()` 别名。 | +| [TryLock](TryLock.md) | 尝试获得锁;同页也说明 `try_lock()` 别名。 | ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [SpinLock](../SpinLock/SpinLock.md) diff --git a/docs/api/XCEngine/Threading/Mutex/TryLock.md b/docs/api/XCEngine/Threading/Mutex/TryLock.md index c9848b44..524614bb 100644 --- a/docs/api/XCEngine/Threading/Mutex/TryLock.md +++ b/docs/api/XCEngine/Threading/Mutex/TryLock.md @@ -1,30 +1,26 @@ # Mutex::TryLock -公开方法,详见头文件声明。 +尝试获得互斥锁。 ```cpp bool TryLock(); +bool try_lock() const; ``` -该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现有两套入口: -**返回:** `bool` - 返回值语义详见头文件声明。 +- `TryLock()`:引擎风格命名。 +- `try_lock()`:标准 Lockable 风格别名。 -**示例:** +两者都直接调用底层 `std::mutex::try_lock()`。 -```cpp -#include +## 返回值 -void Example() { - XCEngine::Threading::Mutex object; - // 根据上下文补齐参数后调用 Mutex::TryLock(...)。 - (void)object; -} -``` +- `bool` - 成功获得锁时返回 `true`;否则返回 `false`。 ## 相关文档 -- [返回类总览](Mutex.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Mutex.md) +- [Lock](Lock.md) diff --git a/docs/api/XCEngine/Threading/Mutex/Unlock.md b/docs/api/XCEngine/Threading/Mutex/Unlock.md new file mode 100644 index 00000000..a13f5b83 --- /dev/null +++ b/docs/api/XCEngine/Threading/Mutex/Unlock.md @@ -0,0 +1,26 @@ +# Mutex::Unlock + +释放互斥锁。 + +```cpp +void Unlock(); +void unlock() const; +``` + +## 行为说明 + +当前实现有两套入口: + +- `Unlock()`:引擎风格命名。 +- `unlock()`:标准 Lockable 风格别名。 + +两者都直接转发到底层 `std::mutex::unlock()`。 + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](Mutex.md) +- [Lock](Lock.md) diff --git a/docs/api/XCEngine/Threading/Mutex/lock.md b/docs/api/XCEngine/Threading/Mutex/lock.md deleted file mode 100644 index 03f78c60..00000000 --- a/docs/api/XCEngine/Threading/Mutex/lock.md +++ /dev/null @@ -1,30 +0,0 @@ -# Mutex::lock - -公开方法,详见头文件声明。 - -```cpp -void lock() const; -``` - -该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。 - -**参数:** 无。 - -**返回:** `void` - 无返回值。 - -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::Mutex object; - // 根据上下文补齐参数后调用 Mutex::lock(...)。 - (void)object; -} -``` - -## 相关文档 - -- [返回类总览](Mutex.md) -- [返回模块目录](../Threading.md) diff --git a/docs/api/XCEngine/Threading/Mutex/try_lock.md b/docs/api/XCEngine/Threading/Mutex/try_lock.md deleted file mode 100644 index 3edc33b1..00000000 --- a/docs/api/XCEngine/Threading/Mutex/try_lock.md +++ /dev/null @@ -1,30 +0,0 @@ -# Mutex::try_lock - -公开方法,详见头文件声明。 - -```cpp -bool try_lock() const; -``` - -该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。 - -**参数:** 无。 - -**返回:** `bool` - 返回值语义详见头文件声明。 - -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::Mutex object; - // 根据上下文补齐参数后调用 Mutex::try_lock(...)。 - (void)object; -} -``` - -## 相关文档 - -- [返回类总览](Mutex.md) -- [返回模块目录](../Threading.md) diff --git a/docs/api/XCEngine/Threading/Mutex/unlock.md b/docs/api/XCEngine/Threading/Mutex/unlock.md deleted file mode 100644 index 48732f39..00000000 --- a/docs/api/XCEngine/Threading/Mutex/unlock.md +++ /dev/null @@ -1,30 +0,0 @@ -# Mutex::unlock - -公开方法,详见头文件声明。 - -```cpp -void unlock() const; -``` - -该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。 - -**参数:** 无。 - -**返回:** `void` - 无返回值。 - -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::Mutex object; - // 根据上下文补齐参数后调用 Mutex::unlock(...)。 - (void)object; -} -``` - -## 相关文档 - -- [返回类总览](Mutex.md) -- [返回模块目录](../Threading.md) diff --git a/docs/api/XCEngine/Threading/ReadWriteLock/Constructor.md b/docs/api/XCEngine/Threading/ReadWriteLock/Constructor.md index 277ba6f1..046880c4 100644 --- a/docs/api/XCEngine/Threading/ReadWriteLock/Constructor.md +++ b/docs/api/XCEngine/Threading/ReadWriteLock/Constructor.md @@ -1,28 +1,23 @@ -# ReadWriteLock::ReadWriteLock() +# ReadWriteLock::Constructor -构造对象。 +默认构造一个读写锁。 ```cpp ReadWriteLock() = default; ``` -该方法声明于 `XCEngine/Threading/ReadWriteLock.h`,当前页面用于固定 `ReadWriteLock` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前构造函数是默认实现,初始状态等价于: -**返回:** `void` - 无返回值。 +- `m_readers == 0` +- `m_writersWaiting == 0` +- `m_writerActive == false` -**示例:** +## 返回值 -```cpp -#include - -void Example() { - XCEngine::Threading::ReadWriteLock object; -} -``` +- 无。 ## 相关文档 -- [返回类总览](ReadWriteLock.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](ReadWriteLock.md) diff --git a/docs/api/XCEngine/Threading/ReadWriteLock/Destructor.md b/docs/api/XCEngine/Threading/ReadWriteLock/Destructor.md index 923c1dfb..b467abe4 100644 --- a/docs/api/XCEngine/Threading/ReadWriteLock/Destructor.md +++ b/docs/api/XCEngine/Threading/ReadWriteLock/Destructor.md @@ -1,29 +1,19 @@ -# ReadWriteLock::~ReadWriteLock() +# ReadWriteLock::Destructor -销毁对象并释放相关资源。 +销毁读写锁对象。 ```cpp ~ReadWriteLock() = default; ``` -该方法声明于 `XCEngine/Threading/ReadWriteLock.h`,当前页面用于固定 `ReadWriteLock` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前析构函数是默认实现,底层销毁行为由内部 `std::mutex` 和 `std::condition_variable` 决定。 -**返回:** `void` - 无返回值。 +## 返回值 -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::ReadWriteLock object; - // 对象离开作用域时会自动触发析构。 -} -``` +- 无。 ## 相关文档 -- [返回类总览](ReadWriteLock.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](ReadWriteLock.md) diff --git a/docs/api/XCEngine/Threading/ReadWriteLock/ReadLock.md b/docs/api/XCEngine/Threading/ReadWriteLock/ReadLock.md index 7de6c40e..e4f5b3b7 100644 --- a/docs/api/XCEngine/Threading/ReadWriteLock/ReadLock.md +++ b/docs/api/XCEngine/Threading/ReadWriteLock/ReadLock.md @@ -1,30 +1,31 @@ # ReadWriteLock::ReadLock -公开方法,详见头文件声明。 +以共享方式进入读写锁。 ```cpp void ReadLock(); ``` -该方法声明于 `XCEngine/Threading/ReadWriteLock.h`,当前页面用于固定 `ReadWriteLock` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 - -**返回:** `void` - 无返回值。 - -**示例:** +当前实现会先拿内部互斥量,然后等待下面这个条件成立: ```cpp -#include - -void Example() { - XCEngine::Threading::ReadWriteLock object; - // 根据上下文补齐参数后调用 ReadWriteLock::ReadLock(...)。 - (void)object; -} +!m_writerActive && m_writersWaiting == 0 ``` +条件满足后,`m_readers` 加一。 + +## 返回值 + +- 无。 + +## 注意事项 + +- 只要有写者在等待,新读者也会被拦住,因此当前策略是写者优先而不是纯读者优先。 + ## 相关文档 -- [返回类总览](ReadWriteLock.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](ReadWriteLock.md) +- [ReadUnlock](ReadUnlock.md) +- [WriteLock](WriteLock.md) diff --git a/docs/api/XCEngine/Threading/ReadWriteLock/ReadUnlock.md b/docs/api/XCEngine/Threading/ReadWriteLock/ReadUnlock.md index fd525427..3246edf0 100644 --- a/docs/api/XCEngine/Threading/ReadWriteLock/ReadUnlock.md +++ b/docs/api/XCEngine/Threading/ReadWriteLock/ReadUnlock.md @@ -1,30 +1,23 @@ # ReadWriteLock::ReadUnlock -公开方法,详见头文件声明。 +释放共享读锁。 ```cpp void ReadUnlock(); ``` -该方法声明于 `XCEngine/Threading/ReadWriteLock.h`,当前页面用于固定 `ReadWriteLock` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会先拿内部互斥量,再执行: -**返回:** `void` - 无返回值。 +1. `--m_readers` +2. 如果 `m_readers == 0`,调用 `m_writeCondition.notify_all()` -**示例:** +## 返回值 -```cpp -#include - -void Example() { - XCEngine::Threading::ReadWriteLock object; - // 根据上下文补齐参数后调用 ReadWriteLock::ReadUnlock(...)。 - (void)object; -} -``` +- 无。 ## 相关文档 -- [返回类总览](ReadWriteLock.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](ReadWriteLock.md) +- [ReadLock](ReadLock.md) diff --git a/docs/api/XCEngine/Threading/ReadWriteLock/ReadWriteLock.md b/docs/api/XCEngine/Threading/ReadWriteLock/ReadWriteLock.md index d1a7efaf..3b10513b 100644 --- a/docs/api/XCEngine/Threading/ReadWriteLock/ReadWriteLock.md +++ b/docs/api/XCEngine/Threading/ReadWriteLock/ReadWriteLock.md @@ -6,30 +6,33 @@ **头文件**: `XCEngine/Threading/ReadWriteLock.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `ReadWriteLock` public API。 +**描述**: 基于互斥量和条件变量实现的写者优先读写锁。 ## 概述 -`ReadWriteLock.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`ReadWriteLock` 允许多个读者并发进入,但写者需要独占访问。 -## 声明概览 +当前实现的一个关键策略是:只要有写者在等待,新读者就不能继续进入。这意味着它更偏向“写者优先”,可以降低写者长期饥饿的风险,但也可能让高频写入场景里的读者等待更久。 -| 声明 | 类型 | 说明 | -|------|------|------| -| `ReadWriteLock` | `class` | 头文件中的公开声明。 | +## 当前实现边界 -## 公共方法 +- 没有 `TryReadLock()` / `TryWriteLock()`。 +- 没有升级、降级或 RAII guard 类型。 +- 当前策略会在 `m_writersWaiting > 0` 时阻止新读者进入,因此可能出现读者饥饿。 +- 没有单测覆盖这把锁的并发行为。 -| 方法 | 描述 | +## 公开方法 + +| 方法 | 说明 | |------|------| -| [ReadWriteLock()](Constructor.md) | 构造对象。 | -| [~ReadWriteLock()](Destructor.md) | 销毁对象并释放相关资源。 | -| [ReadLock](ReadLock.md) | 公开方法,详见头文件声明。 | -| [ReadUnlock](ReadUnlock.md) | 公开方法,详见头文件声明。 | -| [WriteLock](WriteLock.md) | 公开方法,详见头文件声明。 | -| [WriteUnlock](WriteUnlock.md) | 公开方法,详见头文件声明。 | +| [Constructor](Constructor.md) | 默认构造读写锁。 | +| [Destructor](Destructor.md) | 销毁读写锁。 | +| [ReadLock](ReadLock.md) | 以共享方式进入。 | +| [ReadUnlock](ReadUnlock.md) | 释放共享读锁。 | +| [WriteLock](WriteLock.md) | 以独占方式进入。 | +| [WriteUnlock](WriteUnlock.md) | 释放独占写锁。 | ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [Mutex](../Mutex/Mutex.md) diff --git a/docs/api/XCEngine/Threading/ReadWriteLock/WriteLock.md b/docs/api/XCEngine/Threading/ReadWriteLock/WriteLock.md index 51976556..a0249b60 100644 --- a/docs/api/XCEngine/Threading/ReadWriteLock/WriteLock.md +++ b/docs/api/XCEngine/Threading/ReadWriteLock/WriteLock.md @@ -1,30 +1,26 @@ # ReadWriteLock::WriteLock -公开方法,详见头文件声明。 +以独占方式进入读写锁。 ```cpp void WriteLock(); ``` -该方法声明于 `XCEngine/Threading/ReadWriteLock.h`,当前页面用于固定 `ReadWriteLock` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会: -**返回:** `void` - 无返回值。 +1. 拿内部互斥量。 +2. 先执行 `++m_writersWaiting`。 +3. 等待 `m_readers == 0 && !m_writerActive`。 +4. 条件满足后执行 `--m_writersWaiting` 并把 `m_writerActive = true`。 -**示例:** +## 返回值 -```cpp -#include - -void Example() { - XCEngine::Threading::ReadWriteLock object; - // 根据上下文补齐参数后调用 ReadWriteLock::WriteLock(...)。 - (void)object; -} -``` +- 无。 ## 相关文档 -- [返回类总览](ReadWriteLock.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](ReadWriteLock.md) +- [WriteUnlock](WriteUnlock.md) +- [ReadLock](ReadLock.md) diff --git a/docs/api/XCEngine/Threading/ReadWriteLock/WriteUnlock.md b/docs/api/XCEngine/Threading/ReadWriteLock/WriteUnlock.md index 4f1988a4..42de6197 100644 --- a/docs/api/XCEngine/Threading/ReadWriteLock/WriteUnlock.md +++ b/docs/api/XCEngine/Threading/ReadWriteLock/WriteUnlock.md @@ -1,30 +1,24 @@ # ReadWriteLock::WriteUnlock -公开方法,详见头文件声明。 +释放独占写锁。 ```cpp void WriteUnlock(); ``` -该方法声明于 `XCEngine/Threading/ReadWriteLock.h`,当前页面用于固定 `ReadWriteLock` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会先拿内部互斥量,然后: -**返回:** `void` - 无返回值。 +1. 把 `m_writerActive = false` +2. 调用 `m_readCondition.notify_all()` +3. 调用 `m_writeCondition.notify_one()` -**示例:** +## 返回值 -```cpp -#include - -void Example() { - XCEngine::Threading::ReadWriteLock object; - // 根据上下文补齐参数后调用 ReadWriteLock::WriteUnlock(...)。 - (void)object; -} -``` +- 无。 ## 相关文档 -- [返回类总览](ReadWriteLock.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](ReadWriteLock.md) +- [WriteLock](WriteLock.md) diff --git a/docs/api/XCEngine/Threading/SpinLock/Lock.md b/docs/api/XCEngine/Threading/SpinLock/Lock.md new file mode 100644 index 00000000..82a38b04 --- /dev/null +++ b/docs/api/XCEngine/Threading/SpinLock/Lock.md @@ -0,0 +1,36 @@ +# SpinLock::Lock + +自旋直到获得锁。 + +```cpp +void Lock(); +void lock(); +``` + +## 行为说明 + +当前实现有两套入口: + +- `Lock()`:引擎风格命名。 +- `lock()`:标准 Lockable 风格别名。 + +核心逻辑是一个空循环: + +```cpp +while (m_flag.test_and_set(std::memory_order_acquire)) { +} +``` + +## 返回值 + +- 无。 + +## 注意事项 + +- 持锁时间稍长时会持续占用 CPU。 +- 适合极短临界区,不适合可能阻塞的工作。 + +## 相关文档 + +- [返回类型总览](SpinLock.md) +- [Unlock](Unlock.md) diff --git a/docs/api/XCEngine/Threading/SpinLock/SpinLock.md b/docs/api/XCEngine/Threading/SpinLock/SpinLock.md index e0c67193..425f156e 100644 --- a/docs/api/XCEngine/Threading/SpinLock/SpinLock.md +++ b/docs/api/XCEngine/Threading/SpinLock/SpinLock.md @@ -6,30 +6,33 @@ **头文件**: `XCEngine/Threading/SpinLock.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `SpinLock` public API。 +**描述**: 基于 `std::atomic_flag` 的轻量自旋锁。 ## 概述 -`SpinLock.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`SpinLock` 和 `Mutex` 的主要区别不在 API 形状,而在等待策略: -## 声明概览 +- `Mutex` 依赖 OS 互斥量阻塞等待。 +- `SpinLock` 在失败时会一直忙等,不让出 CPU。 -| 声明 | 类型 | 说明 | -|------|------|------| -| `SpinLock` | `class` | 头文件中的公开声明。 | +这类锁通常只适合非常短的临界区,例如极小的元数据更新。商业引擎会保留它,是因为在高频、超短持锁窗口下,系统 mutex 的调度成本可能反而更高。 -## 公共方法 +## 当前实现边界 -| 方法 | 描述 | +- 失败时是空循环忙等,没有回退、没有 `Yield()`、没有 pause 指令。 +- 没有公平性保证。 +- 不是递归锁;同一线程重复进入会自旋死锁。 +- 与 `Mutex` 一样,同时提供了标准 Lockable 风格小写别名。 + +## 公开方法 + +| 方法 | 说明 | |------|------| -| [Lock](Lock.md) | 公开方法,详见头文件声明。 | -| [Unlock](Unlock.md) | 公开方法,详见头文件声明。 | -| [TryLock](TryLock.md) | 公开方法,详见头文件声明。 | -| [lock](lock.md) | 公开方法,详见头文件声明。 | -| [unlock](unlock.md) | 公开方法,详见头文件声明。 | -| [try_lock](try_lock.md) | 公开方法,详见头文件声明。 | +| [Lock](Lock.md) | 阻塞自旋直到获得锁;同页也说明 `lock()` 别名。 | +| [Unlock](Unlock.md) | 释放锁;同页也说明 `unlock()` 别名。 | +| [TryLock](TryLock.md) | 尝试获得锁;同页也说明 `try_lock()` 别名。 | ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [Mutex](../Mutex/Mutex.md) diff --git a/docs/api/XCEngine/Threading/SpinLock/TryLock.md b/docs/api/XCEngine/Threading/SpinLock/TryLock.md index fcbfb0cb..fa14f22d 100644 --- a/docs/api/XCEngine/Threading/SpinLock/TryLock.md +++ b/docs/api/XCEngine/Threading/SpinLock/TryLock.md @@ -1,30 +1,30 @@ # SpinLock::TryLock -公开方法,详见头文件声明。 +尝试获得自旋锁。 ```cpp bool TryLock(); +bool try_lock(); ``` -该方法声明于 `XCEngine/Threading/SpinLock.h`,当前页面用于固定 `SpinLock` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现有两套入口: -**返回:** `bool` - 返回值语义详见头文件声明。 +- `TryLock()`:引擎风格命名。 +- `try_lock()`:标准 Lockable 风格别名。 -**示例:** +两者最终都调用同一份逻辑: ```cpp -#include - -void Example() { - XCEngine::Threading::SpinLock object; - // 根据上下文补齐参数后调用 SpinLock::TryLock(...)。 - (void)object; -} +return !m_flag.test_and_set(std::memory_order_acquire); ``` +## 返回值 + +- `bool` - 成功获得锁时返回 `true`;否则返回 `false`。 + ## 相关文档 -- [返回类总览](SpinLock.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](SpinLock.md) +- [Lock](Lock.md) diff --git a/docs/api/XCEngine/Threading/SpinLock/Unlock.md b/docs/api/XCEngine/Threading/SpinLock/Unlock.md new file mode 100644 index 00000000..0203a3a5 --- /dev/null +++ b/docs/api/XCEngine/Threading/SpinLock/Unlock.md @@ -0,0 +1,30 @@ +# SpinLock::Unlock + +释放自旋锁。 + +```cpp +void Unlock(); +void unlock(); +``` + +## 行为说明 + +当前实现有两套入口: + +- `Unlock()`:引擎风格命名。 +- `unlock()`:标准 Lockable 风格别名。 + +两者都执行: + +```cpp +m_flag.clear(std::memory_order_release); +``` + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](SpinLock.md) +- [Lock](Lock.md) diff --git a/docs/api/XCEngine/Threading/SpinLock/lock.md b/docs/api/XCEngine/Threading/SpinLock/lock.md deleted file mode 100644 index 376bce33..00000000 --- a/docs/api/XCEngine/Threading/SpinLock/lock.md +++ /dev/null @@ -1,30 +0,0 @@ -# SpinLock::lock - -公开方法,详见头文件声明。 - -```cpp -void lock(); -``` - -该方法声明于 `XCEngine/Threading/SpinLock.h`,当前页面用于固定 `SpinLock` 类目录下的方法级 canonical 路径。 - -**参数:** 无。 - -**返回:** `void` - 无返回值。 - -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::SpinLock object; - // 根据上下文补齐参数后调用 SpinLock::lock(...)。 - (void)object; -} -``` - -## 相关文档 - -- [返回类总览](SpinLock.md) -- [返回模块目录](../Threading.md) diff --git a/docs/api/XCEngine/Threading/SpinLock/try_lock.md b/docs/api/XCEngine/Threading/SpinLock/try_lock.md deleted file mode 100644 index 540f3fb5..00000000 --- a/docs/api/XCEngine/Threading/SpinLock/try_lock.md +++ /dev/null @@ -1,30 +0,0 @@ -# SpinLock::try_lock - -公开方法,详见头文件声明。 - -```cpp -bool try_lock(); -``` - -该方法声明于 `XCEngine/Threading/SpinLock.h`,当前页面用于固定 `SpinLock` 类目录下的方法级 canonical 路径。 - -**参数:** 无。 - -**返回:** `bool` - 返回值语义详见头文件声明。 - -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::SpinLock object; - // 根据上下文补齐参数后调用 SpinLock::try_lock(...)。 - (void)object; -} -``` - -## 相关文档 - -- [返回类总览](SpinLock.md) -- [返回模块目录](../Threading.md) diff --git a/docs/api/XCEngine/Threading/SpinLock/unlock.md b/docs/api/XCEngine/Threading/SpinLock/unlock.md deleted file mode 100644 index ec566251..00000000 --- a/docs/api/XCEngine/Threading/SpinLock/unlock.md +++ /dev/null @@ -1,30 +0,0 @@ -# SpinLock::unlock - -公开方法,详见头文件声明。 - -```cpp -void unlock(); -``` - -该方法声明于 `XCEngine/Threading/SpinLock.h`,当前页面用于固定 `SpinLock` 类目录下的方法级 canonical 路径。 - -**参数:** 无。 - -**返回:** `void` - 无返回值。 - -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::SpinLock object; - // 根据上下文补齐参数后调用 SpinLock::unlock(...)。 - (void)object; -} -``` - -## 相关文档 - -- [返回类总览](SpinLock.md) -- [返回模块目录](../Threading.md) diff --git a/docs/api/XCEngine/Threading/Task/AddRef.md b/docs/api/XCEngine/Threading/Task/AddRef.md new file mode 100644 index 00000000..4090a68e --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/AddRef.md @@ -0,0 +1,24 @@ +# ITask::AddRef + +增加任务对象引用计数。 + +```cpp +void AddRef(); +``` + +## 行为说明 + +当前头文件内联实现执行: + +```cpp +m_refCount.fetch_add(1); +``` + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [Release](Release.md) diff --git a/docs/api/XCEngine/Threading/Task/Destructor.md b/docs/api/XCEngine/Threading/Task/Destructor.md new file mode 100644 index 00000000..e7f7cd34 --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/Destructor.md @@ -0,0 +1,20 @@ +# ITask::Destructor + +通过基类指针安全销毁任务对象。 + +```cpp +virtual ~ITask() = default; +``` + +## 行为说明 + +虚析构函数保证派生任务能够通过 `ITask*` 正确析构。 + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [Release](Release.md) diff --git a/docs/api/XCEngine/Threading/Task/Execute.md b/docs/api/XCEngine/Threading/Task/Execute.md new file mode 100644 index 00000000..95c55e15 --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/Execute.md @@ -0,0 +1,20 @@ +# ITask::Execute + +执行任务主体。 + +```cpp +virtual void Execute() = 0; +``` + +## 行为说明 + +这是纯虚接口,具体任务逻辑由派生类实现。 + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [OnComplete](OnComplete.md) diff --git a/docs/api/XCEngine/Threading/Task/GetId.md b/docs/api/XCEngine/Threading/Task/GetId.md new file mode 100644 index 00000000..c963e26d --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/GetId.md @@ -0,0 +1,20 @@ +# ITask::GetId + +读取任务 ID。 + +```cpp +uint64_t GetId() const; +``` + +## 行为说明 + +当前头文件内联实现直接返回 `m_id`。 + +## 返回值 + +- `uint64_t` - 当前任务 ID。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [SetId](SetId.md) diff --git a/docs/api/XCEngine/Threading/Task/GetPriority.md b/docs/api/XCEngine/Threading/Task/GetPriority.md new file mode 100644 index 00000000..290b0c0f --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/GetPriority.md @@ -0,0 +1,20 @@ +# ITask::GetPriority + +读取任务优先级。 + +```cpp +TaskPriority GetPriority() const; +``` + +## 行为说明 + +当前头文件内联实现直接返回 `m_priority`。 + +## 返回值 + +- `TaskPriority` - 当前任务优先级。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [SetPriority](SetPriority.md) diff --git a/docs/api/XCEngine/Threading/Task/GetStatus.md b/docs/api/XCEngine/Threading/Task/GetStatus.md new file mode 100644 index 00000000..a2576e49 --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/GetStatus.md @@ -0,0 +1,20 @@ +# ITask::GetStatus + +读取任务状态。 + +```cpp +TaskStatus GetStatus() const; +``` + +## 行为说明 + +当前头文件内联实现通过 `m_status.load()` 返回原子状态值。 + +## 返回值 + +- `TaskStatus` - 当前任务状态。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [SetStatus](SetStatus.md) diff --git a/docs/api/XCEngine/Threading/Task/OnCancel.md b/docs/api/XCEngine/Threading/Task/OnCancel.md new file mode 100644 index 00000000..04c6243e --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/OnCancel.md @@ -0,0 +1,20 @@ +# ITask::OnCancel + +任务取消时的回调钩子。 + +```cpp +virtual void OnCancel() {} +``` + +## 行为说明 + +当前基类默认实现为空,不做任何事。 + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [OnComplete](OnComplete.md) diff --git a/docs/api/XCEngine/Threading/Task/OnComplete.md b/docs/api/XCEngine/Threading/Task/OnComplete.md new file mode 100644 index 00000000..9b589dbc --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/OnComplete.md @@ -0,0 +1,20 @@ +# ITask::OnComplete + +任务完成后的回调钩子。 + +```cpp +virtual void OnComplete() {} +``` + +## 行为说明 + +当前基类默认实现为空,不做任何事。 + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [Execute](Execute.md) diff --git a/docs/api/XCEngine/Threading/Task/Release.md b/docs/api/XCEngine/Threading/Task/Release.md new file mode 100644 index 00000000..1a38166c --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/Release.md @@ -0,0 +1,28 @@ +# ITask::Release + +释放一次任务对象引用。 + +```cpp +void Release(); +``` + +## 行为说明 + +当前头文件内联实现会: + +1. 执行 `m_refCount.fetch_sub(1)` +2. 如果旧值正好是 `1`,则执行 `delete this` + +## 返回值 + +- 无。 + +## 注意事项 + +- 这是一套侵入式引用计数协议,默认假设对象是 `new` 出来的。 +- 如果对栈对象调用 `Release()` 并走到 `delete this`,会产生未定义行为。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [AddRef](AddRef.md) diff --git a/docs/api/XCEngine/Threading/Task/SetId.md b/docs/api/XCEngine/Threading/Task/SetId.md new file mode 100644 index 00000000..e2c9099f --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/SetId.md @@ -0,0 +1,24 @@ +# ITask::SetId + +设置任务 ID。 + +```cpp +void SetId(uint64_t id); +``` + +## 行为说明 + +当前头文件内联实现直接执行 `m_id = id`。 + +## 参数 + +- `id` - 要写入的任务 ID。 + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [GetId](GetId.md) diff --git a/docs/api/XCEngine/Threading/Task/SetPriority.md b/docs/api/XCEngine/Threading/Task/SetPriority.md new file mode 100644 index 00000000..5ce8479a --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/SetPriority.md @@ -0,0 +1,24 @@ +# ITask::SetPriority + +设置任务优先级。 + +```cpp +void SetPriority(TaskPriority priority); +``` + +## 行为说明 + +当前头文件内联实现直接执行 `m_priority = priority`。 + +## 参数 + +- `priority` - 要写入的优先级。 + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [GetPriority](GetPriority.md) diff --git a/docs/api/XCEngine/Threading/Task/SetStatus.md b/docs/api/XCEngine/Threading/Task/SetStatus.md new file mode 100644 index 00000000..b116c76d --- /dev/null +++ b/docs/api/XCEngine/Threading/Task/SetStatus.md @@ -0,0 +1,24 @@ +# ITask::SetStatus + +设置任务状态。 + +```cpp +void SetStatus(TaskStatus status); +``` + +## 行为说明 + +当前头文件内联实现直接把 `status` 写入原子成员 `m_status`。 + +## 参数 + +- `status` - 要写入的新状态。 + +## 返回值 + +- 无。 + +## 相关文档 + +- [返回类型总览](Task.md) +- [GetStatus](GetStatus.md) diff --git a/docs/api/XCEngine/Threading/Task/Task.md b/docs/api/XCEngine/Threading/Task/Task.md index a79847d6..2968eb24 100644 --- a/docs/api/XCEngine/Threading/Task/Task.md +++ b/docs/api/XCEngine/Threading/Task/Task.md @@ -1,36 +1,74 @@ -# Task +# ITask **命名空间**: `XCEngine::Threading` -**类型**: `enum class` +**类型**: `class (abstract interface)` + `enum class` **头文件**: `XCEngine/Threading/Task.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `Task` public API。 +**描述**: 定义任务优先级、任务状态以及带侵入式引用计数的抽象任务基类 `ITask`。 ## 概述 -`Task.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`Task.h` 暴露了三类核心概念: -## 声明概览 +- `TaskPriority`:任务优先级枚举。 +- `TaskStatus`:任务状态枚举。 +- `ITask`:任务执行、完成回调、取消回调和引用计数的统一基类。 -| 声明 | 类型 | 说明 | -|------|------|------| -| `TaskPriority` | `enum class` | 头文件中的公开声明。 | -| `TaskStatus` | `enum class` | 头文件中的公开声明。 | -| `ITask` | `class` | 头文件中的公开声明。 | +这种设计很像很多商业引擎早期 job system 的起点:先用一个稳定任务抽象把“执行单元”统一起来,再围绕它搭调度器、主线程回调和任务组。 -## 枚举值 +## 枚举 -| 枚举值 | 数值 | 描述 | -|--------|------|------| -| `Critical` | `0` | 枚举项。 | -| `High` | `1` | 枚举项。 | -| `Normal` | `2` | 枚举项。 | -| `Low` | `3` | 枚举项。 | -| `Idle` | `4` | 枚举项。 | +### `TaskPriority` + +当前优先级从高到低依次是: + +- `Critical` +- `High` +- `Normal` +- `Low` +- `Idle` + +### `TaskStatus` + +当前状态包括: + +- `Pending` +- `Scheduled` +- `Running` +- `Completed` +- `Failed` +- `Canceled` + +## 当前实现边界 + +- `ITask` 采用侵入式引用计数;`Release()` 在计数归零时直接 `delete this`,因此这套生命周期默认假设任务对象位于堆上。 +- `m_status` 是原子值,但 `m_priority` 和 `m_id` 不是。 +- 当前 `TaskSystem` 并没有完整使用这套状态机,例如提交时不会自动写入 `Scheduled`。 + +## 公开方法 + +| 方法 | 说明 | +|------|------| +| [Destructor](Destructor.md) | 虚析构函数。 | +| [Execute](Execute.md) | 执行任务主体。 | +| [OnComplete](OnComplete.md) | 完成回调。 | +| [OnCancel](OnCancel.md) | 取消回调。 | +| [GetPriority](GetPriority.md) | 读取优先级。 | +| [GetStatus](GetStatus.md) | 读取状态。 | +| [GetId](GetId.md) | 读取任务 ID。 | +| [SetId](SetId.md) | 设置任务 ID。 | +| [SetPriority](SetPriority.md) | 设置优先级。 | +| [SetStatus](SetStatus.md) | 设置状态。 | +| [AddRef](AddRef.md) | 增加引用计数。 | +| [Release](Release.md) | 释放引用。 | + +## 已知实现 + +- [LambdaTask](../LambdaTask/LambdaTask.md) ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [TaskSystem](../TaskSystem/TaskSystem.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/AddDependency.md b/docs/api/XCEngine/Threading/TaskGroup/AddDependency.md index 22ea9634..a8f7a6b3 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/AddDependency.md +++ b/docs/api/XCEngine/Threading/TaskGroup/AddDependency.md @@ -1,32 +1,44 @@ # TaskGroup::AddDependency -添加元素或建立关联。 +记录一个任务对另一个任务的依赖关系。 ```cpp void AddDependency(uint64_t taskId, uint64_t dependsOn); ``` -该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `taskId` - 参数语义详见头文件声明。 -- `dependsOn` - 参数语义详见头文件声明。 +当前实现会在持锁状态下检查两个 ID 是否都位于 `m_tasks` 范围内;如果合法,就把 `dependsOn` 追加到 `m_tasks[taskId].dependencies`。 -**返回:** `void` - 无返回值。 +如果任一 ID 越界,函数会直接忽略这次调用。 -**示例:** +## 参数 -```cpp -#include +- `taskId` - 依赖别人的任务。 +- `dependsOn` - 被依赖的任务。 -void Example() { - XCEngine::Threading::TaskGroup object; - // 根据上下文补齐参数后调用 TaskGroup::AddDependency(...)。 - (void)object; -} -``` +## 返回值 + +- 无。 + +## 当前实现限制 + +- 当前只保存依赖 ID,不会递增 `pendingDepCount`。 +- 当前没有环检测。 +- 当前没有“依赖完成后解锁任务”的运行时逻辑。 +- 由于 [TaskGroup](TaskGroup.md) 本身没有接入真正调度,这些依赖关系目前只是被记录下来,不会改变任务执行顺序。 + +## 设计说明 + +商业级任务系统里的依赖通常会驱动两个行为: + +- 决定任务什么时候从 waiting 变成 ready。 +- 决定整组任务什么时候可以触发 completion fence。 + +当前 `AddDependency()` 只覆盖了“数据结构里留一份关系记录”这一步。 ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [AddTask](AddTask.md) +- [Wait](Wait.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/AddTask.md b/docs/api/XCEngine/Threading/TaskGroup/AddTask.md index d343241c..504423bf 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/AddTask.md +++ b/docs/api/XCEngine/Threading/TaskGroup/AddTask.md @@ -1,45 +1,52 @@ # TaskGroup::AddTask -添加元素或建立关联。 - -该方法在 `XCEngine/Threading/TaskGroup.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。 - -## 重载 1: 声明 +向任务组添加一个任务对象或 lambda 任务。 ```cpp uint64_t AddTask(std::unique_ptr task); -``` - -**参数:** -- `task` - 参数语义详见头文件声明。 - -**返回:** `uint64_t` - 返回值语义详见头文件声明。 - -## 重载 2: 声明 - -```cpp uint64_t AddTask(Callback&& func, TaskPriority priority = TaskPriority::Normal); ``` -**参数:** -- `func` - 参数语义详见头文件声明。 -- `priority` - 参数语义详见头文件声明。 +## 行为说明 -**返回:** `uint64_t` - 返回值语义详见头文件声明。 +`AddTask(std::unique_ptr)` 当前会: -**示例:** +1. 加锁保护 `m_tasks`。 +2. 取出 `task.get()` 保存到内部 `TaskNode::task`。 +3. 用当前 `m_tasks.size()` 作为返回的任务 ID。 +4. 把节点追加到 `m_tasks`。 +5. 递增 `m_pendingCount`。 +6. 对传入的 `unique_ptr` 调用 `release()`。 -```cpp -#include +`AddTask(Callback&&, TaskPriority)` 会先构造一个 `LambdaTask`,然后转发到上面的重载。 -void Example() { - XCEngine::Threading::TaskGroup object; - // 根据上下文补齐参数后调用 TaskGroup::AddTask(...)。 - (void)object; -} -``` +## 参数 + +- `task` - 要加入任务组的任务对象。 +- `func` - 要包装成 lambda 任务的可调用对象。 +- `priority` - lambda 任务的优先级。 + +## 返回值 + +- 返回任务在当前任务组内的索引式 ID。 + +## 当前实现限制 + +- 当前只把任务放进 `TaskGroup` 内部数组,不会提交到 [TaskSystem](../TaskSystem/TaskSystem.md) 队列。 +- `task.release()` 之后,任务组接管的是裸指针,但当前析构函数不会释放这些对象。 +- `pendingDepCount` 是在节点尚未添加依赖时按 `dependencies.size()` 计算的,因此始终初始化为 `0`。 +- 当前不会在这里更新任务状态,也不会触发任何执行逻辑。 +- 返回的任务 ID 仅是组内索引,不是 [ITask::GetId](../Task/GetId.md) 那种系统级任务 ID。 + +## 设计说明 + +把“组内任务 ID”和“系统任务 ID”分开,本来是合理设计。前者适合描述组内依赖,后者适合给全局调度器跟踪任务。 + +但当前实现只完成了最外层接口形状,还没有把这两套标识真正贯通起来。 ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [AddDependency](AddDependency.md) +- [ITask](../Task/Task.md) +- [LambdaTask](../LambdaTask/LambdaTask.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/Cancel.md b/docs/api/XCEngine/Threading/TaskGroup/Cancel.md index 9091442a..2829e7b5 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/Cancel.md +++ b/docs/api/XCEngine/Threading/TaskGroup/Cancel.md @@ -1,30 +1,44 @@ # TaskGroup::Cancel -判断当前条件下是否可执行。 +取消任务组中的未完成任务。 ```cpp void Cancel(); ``` -该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会: -**返回:** `void` - 无返回值。 +1. 加锁。 +2. 把 `m_canceled` 设为 `true`。 +3. 遍历 `m_tasks`。 +4. 对每个 `task != nullptr` 且 `completed == false` 的节点调用 `task->OnCancel()`。 -**示例:** +## 返回值 -```cpp -#include +- 无。 -void Example() { - XCEngine::Threading::TaskGroup object; - // 根据上下文补齐参数后调用 TaskGroup::Cancel(...)。 - (void)object; -} -``` +## 当前实现限制 + +- 当前不会把任务状态改成 `TaskStatus::Canceled`。 +- 当前不会减少 `m_pendingCount`,因此也不会让 [Wait](Wait.md) / [IsComplete](IsComplete.md) 表现为“任务组结束了”。 +- 当前不会通知条件变量。 +- 当前不会释放任务对象。 +- `OnCancel()` 是在任务组内部锁保护下调用的;如果回调里再次操作同一个 `TaskGroup`,可能引入重入问题。 + +## 设计说明 + +真正可用的取消语义通常至少要覆盖三件事: + +- 阻止尚未开始的任务继续进入执行。 +- 让等待方得到确定的结束信号。 +- 让任务对象生命周期仍然可控。 + +当前实现只覆盖了“通知任务自己被取消”这一层。 ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [Wait](Wait.md) +- [ITask::OnCancel](../Task/OnCancel.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/Constructor.md b/docs/api/XCEngine/Threading/TaskGroup/Constructor.md index 510b2290..0c2d0c22 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/Constructor.md +++ b/docs/api/XCEngine/Threading/TaskGroup/Constructor.md @@ -1,28 +1,32 @@ -# TaskGroup::TaskGroup() +# TaskGroup::TaskGroup -构造对象。 +构造一个空的任务组。 ```cpp TaskGroup(); ``` -该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前构造函数是默认实现,主要完成以下初始化: -**返回:** `void` - 无返回值。 +- `m_tasks` 为空。 +- `m_pendingCount` 初始为 `0`。 +- `m_completedCount` 初始为 `0`。 +- `m_canceled` 初始为 `false`。 -**示例:** +此时 [IsComplete](IsComplete.md) 会返回 `true`,因为空任务组的 `m_pendingCount == 0`。 -```cpp -#include +## 返回值 -void Example() { - XCEngine::Threading::TaskGroup object; -} -``` +- 无。 + +## 注意事项 + +- 构造任务组本身不会把它注册到 [TaskSystem](../TaskSystem/TaskSystem.md);只有 [TaskSystem::CreateTaskGroup](../TaskSystem/CreateTaskGroup.md) 会维护系统内部的任务组列表。 +- 当前对象刚创建时虽然“已完成”,但这不代表它具备完整的任务栅栏语义,只是计数器碰巧为零。 ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [TaskSystem::CreateTaskGroup](../TaskSystem/CreateTaskGroup.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/Destructor.md b/docs/api/XCEngine/Threading/TaskGroup/Destructor.md index c6270dca..a5d5e74c 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/Destructor.md +++ b/docs/api/XCEngine/Threading/TaskGroup/Destructor.md @@ -1,29 +1,32 @@ -# TaskGroup::~TaskGroup() +# TaskGroup::~TaskGroup -销毁对象并释放相关资源。 +销毁任务组对象。 ```cpp ~TaskGroup(); ``` -该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前析构函数是默认实现,不包含额外清理逻辑。 -**返回:** `void` - 无返回值。 +## 返回值 -**示例:** +- 无。 -```cpp -#include +## 当前实现限制 -void Example() { - XCEngine::Threading::TaskGroup object; - // 对象离开作用域时会自动触发析构。 -} -``` +- 当前不会释放 [AddTask](AddTask.md) 存入的裸任务指针。 +- 如果你通过 `AddTask(std::unique_ptr)` 添加了任务,`TaskGroup` 会在添加时 `release()` 掉 `unique_ptr` 所有权,而析构时又不回收,这会导致泄漏。 +- 当前析构也不会自动调用 [Cancel](Cancel.md) 或 [Wait](Wait.md)。 + +## 使用建议 + +- 如果任务组来自 [TaskSystem::CreateTaskGroup](../TaskSystem/CreateTaskGroup.md),应通过 [TaskSystem::DestroyTaskGroup](../TaskSystem/DestroyTaskGroup.md) 销毁其外层所有权。 +- 但即便如此,当前任务对象自身的所有权问题仍然存在,`DestroyTaskGroup()` 也无法补救 `TaskGroup` 内部已经泄漏的裸指针。 ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [AddTask](AddTask.md) +- [TaskSystem::DestroyTaskGroup](../TaskSystem/DestroyTaskGroup.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/GetProgress.md b/docs/api/XCEngine/Threading/TaskGroup/GetProgress.md index dcba9d5f..f9b99edf 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/GetProgress.md +++ b/docs/api/XCEngine/Threading/TaskGroup/GetProgress.md @@ -1,30 +1,32 @@ # TaskGroup::GetProgress -获取相关状态或对象。 +返回任务组当前完成进度。 ```cpp float GetProgress() const; ``` -该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现逻辑是: -**返回:** `float` - 返回值语义详见头文件声明。 +- 如果任务总数为 `0`,返回 `1.0f`。 +- 否则返回 `m_completedCount / m_tasks.size()`。 -**示例:** +## 返回值 -```cpp -#include +- 取值范围目标上应在 `0.0f` 到 `1.0f` 之间。 -void Example() { - XCEngine::Threading::TaskGroup object; - // 根据上下文补齐参数后调用 TaskGroup::GetProgress(...)。 - (void)object; -} -``` +## 当前实现限制 + +- 当前源码里 `m_completedCount` 没有任何递增路径。 +- 因此: + - 空任务组返回 `1.0f` + - 只要添加过任务,当前几乎总是返回 `0.0f` +- 这个进度值当前不能反映真实执行进度。 ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [IsComplete](IsComplete.md) +- [WaitFor](WaitFor.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/IsComplete.md b/docs/api/XCEngine/Threading/TaskGroup/IsComplete.md index 45844ecd..eb6ee33d 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/IsComplete.md +++ b/docs/api/XCEngine/Threading/TaskGroup/IsComplete.md @@ -1,30 +1,32 @@ # TaskGroup::IsComplete -查询当前状态。 +查询任务组是否完成。 ```cpp bool IsComplete() const; ``` -该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 - -**返回:** `bool` - 返回值语义详见头文件声明。 - -**示例:** +当前实现直接返回: ```cpp -#include - -void Example() { - XCEngine::Threading::TaskGroup object; - // 根据上下文补齐参数后调用 TaskGroup::IsComplete(...)。 - (void)object; -} +m_pendingCount.load() == 0 ``` +## 返回值 + +- 若 `m_pendingCount` 为 `0` 则返回 `true`。 +- 否则返回 `false`。 + +## 当前实现限制 + +- 空任务组会返回 `true`。 +- 非空任务组当前通常会一直返回 `false`,因为源码里没有对应的递减逻辑。 +- 这个结果也不会考虑 [Cancel](Cancel.md) 是否已调用。 + ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [Wait](Wait.md) +- [GetProgress](GetProgress.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/SetCompleteCallback.md b/docs/api/XCEngine/Threading/TaskGroup/SetCompleteCallback.md index d6cb4916..4f799dfe 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/SetCompleteCallback.md +++ b/docs/api/XCEngine/Threading/TaskGroup/SetCompleteCallback.md @@ -1,31 +1,39 @@ # TaskGroup::SetCompleteCallback -设置相关状态或配置。 +设置任务组完成时要调用的回调函数。 ```cpp void SetCompleteCallback(Callback&& callback); ``` -该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `callback` - 参数语义详见头文件声明。 +当前实现仅在持锁状态下把回调保存到 `m_completeCallback`。 -**返回:** `void` - 无返回值。 +## 参数 -**示例:** +- `callback` - 任务组完成后期望执行的回调。 -```cpp -#include +## 返回值 -void Example() { - XCEngine::Threading::TaskGroup object; - // 根据上下文补齐参数后调用 TaskGroup::SetCompleteCallback(...)。 - (void)object; -} -``` +- 无。 + +## 当前实现限制 + +- 当前没有任何代码路径会真正调用 `m_completeCallback`。 +- 设置回调不会改变 [Wait](Wait.md)、[IsComplete](IsComplete.md) 或 [GetProgress](GetProgress.md) 的行为。 + +## 设计说明 + +这类接口在商业引擎里通常用于: + +- 任务批次完成后唤醒主线程状态机。 +- 让资源系统在异步加载收尾时投递后续工作。 + +当前这里只保留了接口入口,还没有接上“何时判定整组完成”的核心机制。 ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [IsComplete](IsComplete.md) +- [Wait](Wait.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/TaskGroup.md b/docs/api/XCEngine/Threading/TaskGroup/TaskGroup.md index 35862b8c..7625d7a5 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/TaskGroup.md +++ b/docs/api/XCEngine/Threading/TaskGroup/TaskGroup.md @@ -6,34 +6,58 @@ **头文件**: `XCEngine/Threading/TaskGroup.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `TaskGroup` public API。 +**描述**: 表示一组带依赖关系的任务集合,目标是为任务批次提供等待、进度查询和完成回调入口。 ## 概述 -`TaskGroup.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`TaskGroup` 体现的是商业引擎里很常见的一个设计方向: 把一批相关任务组织成一个“组”,然后围绕这批任务暴露: -## 声明概览 +- 批量添加任务。 +- 任务之间的依赖关系。 +- 整组完成等待。 +- 整组完成回调。 +- 进度查询与取消。 -| 声明 | 类型 | 说明 | -|------|------|------| -| `TaskGroup` | `class` | 头文件中的公开声明。 | +这种抽象本身是合理的。像 Unity 的 job fence、Unreal 的 task graph event,以及很多自研引擎里的 batch/fence/group 概念,本质上都在解决同一个问题: 上层系统往往关心“一批工作什么时候整体完成”,而不是只关心单个任务对象。 -## 公共方法 +## 当前实现边界 -| 方法 | 描述 | +当前 `TaskGroup` 还停留在骨架阶段,文档必须按源码现实理解: + +- [AddTask](AddTask.md) 会把 `std::unique_ptr` 释放成裸指针保存,但析构函数是默认实现,当前不会回收这些任务对象。 +- [AddDependency](AddDependency.md) 只记录依赖 ID,不会更新 `pendingDepCount`,也没有真正接入调度流程。 +- [Wait](Wait.md) 和 [WaitFor](WaitFor.md) 依赖 `m_pendingCount == 0`,但当前代码里这个计数只增不减。 +- [GetProgress](GetProgress.md) 依赖 `m_completedCount`,但当前没有任何路径会递增它。 +- [SetCompleteCallback](SetCompleteCallback.md) 只是保存回调,当前不会触发。 +- [Cancel](Cancel.md) 只会调用 `OnCancel()`,不会让任务组进入“已完成”状态,也不会唤醒等待者。 +- 当前 `TaskGroup` 和 [TaskSystem](../TaskSystem/TaskSystem.md) 之间没有形成真正的组调度联动。 + +因此,当前源码中的 `TaskGroup` 更像“未来任务图系统的接口草图”,而不是已经可依赖的完成态任务栅栏。 + +## 公开方法 + +| 方法 | 说明 | |------|------| -| [TaskGroup()](Constructor.md) | 构造对象。 | -| [~TaskGroup()](Destructor.md) | 销毁对象并释放相关资源。 | -| [AddTask](AddTask.md) | 添加元素或建立关联。 | -| [AddDependency](AddDependency.md) | 添加元素或建立关联。 | -| [Wait](Wait.md) | 公开方法,详见头文件声明。 | -| [WaitFor](WaitFor.md) | 公开方法,详见头文件声明。 | -| [SetCompleteCallback](SetCompleteCallback.md) | 设置相关状态或配置。 | -| [IsComplete](IsComplete.md) | 查询当前状态。 | -| [GetProgress](GetProgress.md) | 获取相关状态或对象。 | -| [Cancel](Cancel.md) | 判断当前条件下是否可执行。 | +| [Constructor](Constructor.md) | 构造一个空任务组。 | +| [Destructor](Destructor.md) | 销毁任务组对象。 | +| [AddTask](AddTask.md) | 向任务组添加一个任务或 lambda。 | +| [AddDependency](AddDependency.md) | 为任务记录依赖关系。 | +| [Wait](Wait.md) | 阻塞等待任务组完成。 | +| [WaitFor](WaitFor.md) | 限时等待任务组完成。 | +| [SetCompleteCallback](SetCompleteCallback.md) | 设置完成回调。 | +| [IsComplete](IsComplete.md) | 查询任务组是否完成。 | +| [GetProgress](GetProgress.md) | 查询完成进度。 | +| [Cancel](Cancel.md) | 取消任务组中的未完成任务。 | + +## 使用建议 + +- 如果你现在需要稳定的并发基础设施,优先使用 [Mutex](../Mutex/Mutex.md)、[SpinLock](../SpinLock/SpinLock.md)、[ReadWriteLock](../ReadWriteLock/ReadWriteLock.md) 和 [Thread](../Thread/Thread.md)。 +- 当前不要把 `TaskGroup` 当成可用的 task fence 或 job dependency graph。 +- 如果后续要把它做成商用级任务组,至少需要补齐任务所有权、依赖计数、完成通知和 `TaskSystem` 集成。 ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [ITask](../Task/Task.md) +- [TaskSystem](../TaskSystem/TaskSystem.md) +- [Synchronization And Task System Limits](../../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/Wait.md b/docs/api/XCEngine/Threading/TaskGroup/Wait.md index 58529345..374c83e8 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/Wait.md +++ b/docs/api/XCEngine/Threading/TaskGroup/Wait.md @@ -1,30 +1,32 @@ # TaskGroup::Wait -公开方法,详见头文件声明。 +阻塞当前线程,等待任务组完成。 ```cpp void Wait(); ``` -该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会等待条件变量,直到谓词 `m_pendingCount.load() == 0` 为真。 -**返回:** `void` - 无返回值。 +## 返回值 -**示例:** +- 无。 -```cpp -#include +## 当前实现限制 -void Example() { - XCEngine::Threading::TaskGroup object; - // 根据上下文补齐参数后调用 TaskGroup::Wait(...)。 - (void)object; -} -``` +- 当前源码里 `m_pendingCount` 会在 [AddTask](AddTask.md) 时递增,但没有任何代码路径会把它递减。 +- 这意味着只要任务组里添加过任务,`Wait()` 当前就不会因为正常任务完成而返回。 +- [Cancel](Cancel.md) 也不会通知条件变量,因此取消并不能唤醒这里的等待。 + +## 使用建议 + +- 当前不要在生产代码中依赖这个接口实现真正的任务组同步。 +- 如果你需要可靠同步,优先直接使用 [Thread::Join](../Thread/Join.md) 或更低层的锁/条件变量方案。 ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [WaitFor](WaitFor.md) +- [IsComplete](IsComplete.md) diff --git a/docs/api/XCEngine/Threading/TaskGroup/WaitFor.md b/docs/api/XCEngine/Threading/TaskGroup/WaitFor.md index 105afd20..9107c618 100644 --- a/docs/api/XCEngine/Threading/TaskGroup/WaitFor.md +++ b/docs/api/XCEngine/Threading/TaskGroup/WaitFor.md @@ -1,31 +1,31 @@ # TaskGroup::WaitFor -公开方法,详见头文件声明。 +在给定超时时间内等待任务组完成。 ```cpp bool WaitFor(std::chrono::milliseconds timeout); ``` -该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `timeout` - 参数语义详见头文件声明。 +当前实现使用 `condition_variable::wait_for`,等待谓词 `m_pendingCount.load() == 0`。 -**返回:** `bool` - 返回值语义详见头文件声明。 +## 参数 -**示例:** +- `timeout` - 最长等待时间。 -```cpp -#include +## 返回值 -void Example() { - XCEngine::Threading::TaskGroup object; - // 根据上下文补齐参数后调用 TaskGroup::WaitFor(...)。 - (void)object; -} -``` +- 若谓词在超时前成立则返回 `true`。 +- 否则返回 `false`。 + +## 当前实现限制 + +- 与 [Wait](Wait.md) 一样,当前 `m_pendingCount` 只增不减,因此非空任务组几乎总会超时返回 `false`。 +- [Cancel](Cancel.md) 不会通知等待者,所以取消也不会帮助 `WaitFor()` 提前结束。 ## 相关文档 -- [返回类总览](TaskGroup.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskGroup.md) +- [Wait](Wait.md) +- [GetProgress](GetProgress.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/CreateTaskGroup.md b/docs/api/XCEngine/Threading/TaskSystem/CreateTaskGroup.md index cc5ba6b8..d03884b5 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/CreateTaskGroup.md +++ b/docs/api/XCEngine/Threading/TaskSystem/CreateTaskGroup.md @@ -1,30 +1,31 @@ # TaskSystem::CreateTaskGroup -创建新对象或资源。 +创建一个新的任务组对象。 ```cpp TaskGroup* CreateTaskGroup(); ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会: -**返回:** `TaskGroup*` - 返回值语义详见头文件声明。 +1. 通过 `new TaskGroup()` 分配一个任务组。 +2. 在 `m_groupMutex` 保护下把该指针加入 `m_taskGroups`。 +3. 返回这个裸指针。 -**示例:** +## 返回值 -```cpp -#include +- 新创建的 `TaskGroup*`。 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::CreateTaskGroup(...)。 - (void)object; -} -``` +## 当前实现限制 + +- 当前只是在系统内部登记这个指针,并没有让任务组自动接入任务调度。 +- 返回裸指针意味着所有权由调用方显式管理。 +- 当前 [Shutdown](Shutdown.md) 不会自动销毁这些任务组。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [TaskGroup](../TaskGroup/TaskGroup.md) +- [DestroyTaskGroup](DestroyTaskGroup.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/DestroyTaskGroup.md b/docs/api/XCEngine/Threading/TaskSystem/DestroyTaskGroup.md index f871c70c..cac0f662 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/DestroyTaskGroup.md +++ b/docs/api/XCEngine/Threading/TaskSystem/DestroyTaskGroup.md @@ -1,31 +1,35 @@ # TaskSystem::DestroyTaskGroup -公开方法,详见头文件声明。 +销毁一个由任务系统创建的任务组。 ```cpp void DestroyTaskGroup(TaskGroup* group); ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `group` - 参数语义详见头文件声明。 +当前实现会: -**返回:** `void` - 无返回值。 +1. 若 `group == nullptr`,直接返回。 +2. 在 `m_groupMutex` 保护下,从 `m_taskGroups` 中查找并移除该指针。 +3. 在锁外执行 `delete group`。 -**示例:** +## 参数 -```cpp -#include +- `group` - 要销毁的任务组。 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::DestroyTaskGroup(...)。 - (void)object; -} -``` +## 返回值 + +- 无。 + +## 当前实现限制 + +- 当前不会先 [Cancel](../TaskGroup/Cancel.md) 或 [Wait](../TaskGroup/Wait.md)。 +- 若任务组内部已有通过 [TaskGroup::AddTask](../TaskGroup/AddTask.md) 存进去的任务对象,`delete group` 也不会释放这些裸任务指针。 +- 如果传入的指针不在 `m_taskGroups` 列表里,当前实现仍会直接 `delete group`。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [CreateTaskGroup](CreateTaskGroup.md) +- [TaskGroup](../TaskGroup/TaskGroup.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/Get.md b/docs/api/XCEngine/Threading/TaskSystem/Get.md index f5b79688..0cf6e3b9 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/Get.md +++ b/docs/api/XCEngine/Threading/TaskSystem/Get.md @@ -1,29 +1,30 @@ # TaskSystem::Get -获取相关状态或对象。 +取得全局任务系统单例。 ```cpp static TaskSystem& Get(); ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 - -**返回:** `TaskSystem&` - 返回值语义详见头文件声明。 - -**示例:** +当前实现返回一个函数内静态对象: ```cpp -#include - -void Example() { - auto& instance = XCEngine::Threading::TaskSystem::Get(); - (void)instance; -} +static TaskSystem instance; ``` +## 返回值 + +- `TaskSystem` 的全局唯一实例引用。 + +## 注意事项 + +- 取得实例并不会自动调用 [Initialize](Initialize.md)。 +- 由于构造函数和析构函数是私有的,外部只能通过这个入口访问任务系统。 +- 当前单例持有线程、队列和任务组列表,因此生命周期等同于整个进程内的静态对象生命周期。 + ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [Initialize](Initialize.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/GetWorkerThreadCount.md b/docs/api/XCEngine/Threading/TaskSystem/GetWorkerThreadCount.md index fb68628d..175e6735 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/GetWorkerThreadCount.md +++ b/docs/api/XCEngine/Threading/TaskSystem/GetWorkerThreadCount.md @@ -1,30 +1,25 @@ # TaskSystem::GetWorkerThreadCount -获取相关状态或对象。 +返回当前记录的工作线程数。 ```cpp uint32_t GetWorkerThreadCount() const; ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现直接返回成员 `m_workerThreadCount`。 -**返回:** `uint32_t` - 返回值语义详见头文件声明。 +## 返回值 -**示例:** +- 当前配置的工作线程数量。 -```cpp -#include +## 注意事项 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::GetWorkerThreadCount(...)。 - (void)object; -} -``` +- 在 [Initialize](Initialize.md) 之前,这个值默认是 `0`。 +- 这个值表示“初始化时决定的目标线程数”,不表示当前仍然活跃的线程数量。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [Initialize](Initialize.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/Initialize.md b/docs/api/XCEngine/Threading/TaskSystem/Initialize.md index 94d170c2..0d979e6f 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/Initialize.md +++ b/docs/api/XCEngine/Threading/TaskSystem/Initialize.md @@ -1,31 +1,39 @@ # TaskSystem::Initialize -初始化内部状态。 +初始化任务系统并创建工作线程。 ```cpp void Initialize(const TaskSystemConfig& config); ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `config` - 参数语义详见头文件声明。 +当前实现会: -**返回:** `void` - 无返回值。 +1. 从 `config.workerThreadCount` 读取目标线程数。 +2. 当该值为 `0` 时,退回到 `std::thread::hardware_concurrency()`。 +3. 若仍为 `0`,最终使用 `2`。 +4. 把 `m_running` 设为 `true`。 +5. 启动对应数量的 `std::thread`,每个线程执行内部 `WorkerThread()` 循环。 -**示例:** +## 参数 -```cpp -#include +- `config` - 任务系统初始化配置。 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::Initialize(...)。 - (void)object; -} -``` +## 返回值 + +- 无。 + +## 当前实现限制 + +- 当前只真正使用 `workerThreadCount`,其余配置字段都会被忽略。 +- 当前没有防止重复初始化的保护;多次调用会继续往 `m_workerThreads` 里追加线程。 +- 当前不会把 `m_shutdown` 重置回 `false`,因此一旦执行过 [Shutdown](Shutdown.md),再次 `Initialize()` 的行为是不完整的。 +- 当前不会清空历史队列或主线程回调队列。 +- 当前不会给工作线程命名,也没有线程绑定、栈大小或亲和性设置。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [TaskSystemConfig](../TaskSystemConfig/TaskSystemConfig.md) +- [Shutdown](Shutdown.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/ParallelFor.md b/docs/api/XCEngine/Threading/TaskSystem/ParallelFor.md index cc3b8319..4d1890ee 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/ParallelFor.md +++ b/docs/api/XCEngine/Threading/TaskSystem/ParallelFor.md @@ -1,33 +1,54 @@ # TaskSystem::ParallelFor -公开方法,详见头文件声明。 +把一个整数区间拆分成多个任务并提交执行。 ```cpp -template void ParallelFor(int32_t start, int32_t end, Func&& func); +template +void ParallelFor(int32_t start, int32_t end, Func&& func); ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `start` - 参数语义详见头文件声明。 -- `end` - 参数语义详见头文件声明。 -- `func` - 参数语义详见头文件声明。 +当前模板实现会: -**返回:** `template void` - 返回值语义详见头文件声明。 +1. 计算区间长度 `count = end - start`。 +2. 若 `count <= 0`,直接返回。 +3. 用 `std::thread::hardware_concurrency()` 决定分片数量;若返回 `0`,回退到 `2`。 +4. 按 `(count + numThreads - 1) / numThreads` 计算块大小。 +5. 为每个分片构造一个高优先级 lambda 任务。 +6. 逐个调用 [Submit](Submit.md) 提交这些任务。 -**示例:** +## 参数 -```cpp -#include +- `start` - 起始索引,包含。 +- `end` - 结束索引,不包含。 +- `func` - 对区间内每个索引执行的可调用对象。 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::ParallelFor(...)。 - (void)object; -} -``` +## 返回值 + +- 无。 + +## 当前实现限制 + +- 当前函数提交完任务后立即返回,不会等待所有分片完成。 +- 当前按硬件并发数分片,而不是按 [Initialize](Initialize.md) 配置的工作线程数分片。 +- 当前头文件里模板使用了 `LambdaTask` 和 `std::min`,但 `TaskSystem.h` 自身没有包含 `LambdaTask.h` 和 ``;如果只包含这个头,模板实例化可能失败。 +- 当前底层仍然依赖 [Submit](Submit.md),因此会继承任务生命周期悬空指针问题。 +- 当 `numThreads > count` 时,会提交一些空分片任务。 + +## 设计说明 + +商业级 `ParallelFor` 通常至少还需要: + +- 同步栅栏或等待句柄。 +- 更合理的分块策略。 +- 工作窃取或局部队列。 +- 对小任务的过度拆分抑制。 + +当前版本更接近“把并行循环 API 形状先搭出来”。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [Submit](Submit.md) +- [Synchronization And Task System Limits](../../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/RunOnMainThread.md b/docs/api/XCEngine/Threading/TaskSystem/RunOnMainThread.md index 6bbb24d5..5d2120c7 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/RunOnMainThread.md +++ b/docs/api/XCEngine/Threading/TaskSystem/RunOnMainThread.md @@ -1,31 +1,31 @@ # TaskSystem::RunOnMainThread -公开方法,详见头文件声明。 +把一个回调排入主线程执行队列。 ```cpp void RunOnMainThread(std::function&& func); ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `func` - 参数语义详见头文件声明。 +当前实现会在 `m_queueMutex` 保护下把回调追加到 `m_mainThreadQueue`。 -**返回:** `void` - 无返回值。 +这些回调不会立即执行,而是等待 [Update](Update.md) 被调用时再统一消费。 -**示例:** +## 参数 -```cpp -#include +- `func` - 需要在主线程执行的回调。 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::RunOnMainThread(...)。 - (void)object; -} -``` +## 返回值 + +- 无。 + +## 注意事项 + +- 当前实现本身不检查调用线程是否为主线程;“主线程”只是通过谁来调用 [Update](Update.md) 约定出来的。 +- 当前没有队列容量限制,也没有通知等待主线程的机制。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [Update](Update.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/Shutdown.md b/docs/api/XCEngine/Threading/TaskSystem/Shutdown.md index b31489b4..3fc2742e 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/Shutdown.md +++ b/docs/api/XCEngine/Threading/TaskSystem/Shutdown.md @@ -1,30 +1,45 @@ # TaskSystem::Shutdown -关闭并清理内部状态。 +关闭任务系统并回收工作线程。 ```cpp void Shutdown(); ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会: -**返回:** `void` - 无返回值。 +1. 把 `m_running` 设为 `false`。 +2. 把 `m_shutdown` 设为 `true`。 +3. `notify_all()` 唤醒等待任务的工作线程。 +4. 逐个 `join()` 仍然可连接的工作线程。 +5. 清空 `m_workerThreads`。 -**示例:** +## 返回值 -```cpp -#include +- 无。 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::Shutdown(...)。 - (void)object; -} -``` +## 当前实现限制 + +- 当前不会清空 `m_taskQueue`,未执行的任务会被直接遗留。 +- 当前不会释放队列中残留任务对应的对象。 +- 当前不会销毁已经通过 [CreateTaskGroup](CreateTaskGroup.md) 创建的任务组。 +- 当前不会清空 `m_mainThreadQueue`。 +- `m_shutdown` 会一直保持为 `true`,这使得重新初始化路径当前不可用。 + +## 设计说明 + +商业级任务系统的关闭通常需要定义明确的 shutdown policy,例如: + +- 等待现有任务自然跑完。 +- 取消可取消任务并清理资源。 +- 强制丢弃队列但保证对象生命周期可回收。 + +当前实现只覆盖了“停线程”这一步。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [Initialize](Initialize.md) +- [Submit](Submit.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/Submit.md b/docs/api/XCEngine/Threading/TaskSystem/Submit.md index 2be6c3d6..41081d72 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/Submit.md +++ b/docs/api/XCEngine/Threading/TaskSystem/Submit.md @@ -1,45 +1,57 @@ # TaskSystem::Submit -公开方法,详见头文件声明。 - -该方法在 `XCEngine/Threading/TaskSystem.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。 - -## 重载 1: 声明 +提交一个任务对象或 lambda 到任务系统。 ```cpp uint64_t Submit(std::unique_ptr task); -``` - -**参数:** -- `task` - 参数语义详见头文件声明。 - -**返回:** `uint64_t` - 返回值语义详见头文件声明。 - -## 重载 2: 声明 - -```cpp uint64_t Submit(std::function&& func, TaskPriority priority = TaskPriority::Normal); ``` -**参数:** -- `func` - 参数语义详见头文件声明。 -- `priority` - 参数语义详见头文件声明。 +## 行为说明 -**返回:** `uint64_t` - 返回值语义详见头文件声明。 +`Submit(std::unique_ptr)` 当前会: -**示例:** +1. 若 `task == nullptr`,直接返回 `0`。 +2. 递增 `m_nextTaskId` 生成新 ID。 +3. 调用 `task->SetId(taskId)`。 +4. 用 `task.get()` 构造 `TaskWrapper`。 +5. 在 `m_queueMutex` 保护下把 `TaskWrapper` 压入优先级队列。 +6. 唤醒一个工作线程。 +7. 返回任务 ID。 -```cpp -#include +`Submit(std::function&&, TaskPriority)` 会先 `new LambdaTask>`,再把它包装成 `std::unique_ptr` 转发给另一个重载。 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::Submit(...)。 - (void)object; -} -``` +## 参数 + +- `task` - 要提交的任务对象。 +- `func` - 要包装成任务的可调用对象。 +- `priority` - lambda 任务优先级。 + +## 返回值 + +- 成功路径返回新分配的任务 ID。 +- 当 `task == nullptr` 时返回 `0`。 + +## 当前实现风险 + +- 当前函数把 `task.get()` 压入队列后,没有 `release()` 也没有额外 `AddRef()`。 +- 因此 `unique_ptr` 会在函数返回时销毁任务对象,但队列里仍保留裸指针。 +- 工作线程稍后执行 [ExecuteTask](TaskSystem.md) 路径时,面对的是悬空指针,随后还会调用 `Release()`,这是严重的未定义行为。 +- 当前提交时不会把任务状态改成 `TaskStatus::Scheduled`。 +- 当前不会检查系统是否已经 [Shutdown](Shutdown.md)。 + +## 设计说明 + +商用级任务系统最关键的不是“能把指针塞进队列”,而是任务生命周期必须绝对正确。常见做法一般是: + +- 队列直接持有智能指针。 +- 或者统一使用 intrusive ref-count,并在入队、出队、执行、完成的每个阶段严格平衡引用。 + +当前实现的问题就在于这条最基本的生命周期链路还没有闭合。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [ITask](../Task/Task.md) +- [LambdaTask](../LambdaTask/LambdaTask.md) +- [Wait](Wait.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/TaskSystem.md b/docs/api/XCEngine/Threading/TaskSystem/TaskSystem.md index 405e2a0e..a90cd2f4 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/TaskSystem.md +++ b/docs/api/XCEngine/Threading/TaskSystem/TaskSystem.md @@ -6,35 +6,72 @@ **头文件**: `XCEngine/Threading/TaskSystem.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `TaskSystem` public API。 +**描述**: 提供全局任务调度入口、工作线程池、主线程回调队列以及任务组创建接口。 ## 概述 -`TaskSystem.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`TaskSystem` 想解决的是“把零散后台工作统一交给一套中央调度器管理”这个问题。它当前暴露的 API 形状已经覆盖了商用引擎任务系统常见的几个入口: -## 声明概览 +- 单例式全局访问。 +- 工作线程池初始化与关闭。 +- 按优先级提交任务。 +- 批量任务入口 `ParallelFor()`。 +- 任务组创建与销毁。 +- 回投主线程的回调队列。 -| 声明 | 类型 | 说明 | -|------|------|------| -| `TaskSystem` | `class` | 头文件中的公开声明。 | +这种设计方向本身是对的。商业级引擎很少要求上层系统自己手搓 `std::thread`,而是倾向于通过中央 job system 统一调度、限流、统计和同步。 -## 公共方法 +## 当前实现边界 -| 方法 | 描述 | +当前 `TaskSystem` 仍然明显处于原型阶段,尤其要注意以下事实: + +- [Submit](Submit.md) 当前存在严重生命周期问题: 任务指针被压入队列后,对应 `unique_ptr` 却会在函数返回时销毁对象,导致队列中留下悬空指针。 +- 工作线程取任务时,`GetNextTask()` 访问 `m_taskQueue` 没有使用与入队一致的 `m_queueMutex`,当前存在未同步并发访问。 +- [Wait](Wait.md) 还是空实现。 +- [ParallelFor](ParallelFor.md) 会立即返回,不会等待所有分片完成。 +- [Initialize](Initialize.md) 只真正使用了 `TaskSystemConfig::workerThreadCount`,其余配置项当前都被忽略。 +- [Shutdown](Shutdown.md) 之后 `m_shutdown` 不会恢复为 `false`,重新初始化路径当前基本不可用。 +- [TaskGroup](../TaskGroup/TaskGroup.md) 创建出来后,只是被登记到列表里,并没有接入任务执行与完成统计。 + +因此,当前 `TaskSystem` 不应被当成商业级 job system 使用。更准确的定位是: API 轮廓已经出现,但核心正确性还没有收敛。 + +## 公开方法 + +| 方法 | 说明 | |------|------| -| [Get](Get.md) | 获取相关状态或对象。 | -| [Initialize](Initialize.md) | 初始化内部状态。 | -| [Shutdown](Shutdown.md) | 关闭并清理内部状态。 | -| [Submit](Submit.md) | 公开方法,详见头文件声明。 | -| [CreateTaskGroup](CreateTaskGroup.md) | 创建新对象或资源。 | -| [DestroyTaskGroup](DestroyTaskGroup.md) | 公开方法,详见头文件声明。 | -| [Wait](Wait.md) | 公开方法,详见头文件声明。 | -| [GetWorkerThreadCount](GetWorkerThreadCount.md) | 获取相关状态或对象。 | -| [Update](Update.md) | 更新运行时状态。 | -| [ParallelFor](ParallelFor.md) | 公开方法,详见头文件声明。 | -| [RunOnMainThread](RunOnMainThread.md) | 公开方法,详见头文件声明。 | +| [Get](Get.md) | 取得全局单例实例。 | +| [Initialize](Initialize.md) | 初始化工作线程池。 | +| [Shutdown](Shutdown.md) | 停止工作线程并关闭系统。 | +| [Submit](Submit.md) | 提交一个任务对象或 lambda。 | +| [CreateTaskGroup](CreateTaskGroup.md) | 创建任务组。 | +| [DestroyTaskGroup](DestroyTaskGroup.md) | 销毁任务组。 | +| [Wait](Wait.md) | 等待指定任务完成。 | +| [GetWorkerThreadCount](GetWorkerThreadCount.md) | 查询当前配置的工作线程数。 | +| [Update](Update.md) | 执行主线程回调队列。 | +| [ParallelFor](ParallelFor.md) | 把区间拆成多个高优先级任务提交。 | +| [RunOnMainThread](RunOnMainThread.md) | 把回调排入主线程队列。 | + +## 设计说明 + +为什么引擎仍然需要这样的中心化系统,而不是到处直接开线程: + +- 线程数量需要统一治理,否则很容易过量创建后台线程。 +- 优先级、主线程回投、profiling 和依赖图等能力,通常都需要一个公共调度中心。 +- 资源加载、脚本预处理、导航构建、烘焙和编辑器后台任务,往往都需要共享同一套任务基础设施。 + +这也是为什么很多商业引擎会把“线程原语”和“任务系统”都保留下来: + +- 锁和线程解决底层同步与平台适配问题。 +- 任务系统解决更高层的批处理、吞吐量和生命周期协调问题。 + +## 使用建议 + +- 当前源码中,低层同步原语比 `TaskSystem` 更成熟。 +- 如果确实要继续推进这个模块,优先修正任务所有权、队列同步、等待语义和关闭语义,再谈 profiling、work stealing 或任务依赖图。 ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [TaskSystemConfig](../TaskSystemConfig/TaskSystemConfig.md) +- [TaskGroup](../TaskGroup/TaskGroup.md) +- [Synchronization And Task System Limits](../../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/Update.md b/docs/api/XCEngine/Threading/TaskSystem/Update.md index 85922702..83910f55 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/Update.md +++ b/docs/api/XCEngine/Threading/TaskSystem/Update.md @@ -1,30 +1,34 @@ # TaskSystem::Update -更新运行时状态。 +执行当前积压的主线程回调。 ```cpp void Update(); ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会: -**返回:** `void` - 无返回值。 +1. 在 `m_queueMutex` 保护下把 `m_mainThreadQueue` 整体移动到局部数组。 +2. 清空内部队列。 +3. 在锁外按顺序执行这些回调。 -**示例:** +## 返回值 -```cpp -#include +- 无。 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::Update(...)。 - (void)object; -} -``` +## 设计说明 + +这是一种典型的“后台线程投递,主线程集中消费”模型。商业引擎里资源系统、脚本系统和编辑器工具都经常需要这种回投路径,因为很多对象只能在主线程安全访问。 + +## 当前实现限制 + +- 当前不会自动调用,需要调用方在主线程帧循环里显式执行。 +- `m_mainThreadCondition` 当前没有被使用。 +- 当前没有异常隔离;某个回调抛出异常时,会中断后续回调执行路径。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [RunOnMainThread](RunOnMainThread.md) diff --git a/docs/api/XCEngine/Threading/TaskSystem/Wait.md b/docs/api/XCEngine/Threading/TaskSystem/Wait.md index 0562871a..157f2181 100644 --- a/docs/api/XCEngine/Threading/TaskSystem/Wait.md +++ b/docs/api/XCEngine/Threading/TaskSystem/Wait.md @@ -1,31 +1,36 @@ # TaskSystem::Wait -公开方法,详见头文件声明。 +等待指定任务完成。 ```cpp void Wait(uint64_t taskId); ``` -该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `taskId` - 参数语义详见头文件声明。 +当前实现是一个空函数体,参数 `taskId` 也没有被使用。 -**返回:** `void` - 无返回值。 +## 参数 -**示例:** +- `taskId` - 目标任务 ID。 -```cpp -#include +## 返回值 -void Example() { - XCEngine::Threading::TaskSystem object; - // 根据上下文补齐参数后调用 TaskSystem::Wait(...)。 - (void)object; -} -``` +- 无。 + +## 当前实现限制 + +- 当前不会阻塞。 +- 当前不会轮询任务状态。 +- 当前不会配合条件变量、future 或任务组做任何同步。 + +## 使用建议 + +- 当前不要依赖这个接口实现任务完成等待。 +- 如果后续要把它补成可用接口,至少需要有一个以任务 ID 为键的完成状态表或句柄系统。 ## 相关文档 -- [返回类总览](TaskSystem.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](TaskSystem.md) +- [Submit](Submit.md) +- [TaskGroup::Wait](../TaskGroup/Wait.md) diff --git a/docs/api/XCEngine/Threading/TaskSystemConfig/TaskSystemConfig.md b/docs/api/XCEngine/Threading/TaskSystemConfig/TaskSystemConfig.md index 9eb3f09e..e54bd04a 100644 --- a/docs/api/XCEngine/Threading/TaskSystemConfig/TaskSystemConfig.md +++ b/docs/api/XCEngine/Threading/TaskSystemConfig/TaskSystemConfig.md @@ -6,29 +6,29 @@ **头文件**: `XCEngine/Threading/TaskSystemConfig.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `TaskSystemConfig` public API。 +**描述**: 描述 `TaskSystem` 初始化参数的配置结构体。 ## 概述 -`TaskSystemConfig.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`TaskSystemConfig` 的字段形状已经有了商用任务系统常见的雏形:工作线程数、任务窃取、任务队列上限、profiling 开关和线程栈大小。 -## 声明概览 +但需要注意的是,当前真正被 `TaskSystem::Initialize()` 使用的只有 `workerThreadCount`。 -| 声明 | 类型 | 说明 | -|------|------|------| -| `TaskSystemConfig` | `struct` | 头文件中的公开声明。 | +## 字段 -## 结构体成员 +| 字段 | 类型 | 默认值 | 当前作用 | +|------|------|--------|----------| +| `workerThreadCount` | `uint32_t` | `0` | 已使用;`0` 时回退到 `std::thread::hardware_concurrency()` | +| `enableTaskProfiling` | `bool` | `true` | 当前未使用 | +| `stealTasks` | `bool` | `true` | 当前未使用 | +| `maxTaskQueueSize` | `uint32_t` | `1024` | 当前未使用 | +| `threadStackSize` | `uint32_t` | `0` | 当前未使用 | -| 成员 | 类型 | 描述 | 默认值 | -|------|------|------|--------| -| `workerThreadCount` | `uint32_t` | 结构体公开字段。 | `0` | -| `enableTaskProfiling` | `bool` | 结构体公开字段。 | `true` | -| `stealTasks` | `bool` | 结构体公开字段。 | `true` | -| `maxTaskQueueSize` | `uint32_t` | 结构体公开字段。 | `1024` | -| `threadStackSize` | `uint32_t` | 结构体公开字段。 | `0` | +## 设计说明 + +这说明 `TaskSystem` 目前更接近“先把 API 形状搭出来”,而不是已经把所有调度策略和平台细节真正接上。 ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [TaskSystem](../TaskSystem/TaskSystem.md) diff --git a/docs/api/XCEngine/Threading/Thread/Constructor.md b/docs/api/XCEngine/Threading/Thread/Constructor.md index f3ceb073..811c9c08 100644 --- a/docs/api/XCEngine/Threading/Thread/Constructor.md +++ b/docs/api/XCEngine/Threading/Thread/Constructor.md @@ -1,28 +1,24 @@ -# Thread::Thread() +# Thread::Constructor -构造对象。 +构造一个空线程包装对象。 ```cpp Thread(); ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现是默认构造,不会启动线程。初始状态下: -**返回:** `void` - 无返回值。 +- `m_id == 0` +- `m_name` 为空 +- `m_thread` 不可 join -**示例:** +## 返回值 -```cpp -#include - -void Example() { - XCEngine::Threading::Thread object; -} -``` +- 无。 ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [Start](Start.md) diff --git a/docs/api/XCEngine/Threading/Thread/Destructor.md b/docs/api/XCEngine/Threading/Thread/Destructor.md index 486d4537..89f22d63 100644 --- a/docs/api/XCEngine/Threading/Thread/Destructor.md +++ b/docs/api/XCEngine/Threading/Thread/Destructor.md @@ -1,29 +1,26 @@ -# Thread::~Thread() +# Thread::Destructor -销毁对象并释放相关资源。 +销毁线程包装对象。 ```cpp ~Thread(); ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会在 `m_thread.joinable()` 时自动调用 `m_thread.join()`。 -**返回:** `void` - 无返回值。 +## 返回值 -**示例:** +- 无。 -```cpp -#include +## 注意事项 -void Example() { - XCEngine::Threading::Thread object; - // 对象离开作用域时会自动触发析构。 -} -``` +- 这意味着析构可能阻塞直到线程函数结束。 +- 如果你希望线程独立运行而不在析构时阻塞,应先显式调用 [Detach](Detach.md)。 ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [Join](Join.md) +- [Detach](Detach.md) diff --git a/docs/api/XCEngine/Threading/Thread/Detach.md b/docs/api/XCEngine/Threading/Thread/Detach.md index 41e68753..e602f693 100644 --- a/docs/api/XCEngine/Threading/Thread/Detach.md +++ b/docs/api/XCEngine/Threading/Thread/Detach.md @@ -1,30 +1,24 @@ # Thread::Detach -公开方法,详见头文件声明。 +分离线程。 ```cpp void Detach(); ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会在 `m_thread.joinable()` 时调用 `m_thread.detach()`;否则什么也不做。 -**返回:** `void` - 无返回值。 +## 返回值 -**示例:** +- 无。 -```cpp -#include +## 注意事项 -void Example() { - XCEngine::Threading::Thread object; - // 根据上下文补齐参数后调用 Thread::Detach(...)。 - (void)object; -} -``` +- 一旦分离,线程执行与 `Thread` 对象生命周期脱钩,之后析构不会再 `Join()` 这条线程。 ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [Join](Join.md) diff --git a/docs/api/XCEngine/Threading/Thread/GetCurrentId.md b/docs/api/XCEngine/Threading/Thread/GetCurrentId.md index 118f4427..bdeb802f 100644 --- a/docs/api/XCEngine/Threading/Thread/GetCurrentId.md +++ b/docs/api/XCEngine/Threading/Thread/GetCurrentId.md @@ -1,30 +1,28 @@ # Thread::GetCurrentId -获取相关状态或对象。 +获取当前线程标识。 ```cpp static Id GetCurrentId(); ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会: -**返回:** `Id` - 返回值语义详见头文件声明。 +1. 获取 `std::this_thread::get_id()` +2. 通过 `std::hash` 求 hash +3. 把结果转成 `Id` -**示例:** +## 返回值 -```cpp -#include +- `Id` - 当前线程的 hash 化标识值。 -void Example() { - XCEngine::Threading::Thread object; - // 根据上下文补齐参数后调用 Thread::GetCurrentId(...)。 - (void)object; -} -``` +## 注意事项 + +- 这个值不是 [GetId](GetId.md) 所用的 `native_handle()` 转换结果,因此两者不是统一编码。 ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [GetId](GetId.md) diff --git a/docs/api/XCEngine/Threading/Thread/GetId.md b/docs/api/XCEngine/Threading/Thread/GetId.md index cec3bdd2..74f44646 100644 --- a/docs/api/XCEngine/Threading/Thread/GetId.md +++ b/docs/api/XCEngine/Threading/Thread/GetId.md @@ -1,30 +1,26 @@ # Thread::GetId -获取相关状态或对象。 +获取缓存的线程标识。 ```cpp Id GetId() const; ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前头文件内联实现直接返回 `m_id`。 -**返回:** `Id` - 返回值语义详见头文件声明。 +这个值只在 [Start](Start.md) 里更新,来源是 `native_handle()` 转成整数。 -**示例:** +## 返回值 -```cpp -#include +- `Id` - 当前缓存的线程标识;尚未启动时通常为 `0`。 -void Example() { - XCEngine::Threading::Thread object; - // 根据上下文补齐参数后调用 Thread::GetId(...)。 - (void)object; -} -``` +## 注意事项 + +- 这个值与 [GetCurrentId](GetCurrentId.md) 的实现口径不同,不应假设两者可以直接比较。 ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [GetCurrentId](GetCurrentId.md) diff --git a/docs/api/XCEngine/Threading/Thread/GetName.md b/docs/api/XCEngine/Threading/Thread/GetName.md index 4e0b5e90..2cc31921 100644 --- a/docs/api/XCEngine/Threading/Thread/GetName.md +++ b/docs/api/XCEngine/Threading/Thread/GetName.md @@ -1,30 +1,24 @@ # Thread::GetName -获取相关状态或对象。 +获取保存的线程名称。 ```cpp const Containers::String& GetName() const; ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前头文件内联实现直接返回 `m_name` 的常量引用。 -**返回:** `const Containers::String&` - 返回值语义详见头文件声明。 +## 返回值 -**示例:** +- `const Containers::String&` - 由 [Start](Start.md) 保存下来的线程名称。 -```cpp -#include +## 注意事项 -void Example() { - XCEngine::Threading::Thread object; - // 根据上下文补齐参数后调用 Thread::GetName(...)。 - (void)object; -} -``` +- 这只是 `Thread` 对象内部保存的名称字符串,不代表 OS 级线程名一定被设置。 ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [Start](Start.md) diff --git a/docs/api/XCEngine/Threading/Thread/Join.md b/docs/api/XCEngine/Threading/Thread/Join.md index 42edec87..40ca7af9 100644 --- a/docs/api/XCEngine/Threading/Thread/Join.md +++ b/docs/api/XCEngine/Threading/Thread/Join.md @@ -1,30 +1,20 @@ # Thread::Join -公开方法,详见头文件声明。 +等待线程结束。 ```cpp void Join(); ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现会在 `m_thread.joinable()` 时调用 `m_thread.join()`;否则什么也不做。 -**返回:** `void` - 无返回值。 +## 返回值 -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::Thread object; - // 根据上下文补齐参数后调用 Thread::Join(...)。 - (void)object; -} -``` +- 无。 ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [Detach](Detach.md) diff --git a/docs/api/XCEngine/Threading/Thread/Sleep.md b/docs/api/XCEngine/Threading/Thread/Sleep.md index 831fba14..2f1ae0b6 100644 --- a/docs/api/XCEngine/Threading/Thread/Sleep.md +++ b/docs/api/XCEngine/Threading/Thread/Sleep.md @@ -1,31 +1,28 @@ # Thread::Sleep -公开方法,详见头文件声明。 +让当前线程休眠指定毫秒数。 ```cpp static void Sleep(uint32_t milliseconds); ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `milliseconds` - 参数语义详见头文件声明。 - -**返回:** `void` - 无返回值。 - -**示例:** +当前实现直接调用: ```cpp -#include - -void Example() { - XCEngine::Threading::Thread object; - // 根据上下文补齐参数后调用 Thread::Sleep(...)。 - (void)object; -} +std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); ``` +## 参数 + +- `milliseconds` - 休眠时长,单位毫秒。 + +## 返回值 + +- 无。 + ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [Yield](Yield.md) diff --git a/docs/api/XCEngine/Threading/Thread/Start.md b/docs/api/XCEngine/Threading/Thread/Start.md index 948da07c..db96caf1 100644 --- a/docs/api/XCEngine/Threading/Thread/Start.md +++ b/docs/api/XCEngine/Threading/Thread/Start.md @@ -1,32 +1,36 @@ # Thread::Start -公开方法,详见头文件声明。 +启动一个新线程。 ```cpp -template void Start(Func&& func, const Containers::String& name = "Thread"); +template +void Start(Func&& func, const Containers::String& name = "Thread"); ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** -- `func` - 参数语义详见头文件声明。 -- `name` - 参数语义详见头文件声明。 +当前模板实现会: -**返回:** `template void` - 返回值语义详见头文件声明。 +1. 把 `m_name = name` +2. 执行 `m_thread = std::thread(std::forward(func))` +3. 把 `m_thread.native_handle()` 转成整数,写入 `m_id` -**示例:** +## 参数 -```cpp -#include +- `func` - 线程入口函数或可调用对象。 +- `name` - 保存在线程包装对象中的名称;默认值为 `"Thread"`。 -void Example() { - XCEngine::Threading::Thread object; - // 根据上下文补齐参数后调用 Thread::Start(...)。 - (void)object; -} -``` +## 返回值 + +- 无。 + +## 当前实现限制 + +- 名称只保存在 `m_name`,不会设置到操作系统线程名。 +- `m_id` 是从 `native_handle()` 转换而来的缓存值,不保证跨平台可移植,也不保证与 [GetCurrentId](GetCurrentId.md) 一致。 +- 如果对一个仍然 `joinable` 的线程对象再次调用 `Start()`,会触发 `std::thread` 的终止语义。 ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [GetId](GetId.md) diff --git a/docs/api/XCEngine/Threading/Thread/Thread.md b/docs/api/XCEngine/Threading/Thread/Thread.md index 7d44879c..6e031835 100644 --- a/docs/api/XCEngine/Threading/Thread/Thread.md +++ b/docs/api/XCEngine/Threading/Thread/Thread.md @@ -6,34 +6,41 @@ **头文件**: `XCEngine/Threading/Thread.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `Thread` public API。 +**描述**: 对 `std::thread` 的轻量包装,附带名称字符串和一个缓存的线程标识值。 ## 概述 -`Thread.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`Thread` 不是线程系统,而是一个非常薄的 `std::thread` 外壳。它主要额外做了两件事: -## 声明概览 +- 保存一个 `Containers::String m_name` +- 在 `Start()` 时缓存一个 `m_id` -| 声明 | 类型 | 说明 | -|------|------|------| -| `Thread` | `class` | 头文件中的公开声明。 | +这类包装在引擎里很常见,因为很多系统希望在不直接暴露标准库类型的前提下,统一线程 API、线程名和工具层调试信息。 -## 公共方法 +## 当前实现边界 -| 方法 | 描述 | +- [Destructor](Destructor.md) 会在对象析构时自动 `Join()`,因此析构可能阻塞。 +- [Start](Start.md) 只保存名称字符串,不会设置 OS 层面的线程名。 +- [GetId](GetId.md) 的来源是 `native_handle()` 转成整数,而 [GetCurrentId](GetCurrentId.md) 的来源是 `std::thread::id` 的 hash;两者不是同一口径。 +- [Start](Start.md) 当前没有防御“对一个仍然 joinable 的线程再次 Start”的情况;这会落到 `std::thread` 的终止语义。 +- 当前没有对应单测覆盖。 + +## 公开方法 + +| 方法 | 说明 | |------|------| -| [Thread()](Constructor.md) | 构造对象。 | -| [~Thread()](Destructor.md) | 销毁对象并释放相关资源。 | -| [Start](Start.md) | 公开方法,详见头文件声明。 | -| [Join](Join.md) | 公开方法,详见头文件声明。 | -| [Detach](Detach.md) | 公开方法,详见头文件声明。 | -| [GetId](GetId.md) | 获取相关状态或对象。 | -| [GetName](GetName.md) | 获取相关状态或对象。 | -| [GetCurrentId](GetCurrentId.md) | 获取相关状态或对象。 | -| [Sleep](Sleep.md) | 公开方法,详见头文件声明。 | -| [Yield](Yield.md) | 公开方法,详见头文件声明。 | +| [Constructor](Constructor.md) | 构造空线程对象。 | +| [Destructor](Destructor.md) | 析构时自动 join。 | +| [Start](Start.md) | 启动线程。 | +| [Join](Join.md) | 等待线程结束。 | +| [Detach](Detach.md) | 分离线程。 | +| [GetId](GetId.md) | 获取缓存的线程标识。 | +| [GetName](GetName.md) | 获取保存的线程名称。 | +| [GetCurrentId](GetCurrentId.md) | 获取当前线程标识。 | +| [Sleep](Sleep.md) | 让当前线程休眠。 | +| [Yield](Yield.md) | 让出当前线程时间片。 | ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [Synchronization And Task System Limits](../../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md) diff --git a/docs/api/XCEngine/Threading/Thread/Yield.md b/docs/api/XCEngine/Threading/Thread/Yield.md index 5000839c..d0474e18 100644 --- a/docs/api/XCEngine/Threading/Thread/Yield.md +++ b/docs/api/XCEngine/Threading/Thread/Yield.md @@ -1,30 +1,20 @@ # Thread::Yield -公开方法,详见头文件声明。 +让出当前线程时间片。 ```cpp static void Yield(); ``` -该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 +## 行为说明 -**参数:** 无。 +当前实现直接调用 `std::this_thread::yield()`。 -**返回:** `void` - 无返回值。 +## 返回值 -**示例:** - -```cpp -#include - -void Example() { - XCEngine::Threading::Thread object; - // 根据上下文补齐参数后调用 Thread::Yield(...)。 - (void)object; -} -``` +- 无。 ## 相关文档 -- [返回类总览](Thread.md) -- [返回模块目录](../Threading.md) +- [返回类型总览](Thread.md) +- [Sleep](Sleep.md) diff --git a/docs/api/XCEngine/Threading/Threading.md b/docs/api/XCEngine/Threading/Threading.md index 38813e6f..17b692a8 100644 --- a/docs/api/XCEngine/Threading/Threading.md +++ b/docs/api/XCEngine/Threading/Threading.md @@ -4,11 +4,42 @@ **类型**: `module` -**描述**: 线程封装、同步原语和任务系统。 +**描述**: 提供线程封装、基础同步原语和一套早期任务系统骨架。 -## 概览 +## 概述 -该目录与 `XCEngine/Threading` 对应的 public headers 保持平行,用于承载唯一的 canonical API 文档入口。 +`XCEngine::Threading` 当前由两部分组成: + +- `Mutex`、`SpinLock`、`ReadWriteLock` 和 `Thread` 这类直接可用的并发基础设施。 +- `ITask`、`TaskGroup`、`TaskSystem` 这类面向 job system 的任务抽象。 + +这种分层很符合商业引擎常见做法:底层仍然需要明确的锁和线程封装,上层再逐步演进到任务图、主线程回调和并行 for 之类的调度模型。 + +## 当前实现成熟度 + +这一组 API 的成熟度差异很大,需要分开看: + +- `Mutex` 与 `SpinLock` 本质上是对标准库原语的薄封装,语义相对直接。 +- `ReadWriteLock` 实现了写者优先的读写锁,但没有 try-lock、升级/降级或 RAII 辅助类型。 +- `Thread` 可以封装 `std::thread` 生命周期,但线程名称只是本地字符串,不会设置 OS 线程名,而且 ID 口径与 `GetCurrentId()` 不一致。 +- `ITask` 与 `LambdaTask` 的抽象形状已经具备,但 `TaskGroup` 和 `TaskSystem` 目前仍然明显属于“骨架阶段”。 +- `TaskSystem` 当前存在严重的生命周期和同步问题,因此不能把它当成商用级 job system 使用。 + +## 设计要点 + +- 大写接口如 `Lock()` / `Unlock()` 更接近引擎自身命名风格。 +- 小写接口如 `lock()` / `unlock()` / `try_lock()` 的存在,是为了兼容 `std::lock_guard` 这类标准 Lockable 习惯用法。 +- `ITask` 采用侵入式引用计数,说明这套任务系统原本是朝“跨线程提交和自动释放任务对象”这个方向设计的。 + +## 测试覆盖现状 + +当前测试只覆盖了: + +- `Mutex` +- `SpinLock` +- `ITask` / `LambdaTask` 的最基础行为 + +`ReadWriteLock`、`Thread`、`TaskGroup` 和 `TaskSystem` 当前没有看到对应单测,因此相关文档会更强调源码现状和风险边界。 ## 头文件 @@ -23,6 +54,10 @@ - [Thread](Thread/Thread.md) - `Thread.h` - [Threading](Threading/Threading.md) - `Threading.h` +## 相关指南 + +- [Synchronization And Task System Limits](../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md) - 解释为什么引擎要同时保留锁、线程和任务系统抽象,以及当前实现距离商业级 job system 还差哪些关键能力。 + ## 相关文档 - [上级目录](../XCEngine.md) diff --git a/docs/api/XCEngine/Threading/Threading/Threading.md b/docs/api/XCEngine/Threading/Threading/Threading.md index c1c68b99..31dd5d6f 100644 --- a/docs/api/XCEngine/Threading/Threading/Threading.md +++ b/docs/api/XCEngine/Threading/Threading/Threading.md @@ -1,18 +1,35 @@ # Threading -**命名空间**: `XCEngine` +**命名空间**: `XCEngine::Threading` **类型**: `header` **头文件**: `XCEngine/Threading/Threading.h` -**描述**: 定义 `XCEngine/Threading` 子目录中的 `Threading` public API。 +**描述**: 聚合导出 `Threading` 模块主要 public headers 的便利头文件。 ## 概述 -`Threading.h` 是 `XCEngine/Threading` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 +`Threading.h` 当前不声明新的类型,只是统一包含: + +- `Mutex` +- `SpinLock` +- `ReadWriteLock` +- `Thread` +- `ITask` +- `LambdaTask` +- `TaskGroup` +- `TaskSystemConfig` +- `TaskSystem` + +这类 umbrella header 在引擎里很常见,因为工具层、调试层或 gameplay 层经常希望一次拿到整套线程与任务基础设施,而不是逐个补 include。 + +## 使用建议 + +- 如果你只需要单个基础原语,直接 include 对应头文件会更轻。 +- 如果你要使用 `TaskSystem::ParallelFor()` 这类依赖 `LambdaTask` 模板可见性的接口,当前包含 `Threading.h` 比只包含 `TaskSystem.h` 更稳妥。 ## 相关文档 -- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 -- [API 总索引](../../../main.md) - 返回顶层索引 +- [当前模块](../Threading.md) +- [TaskSystem](../TaskSystem/TaskSystem.md) diff --git a/docs/api/_guides/Threading/Synchronization-And-TaskSystem-Limits.md b/docs/api/_guides/Threading/Synchronization-And-TaskSystem-Limits.md new file mode 100644 index 00000000..34b7f740 --- /dev/null +++ b/docs/api/_guides/Threading/Synchronization-And-TaskSystem-Limits.md @@ -0,0 +1,162 @@ +# Synchronization And Task System Limits + +## 先建立正确的心智模型 + +`XCEngine::Threading` 当前不是一套已经完整收口的商业级并发框架,而是三层能力并存: + +- 同步原语层: [Mutex](../../XCEngine/Threading/Mutex/Mutex.md)、[SpinLock](../../XCEngine/Threading/SpinLock/SpinLock.md)、[ReadWriteLock](../../XCEngine/Threading/ReadWriteLock/ReadWriteLock.md) +- 线程包装层: [Thread](../../XCEngine/Threading/Thread/Thread.md) +- 任务抽象层: [ITask](../../XCEngine/Threading/Task/Task.md)、[TaskGroup](../../XCEngine/Threading/TaskGroup/TaskGroup.md)、[TaskSystem](../../XCEngine/Threading/TaskSystem/TaskSystem.md) + +这三层同时存在是合理的。商业引擎里也几乎从来不是“有了 job system 就不要锁了”,原因很简单: + +- 平台窗口消息、日志、资源表、对象注册表,仍然需要细粒度同步。 +- 有些后台工作需要明确线程生命周期,而不是匿名 job。 +- 任务系统更多解决吞吐量和调度问题,不会替代所有底层同步。 + +## 为什么要同时保留锁、线程和任务系统 + +可以把它类比成很多商业引擎的常见分层: + +- 最底层保留 `mutex`、`rw lock`、原子变量等基础设施。 +- 中间层保留明确的 worker thread 或 service thread,例如文件监控线程、日志线程、调试采样线程。 +- 上层再把大量短小、彼此独立的工作投递到 job system。 + +从设计意图上看,XCEngine 当前也在往这个方向走: + +- `Mutex` 负责通用互斥,适合临界区较大或等待时间不可预测的场景。 +- `SpinLock` 适合极短临界区,代价是忙等。 +- `ReadWriteLock` 试图提升读多写少场景的吞吐量。 +- `Thread` 把 `std::thread` 的基本生命周期包装成统一接口。 +- `TaskSystem` 则意图成为更高层的统一调度器。 + +## 这些同步原语各自适合什么 + +### `Mutex` + +它本质上是对 `std::mutex` 的轻量包装。 + +适合: + +- 保护 map、vector、日志缓冲区等普通共享状态。 +- 需要和 `std::lock_guard`、`std::unique_lock` 等标准库工具协作的场景。 + +优点: + +- 语义清晰。 +- 平台和标准库行为成熟。 + +代价: + +- 阻塞时会进入内核或调度器等待路径,开销比自旋更高。 + +### `SpinLock` + +它当前用 `atomic_flag` 做空循环忙等,没有退避、没有 `yield()`、没有公平性控制。 + +适合: + +- 临界区极短。 +- 竞争概率低。 +- 线程数和 CPU 核数比较接近。 + +不适合: + +- 主线程容易被卡住的路径。 +- 高竞争场景。 +- 持锁期间有任何可能阻塞的代码。 + +### `ReadWriteLock` + +当前实现采用写者优先策略。设计动机很好理解: + +- 对引擎里的配置表、资源索引、场景查询类结构,读远多于写时,读写锁通常比普通互斥更有吸引力。 + +但当前实现要注意: + +- 当有写者排队时,新读者会被挡住。 +- 这会降低写饥饿风险,但提高读饥饿风险。 + +这是典型的吞吐量与公平性权衡。 + +## `Thread` 的定位是什么 + +`Thread` 当前不是线程框架,只是对 `std::thread` 的轻量包装。 + +它的价值主要在于: + +- 统一接口风格。 +- 在对象内保存一个引擎层名称和一个缓存 ID。 +- 析构时自动 `join()`,减少“忘记回收线程句柄”的错误。 + +但这也意味着: + +- 线程名当前不会传播到操作系统。 +- `GetId()` 与 `GetCurrentId()` 的 ID 口径并不一致。 +- 如果错误地对仍然 `joinable` 的对象再次 `Start()`,行为风险和原生 `std::thread` 一样高。 + +## `TaskSystem` 为什么现在还不能算商业级 job system + +如果拿成熟引擎的任务系统做参照,至少会期待这些基本性质: + +- 任务对象生命周期绝对正确。 +- 队列并发访问无数据竞争。 +- 支持明确的等待、依赖和 completion fence。 +- 关闭语义清晰。 +- 线程数、队列、分块策略和 profiling 都能受配置控制。 + +而当前源码距离这些目标还有明显差距: + +- `Submit()` 会把裸指针压入队列,但提交函数返回时对象可能已经被销毁。 +- 任务队列的入队和出队没有统一使用同一把锁。 +- `Wait()` 是空实现。 +- `TaskGroup` 的依赖、完成计数、完成回调都没有真正接上。 +- `ParallelFor()` 不等待结果,只是批量投递。 +- `Shutdown()` 只停线程,不真正清理任务生命周期。 + +这不是文档措辞问题,而是正确性问题。对于并发系统来说,正确性比 API 漂不漂亮重要得多。 + +## 那为什么还要保留这些接口 + +因为这套接口形状本身是有价值的,它表达了引擎未来很可能需要的能力: + +- 批处理任务提交。 +- 主线程回投。 +- 任务组与依赖图。 +- 并行 for。 +- 可扩展的调度配置。 + +很多商业引擎也是先稳定接口轮廓,再逐步把执行器、profiling、依赖图和取消语义补齐。当前文档保留这些页,不是为了假装能力已经可用,而是为了把“设计目标”和“当前现实”同时讲清楚。 + +## 当前阶段的推荐实践 + +如果你现在要在 XCEngine 里写可靠并发代码,更稳妥的做法是: + +1. 基础同步优先用 [Mutex](../../XCEngine/Threading/Mutex/Mutex.md) 或 [ReadWriteLock](../../XCEngine/Threading/ReadWriteLock/ReadWriteLock.md)。 +2. 极短临界区再考虑 [SpinLock](../../XCEngine/Threading/SpinLock/SpinLock.md)。 +3. 需要明确线程生命周期的后台服务,优先直接用 [Thread](../../XCEngine/Threading/Thread/Thread.md)。 +4. 当前把 [TaskSystem](../../XCEngine/Threading/TaskSystem/TaskSystem.md) 和 [TaskGroup](../../XCEngine/Threading/TaskGroup/TaskGroup.md) 视为实验性骨架,而不是生产级调度器。 + +## 如果要把它演进到商业级,需要补什么 + +优先级应该是: + +1. 修正任务所有权和引用计数协议。 +2. 修正队列同步,消除数据竞争。 +3. 实现真实的任务完成等待。 +4. 让 `TaskGroup` 的依赖、进度和完成回调真正接入调度器。 +5. 明确 `Shutdown()` / reinitialize / cancel 的状态机。 +6. 最后再补 profiling、work stealing、局部队列和更智能的 `ParallelFor`。 + +顺序不能反。商业级任务系统最先要站稳的是正确性,其次才是性能和功能丰富度。 + +## 相关 API + +- [Threading](../../XCEngine/Threading/Threading.md) +- [Mutex](../../XCEngine/Threading/Mutex/Mutex.md) +- [SpinLock](../../XCEngine/Threading/SpinLock/SpinLock.md) +- [ReadWriteLock](../../XCEngine/Threading/ReadWriteLock/ReadWriteLock.md) +- [Thread](../../XCEngine/Threading/Thread/Thread.md) +- [Task](../../XCEngine/Threading/Task/Task.md) +- [TaskGroup](../../XCEngine/Threading/TaskGroup/TaskGroup.md) +- [TaskSystem](../../XCEngine/Threading/TaskSystem/TaskSystem.md) diff --git a/docs/api/_meta/rebuild-status.md b/docs/api/_meta/rebuild-status.md index acee8420..e7b51d80 100644 --- a/docs/api/_meta/rebuild-status.md +++ b/docs/api/_meta/rebuild-status.md @@ -1,14 +1,14 @@ # API 文档重构状态 -**生成时间**: `2026-03-26 19:32:04` +**生成时间**: `2026-03-26 20:57:38` **来源**: `docs/api/_tools/audit_api_docs.py` ## 摘要 -- Markdown 页面数(全部): `2445` -- Markdown 页面数(canonical): `2436` -- Public headers 数: `185` +- Markdown 页面数(全部): `2456` +- Markdown 页面数(canonical): `2446` +- Public headers 数: `204` - 有效头文件引用数(全部): `185` - 有效头文件引用数(canonical): `185` - 无效头文件引用数: `0` @@ -20,9 +20,9 @@ ## 平行目录 - Canonical 根目录: `XCEngine` -- 源码目录节点数: `24` +- 源码目录节点数: `27` - 已生成目录总览页节点数: `24` -- 缺失目录总览页节点数: `0` +- 缺失目录总览页节点数: `3` - 支撑目录: `_meta, _tools` ## 模块覆盖 @@ -30,15 +30,17 @@ | 模块 | Public headers | 已覆盖 | 未覆盖 | |------|----------------|--------|--------| | `Audio` | `11` | `11` | `0` | -| `Components` | `8` | `8` | `0` | +| `Components` | `10` | `8` | `2` | | `Core` | `42` | `42` | `0` | | `Debug` | `10` | `10` | `0` | | `Input` | `5` | `5` | `0` | | `Memory` | `5` | `5` | `0` | | `Platform` | `11` | `11` | `0` | | `RHI` | `68` | `68` | `0` | +| `Rendering` | `10` | `0` | `10` | | `Resources` | `13` | `13` | `0` | -| `Scene` | `2` | `2` | `0` | +| `Scene` | `3` | `2` | `1` | +| `Scripting` | `6` | `0` | `6` | | `Threading` | `10` | `10` | `0` | ## 元信息覆盖 @@ -49,3 +51,31 @@ | `类型` | `208` | | `描述` | `208` | | `头文件` | `185` | + +## 缺失的平行目录总览页 + +- `XCEngine/Rendering` +- `XCEngine/Rendering/Pipelines` +- `XCEngine/Scripting` + +## 未覆盖的 public headers + +- `XCEngine/Components/MeshFilterComponent.h` +- `XCEngine/Components/MeshRendererComponent.h` +- `XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h` +- `XCEngine/Rendering/RenderCameraData.h` +- `XCEngine/Rendering/RenderContext.h` +- `XCEngine/Rendering/RenderPipeline.h` +- `XCEngine/Rendering/RenderPipelineAsset.h` +- `XCEngine/Rendering/RenderResourceCache.h` +- `XCEngine/Rendering/RenderSceneExtractor.h` +- `XCEngine/Rendering/RenderSurface.h` +- `XCEngine/Rendering/SceneRenderer.h` +- `XCEngine/Rendering/VisibleRenderObject.h` +- `XCEngine/Scene/SceneRuntime.h` +- `XCEngine/Scripting/IScriptRuntime.h` +- `XCEngine/Scripting/NullScriptRuntime.h` +- `XCEngine/Scripting/ScriptComponent.h` +- `XCEngine/Scripting/ScriptEngine.h` +- `XCEngine/Scripting/ScriptField.h` +- `XCEngine/Scripting/ScriptFieldStorage.h`