docs: rebuild Threading API content
This commit is contained in:
@@ -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 <XCEngine/Threading/LambdaTask.h>
|
||||
- `func` - 要保存的可调用对象。
|
||||
- `priority` - 任务优先级;默认值为 `TaskPriority::Normal`。
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::LambdaTask object;
|
||||
}
|
||||
```
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](LambdaTask.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](LambdaTask.md)
|
||||
- [Execute](Execute.md)
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
# LambdaTask::Execute
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
执行保存的可调用对象。
|
||||
|
||||
```cpp
|
||||
void Execute() override;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/LambdaTask.h`,当前页面用于固定 `LambdaTask` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
|
||||
**示例:**
|
||||
当前实现只有一行:
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/LambdaTask.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::LambdaTask object;
|
||||
// 根据上下文补齐参数后调用 LambdaTask::Execute(...)。
|
||||
(void)object;
|
||||
}
|
||||
m_func();
|
||||
```
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](LambdaTask.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](LambdaTask.md)
|
||||
- [ITask::Execute](../Task/Execute.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<Func>` 是最轻量的任务实现之一:它不额外引入调度语义,只负责保存一个可调用对象,并在 [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)
|
||||
|
||||
@@ -1,28 +1,19 @@
|
||||
# Mutex::Mutex()
|
||||
# Mutex::Constructor
|
||||
|
||||
构造对象。
|
||||
默认构造一个互斥锁。
|
||||
|
||||
```cpp
|
||||
Mutex() = default;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
当前构造函数是编译器生成的默认实现,唯一实质状态是内部的 `std::mutex`。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 返回值
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/Mutex.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Mutex object;
|
||||
}
|
||||
```
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Mutex.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Mutex.md)
|
||||
|
||||
@@ -1,29 +1,23 @@
|
||||
# Mutex::~Mutex()
|
||||
# Mutex::Destructor
|
||||
|
||||
销毁对象并释放相关资源。
|
||||
销毁互斥锁对象。
|
||||
|
||||
```cpp
|
||||
~Mutex() = default;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
当前析构函数是默认实现,析构行为由内部 `std::mutex` 决定。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 返回值
|
||||
|
||||
**示例:**
|
||||
- 无。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/Mutex.h>
|
||||
## 注意事项
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Mutex object;
|
||||
// 对象离开作用域时会自动触发析构。
|
||||
}
|
||||
```
|
||||
- 和标准库一样,销毁一个仍在被使用的互斥锁属于未定义行为。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Mutex.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Mutex.md)
|
||||
|
||||
31
docs/api/XCEngine/Threading/Mutex/Lock.md
Normal file
31
docs/api/XCEngine/Threading/Mutex/Lock.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Mutex::Lock
|
||||
|
||||
阻塞直到获得互斥锁。
|
||||
|
||||
```cpp
|
||||
void Lock();
|
||||
void lock() const;
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前实现有两套入口:
|
||||
|
||||
- `Lock()`:引擎风格命名。
|
||||
- `lock()`:标准 Lockable 风格别名。
|
||||
|
||||
两者都直接转发到底层 `std::mutex::lock()`。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 如果当前线程已经持有这把锁,再次调用会死锁。
|
||||
- `lock()` 的存在使 `Mutex` 可以直接配合 `std::lock_guard<Mutex>` 等标准库工具使用。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Mutex.md)
|
||||
- [Unlock](Unlock.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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/Mutex.h>
|
||||
## 返回值
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Mutex object;
|
||||
// 根据上下文补齐参数后调用 Mutex::TryLock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- `bool` - 成功获得锁时返回 `true`;否则返回 `false`。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Mutex.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Mutex.md)
|
||||
- [Lock](Lock.md)
|
||||
|
||||
26
docs/api/XCEngine/Threading/Mutex/Unlock.md
Normal file
26
docs/api/XCEngine/Threading/Mutex/Unlock.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Mutex::Unlock
|
||||
|
||||
释放互斥锁。
|
||||
|
||||
```cpp
|
||||
void Unlock();
|
||||
void unlock() const;
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前实现有两套入口:
|
||||
|
||||
- `Unlock()`:引擎风格命名。
|
||||
- `unlock()`:标准 Lockable 风格别名。
|
||||
|
||||
两者都直接转发到底层 `std::mutex::unlock()`。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Mutex.md)
|
||||
- [Lock](Lock.md)
|
||||
@@ -1,30 +0,0 @@
|
||||
# Mutex::lock
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
```cpp
|
||||
void lock() const;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/Mutex.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Mutex object;
|
||||
// 根据上下文补齐参数后调用 Mutex::lock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Mutex.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
@@ -1,30 +0,0 @@
|
||||
# Mutex::try_lock
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
```cpp
|
||||
bool try_lock() const;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `bool` - 返回值语义详见头文件声明。
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/Mutex.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Mutex object;
|
||||
// 根据上下文补齐参数后调用 Mutex::try_lock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Mutex.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
@@ -1,30 +0,0 @@
|
||||
# Mutex::unlock
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
```cpp
|
||||
void unlock() const;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/Mutex.h`,当前页面用于固定 `Mutex` 类目录下的方法级 canonical 路径。
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/Mutex.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Mutex object;
|
||||
// 根据上下文补齐参数后调用 Mutex::unlock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Mutex.md)
|
||||
- [返回模块目录](../Threading.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 <XCEngine/Threading/ReadWriteLock.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::ReadWriteLock object;
|
||||
}
|
||||
```
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](ReadWriteLock.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](ReadWriteLock.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 <XCEngine/Threading/ReadWriteLock.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::ReadWriteLock object;
|
||||
// 对象离开作用域时会自动触发析构。
|
||||
}
|
||||
```
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](ReadWriteLock.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](ReadWriteLock.md)
|
||||
|
||||
@@ -1,30 +1,31 @@
|
||||
# ReadWriteLock::ReadLock
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
以共享方式进入读写锁。
|
||||
|
||||
```cpp
|
||||
void ReadLock();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/ReadWriteLock.h`,当前页面用于固定 `ReadWriteLock` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
|
||||
**示例:**
|
||||
当前实现会先拿内部互斥量,然后等待下面这个条件成立:
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/ReadWriteLock.h>
|
||||
|
||||
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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/ReadWriteLock.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::ReadWriteLock object;
|
||||
// 根据上下文补齐参数后调用 ReadWriteLock::ReadUnlock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](ReadWriteLock.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](ReadWriteLock.md)
|
||||
- [ReadLock](ReadLock.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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/ReadWriteLock.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::ReadWriteLock object;
|
||||
// 根据上下文补齐参数后调用 ReadWriteLock::WriteLock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](ReadWriteLock.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](ReadWriteLock.md)
|
||||
- [WriteUnlock](WriteUnlock.md)
|
||||
- [ReadLock](ReadLock.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 <XCEngine/Threading/ReadWriteLock.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::ReadWriteLock object;
|
||||
// 根据上下文补齐参数后调用 ReadWriteLock::WriteUnlock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](ReadWriteLock.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](ReadWriteLock.md)
|
||||
- [WriteLock](WriteLock.md)
|
||||
|
||||
36
docs/api/XCEngine/Threading/SpinLock/Lock.md
Normal file
36
docs/api/XCEngine/Threading/SpinLock/Lock.md
Normal file
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/SpinLock.h>
|
||||
|
||||
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)
|
||||
|
||||
30
docs/api/XCEngine/Threading/SpinLock/Unlock.md
Normal file
30
docs/api/XCEngine/Threading/SpinLock/Unlock.md
Normal file
@@ -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)
|
||||
@@ -1,30 +0,0 @@
|
||||
# SpinLock::lock
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
```cpp
|
||||
void lock();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/SpinLock.h`,当前页面用于固定 `SpinLock` 类目录下的方法级 canonical 路径。
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/SpinLock.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::SpinLock object;
|
||||
// 根据上下文补齐参数后调用 SpinLock::lock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](SpinLock.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
@@ -1,30 +0,0 @@
|
||||
# SpinLock::try_lock
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
```cpp
|
||||
bool try_lock();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/SpinLock.h`,当前页面用于固定 `SpinLock` 类目录下的方法级 canonical 路径。
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `bool` - 返回值语义详见头文件声明。
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/SpinLock.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::SpinLock object;
|
||||
// 根据上下文补齐参数后调用 SpinLock::try_lock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](SpinLock.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
@@ -1,30 +0,0 @@
|
||||
# SpinLock::unlock
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
```cpp
|
||||
void unlock();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/SpinLock.h`,当前页面用于固定 `SpinLock` 类目录下的方法级 canonical 路径。
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/SpinLock.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::SpinLock object;
|
||||
// 根据上下文补齐参数后调用 SpinLock::unlock(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](SpinLock.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
24
docs/api/XCEngine/Threading/Task/AddRef.md
Normal file
24
docs/api/XCEngine/Threading/Task/AddRef.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# ITask::AddRef
|
||||
|
||||
增加任务对象引用计数。
|
||||
|
||||
```cpp
|
||||
void AddRef();
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前头文件内联实现执行:
|
||||
|
||||
```cpp
|
||||
m_refCount.fetch_add(1);
|
||||
```
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [Release](Release.md)
|
||||
20
docs/api/XCEngine/Threading/Task/Destructor.md
Normal file
20
docs/api/XCEngine/Threading/Task/Destructor.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ITask::Destructor
|
||||
|
||||
通过基类指针安全销毁任务对象。
|
||||
|
||||
```cpp
|
||||
virtual ~ITask() = default;
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
虚析构函数保证派生任务能够通过 `ITask*` 正确析构。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [Release](Release.md)
|
||||
20
docs/api/XCEngine/Threading/Task/Execute.md
Normal file
20
docs/api/XCEngine/Threading/Task/Execute.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ITask::Execute
|
||||
|
||||
执行任务主体。
|
||||
|
||||
```cpp
|
||||
virtual void Execute() = 0;
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
这是纯虚接口,具体任务逻辑由派生类实现。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [OnComplete](OnComplete.md)
|
||||
20
docs/api/XCEngine/Threading/Task/GetId.md
Normal file
20
docs/api/XCEngine/Threading/Task/GetId.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ITask::GetId
|
||||
|
||||
读取任务 ID。
|
||||
|
||||
```cpp
|
||||
uint64_t GetId() const;
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前头文件内联实现直接返回 `m_id`。
|
||||
|
||||
## 返回值
|
||||
|
||||
- `uint64_t` - 当前任务 ID。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [SetId](SetId.md)
|
||||
20
docs/api/XCEngine/Threading/Task/GetPriority.md
Normal file
20
docs/api/XCEngine/Threading/Task/GetPriority.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ITask::GetPriority
|
||||
|
||||
读取任务优先级。
|
||||
|
||||
```cpp
|
||||
TaskPriority GetPriority() const;
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前头文件内联实现直接返回 `m_priority`。
|
||||
|
||||
## 返回值
|
||||
|
||||
- `TaskPriority` - 当前任务优先级。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [SetPriority](SetPriority.md)
|
||||
20
docs/api/XCEngine/Threading/Task/GetStatus.md
Normal file
20
docs/api/XCEngine/Threading/Task/GetStatus.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ITask::GetStatus
|
||||
|
||||
读取任务状态。
|
||||
|
||||
```cpp
|
||||
TaskStatus GetStatus() const;
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前头文件内联实现通过 `m_status.load()` 返回原子状态值。
|
||||
|
||||
## 返回值
|
||||
|
||||
- `TaskStatus` - 当前任务状态。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [SetStatus](SetStatus.md)
|
||||
20
docs/api/XCEngine/Threading/Task/OnCancel.md
Normal file
20
docs/api/XCEngine/Threading/Task/OnCancel.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ITask::OnCancel
|
||||
|
||||
任务取消时的回调钩子。
|
||||
|
||||
```cpp
|
||||
virtual void OnCancel() {}
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前基类默认实现为空,不做任何事。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [OnComplete](OnComplete.md)
|
||||
20
docs/api/XCEngine/Threading/Task/OnComplete.md
Normal file
20
docs/api/XCEngine/Threading/Task/OnComplete.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# ITask::OnComplete
|
||||
|
||||
任务完成后的回调钩子。
|
||||
|
||||
```cpp
|
||||
virtual void OnComplete() {}
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前基类默认实现为空,不做任何事。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [Execute](Execute.md)
|
||||
28
docs/api/XCEngine/Threading/Task/Release.md
Normal file
28
docs/api/XCEngine/Threading/Task/Release.md
Normal file
@@ -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)
|
||||
24
docs/api/XCEngine/Threading/Task/SetId.md
Normal file
24
docs/api/XCEngine/Threading/Task/SetId.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# ITask::SetId
|
||||
|
||||
设置任务 ID。
|
||||
|
||||
```cpp
|
||||
void SetId(uint64_t id);
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前头文件内联实现直接执行 `m_id = id`。
|
||||
|
||||
## 参数
|
||||
|
||||
- `id` - 要写入的任务 ID。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [GetId](GetId.md)
|
||||
24
docs/api/XCEngine/Threading/Task/SetPriority.md
Normal file
24
docs/api/XCEngine/Threading/Task/SetPriority.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# ITask::SetPriority
|
||||
|
||||
设置任务优先级。
|
||||
|
||||
```cpp
|
||||
void SetPriority(TaskPriority priority);
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前头文件内联实现直接执行 `m_priority = priority`。
|
||||
|
||||
## 参数
|
||||
|
||||
- `priority` - 要写入的优先级。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [GetPriority](GetPriority.md)
|
||||
24
docs/api/XCEngine/Threading/Task/SetStatus.md
Normal file
24
docs/api/XCEngine/Threading/Task/SetStatus.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# ITask::SetStatus
|
||||
|
||||
设置任务状态。
|
||||
|
||||
```cpp
|
||||
void SetStatus(TaskStatus status);
|
||||
```
|
||||
|
||||
## 行为说明
|
||||
|
||||
当前头文件内联实现直接把 `status` 写入原子成员 `m_status`。
|
||||
|
||||
## 参数
|
||||
|
||||
- `status` - 要写入的新状态。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类型总览](Task.md)
|
||||
- [GetStatus](GetStatus.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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/TaskGroup.h>
|
||||
- `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)
|
||||
|
||||
@@ -1,45 +1,52 @@
|
||||
# TaskGroup::AddTask
|
||||
|
||||
添加元素或建立关联。
|
||||
|
||||
该方法在 `XCEngine/Threading/TaskGroup.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。
|
||||
|
||||
## 重载 1: 声明
|
||||
向任务组添加一个任务对象或 lambda 任务。
|
||||
|
||||
```cpp
|
||||
uint64_t AddTask(std::unique_ptr<ITask> task);
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `task` - 参数语义详见头文件声明。
|
||||
|
||||
**返回:** `uint64_t` - 返回值语义详见头文件声明。
|
||||
|
||||
## 重载 2: 声明
|
||||
|
||||
```cpp
|
||||
uint64_t AddTask(Callback&& func, TaskPriority priority = TaskPriority::Normal);
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `func` - 参数语义详见头文件声明。
|
||||
- `priority` - 参数语义详见头文件声明。
|
||||
## 行为说明
|
||||
|
||||
**返回:** `uint64_t` - 返回值语义详见头文件声明。
|
||||
`AddTask(std::unique_ptr<ITask>)` 当前会:
|
||||
|
||||
**示例:**
|
||||
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 <XCEngine/Threading/TaskGroup.h>
|
||||
`AddTask(Callback&&, TaskPriority)` 会先构造一个 `LambdaTask<Callback>`,然后转发到上面的重载。
|
||||
|
||||
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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/TaskGroup.h>
|
||||
- 无。
|
||||
|
||||
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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/TaskGroup.h>
|
||||
## 返回值
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,29 +1,32 @@
|
||||
# TaskGroup::~TaskGroup()
|
||||
# TaskGroup::~TaskGroup
|
||||
|
||||
销毁对象并释放相关资源。
|
||||
销毁任务组对象。
|
||||
|
||||
```cpp
|
||||
~TaskGroup();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
当前析构函数是默认实现,不包含额外清理逻辑。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 返回值
|
||||
|
||||
**示例:**
|
||||
- 无。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/TaskGroup.h>
|
||||
## 当前实现限制
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::TaskGroup object;
|
||||
// 对象离开作用域时会自动触发析构。
|
||||
}
|
||||
```
|
||||
- 当前不会释放 [AddTask](AddTask.md) 存入的裸任务指针。
|
||||
- 如果你通过 `AddTask(std::unique_ptr<ITask>)` 添加了任务,`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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/TaskGroup.h>
|
||||
- 取值范围目标上应在 `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)
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
# TaskGroup::IsComplete
|
||||
|
||||
查询当前状态。
|
||||
查询任务组是否完成。
|
||||
|
||||
```cpp
|
||||
bool IsComplete() const;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `bool` - 返回值语义详见头文件声明。
|
||||
|
||||
**示例:**
|
||||
当前实现直接返回:
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/TaskGroup.h>
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,31 +1,39 @@
|
||||
# TaskGroup::SetCompleteCallback
|
||||
|
||||
设置相关状态或配置。
|
||||
设置任务组完成时要调用的回调函数。
|
||||
|
||||
```cpp
|
||||
void SetCompleteCallback(Callback&& callback);
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:**
|
||||
- `callback` - 参数语义详见头文件声明。
|
||||
当前实现仅在持锁状态下把回调保存到 `m_completeCallback`。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 参数
|
||||
|
||||
**示例:**
|
||||
- `callback` - 任务组完成后期望执行的回调。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/TaskGroup.h>
|
||||
## 返回值
|
||||
|
||||
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)
|
||||
|
||||
@@ -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<ITask>` 释放成裸指针保存,但析构函数是默认实现,当前不会回收这些任务对象。
|
||||
- [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)
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
# TaskGroup::Wait
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
阻塞当前线程,等待任务组完成。
|
||||
|
||||
```cpp
|
||||
void Wait();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
当前实现会等待条件变量,直到谓词 `m_pendingCount.load() == 0` 为真。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 返回值
|
||||
|
||||
**示例:**
|
||||
- 无。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/TaskGroup.h>
|
||||
## 当前实现限制
|
||||
|
||||
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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/TaskGroup.h>
|
||||
## 返回值
|
||||
|
||||
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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/TaskSystem.h>
|
||||
- 新创建的 `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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/TaskSystem.h>
|
||||
- `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)
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
# TaskSystem::Get
|
||||
|
||||
获取相关状态或对象。
|
||||
取得全局任务系统单例。
|
||||
|
||||
```cpp
|
||||
static TaskSystem& Get();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
|
||||
**返回:** `TaskSystem&` - 返回值语义详见头文件声明。
|
||||
|
||||
**示例:**
|
||||
当前实现返回一个函数内静态对象:
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/TaskSystem.h>
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,30 +1,25 @@
|
||||
# TaskSystem::GetWorkerThreadCount
|
||||
|
||||
获取相关状态或对象。
|
||||
返回当前记录的工作线程数。
|
||||
|
||||
```cpp
|
||||
uint32_t GetWorkerThreadCount() const;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
当前实现直接返回成员 `m_workerThreadCount`。
|
||||
|
||||
**返回:** `uint32_t` - 返回值语义详见头文件声明。
|
||||
## 返回值
|
||||
|
||||
**示例:**
|
||||
- 当前配置的工作线程数量。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/TaskSystem.h>
|
||||
## 注意事项
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::TaskSystem object;
|
||||
// 根据上下文补齐参数后调用 TaskSystem::GetWorkerThreadCount(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 在 [Initialize](Initialize.md) 之前,这个值默认是 `0`。
|
||||
- 这个值表示“初始化时决定的目标线程数”,不表示当前仍然活跃的线程数量。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](TaskSystem.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](TaskSystem.md)
|
||||
- [Initialize](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 <XCEngine/Threading/TaskSystem.h>
|
||||
- `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)
|
||||
|
||||
@@ -1,33 +1,54 @@
|
||||
# TaskSystem::ParallelFor
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
把一个整数区间拆分成多个任务并提交执行。
|
||||
|
||||
```cpp
|
||||
template<typename Func> void ParallelFor(int32_t start, int32_t end, Func&& func);
|
||||
template<typename Func>
|
||||
void ParallelFor(int32_t start, int32_t end, Func&& func);
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:**
|
||||
- `start` - 参数语义详见头文件声明。
|
||||
- `end` - 参数语义详见头文件声明。
|
||||
- `func` - 参数语义详见头文件声明。
|
||||
当前模板实现会:
|
||||
|
||||
**返回:** `template<typename Func> 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 <XCEngine/Threading/TaskSystem.h>
|
||||
- `start` - 起始索引,包含。
|
||||
- `end` - 结束索引,不包含。
|
||||
- `func` - 对区间内每个索引执行的可调用对象。
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::TaskSystem object;
|
||||
// 根据上下文补齐参数后调用 TaskSystem::ParallelFor(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 当前实现限制
|
||||
|
||||
- 当前函数提交完任务后立即返回,不会等待所有分片完成。
|
||||
- 当前按硬件并发数分片,而不是按 [Initialize](Initialize.md) 配置的工作线程数分片。
|
||||
- 当前头文件里模板使用了 `LambdaTask` 和 `std::min`,但 `TaskSystem.h` 自身没有包含 `LambdaTask.h` 和 `<algorithm>`;如果只包含这个头,模板实例化可能失败。
|
||||
- 当前底层仍然依赖 [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)
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
# TaskSystem::RunOnMainThread
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
把一个回调排入主线程执行队列。
|
||||
|
||||
```cpp
|
||||
void RunOnMainThread(std::function<void()>&& func);
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:**
|
||||
- `func` - 参数语义详见头文件声明。
|
||||
当前实现会在 `m_queueMutex` 保护下把回调追加到 `m_mainThreadQueue`。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
这些回调不会立即执行,而是等待 [Update](Update.md) 被调用时再统一消费。
|
||||
|
||||
**示例:**
|
||||
## 参数
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/TaskSystem.h>
|
||||
- `func` - 需要在主线程执行的回调。
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::TaskSystem object;
|
||||
// 根据上下文补齐参数后调用 TaskSystem::RunOnMainThread(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
## 返回值
|
||||
|
||||
- 无。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 当前实现本身不检查调用线程是否为主线程;“主线程”只是通过谁来调用 [Update](Update.md) 约定出来的。
|
||||
- 当前没有队列容量限制,也没有通知等待主线程的机制。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](TaskSystem.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](TaskSystem.md)
|
||||
- [Update](Update.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 <XCEngine/Threading/TaskSystem.h>
|
||||
- 无。
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,45 +1,57 @@
|
||||
# TaskSystem::Submit
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
该方法在 `XCEngine/Threading/TaskSystem.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。
|
||||
|
||||
## 重载 1: 声明
|
||||
提交一个任务对象或 lambda 到任务系统。
|
||||
|
||||
```cpp
|
||||
uint64_t Submit(std::unique_ptr<ITask> task);
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `task` - 参数语义详见头文件声明。
|
||||
|
||||
**返回:** `uint64_t` - 返回值语义详见头文件声明。
|
||||
|
||||
## 重载 2: 声明
|
||||
|
||||
```cpp
|
||||
uint64_t Submit(std::function<void()>&& func, TaskPriority priority = TaskPriority::Normal);
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `func` - 参数语义详见头文件声明。
|
||||
- `priority` - 参数语义详见头文件声明。
|
||||
## 行为说明
|
||||
|
||||
**返回:** `uint64_t` - 返回值语义详见头文件声明。
|
||||
`Submit(std::unique_ptr<ITask>)` 当前会:
|
||||
|
||||
**示例:**
|
||||
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 <XCEngine/Threading/TaskSystem.h>
|
||||
`Submit(std::function<void()>&&, TaskPriority)` 会先 `new LambdaTask<std::function<void()>>`,再把它包装成 `std::unique_ptr<ITask>` 转发给另一个重载。
|
||||
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/TaskSystem.h>
|
||||
- 无。
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::TaskSystem object;
|
||||
// 根据上下文补齐参数后调用 TaskSystem::Update(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
## 设计说明
|
||||
|
||||
这是一种典型的“后台线程投递,主线程集中消费”模型。商业引擎里资源系统、脚本系统和编辑器工具都经常需要这种回投路径,因为很多对象只能在主线程安全访问。
|
||||
|
||||
## 当前实现限制
|
||||
|
||||
- 当前不会自动调用,需要调用方在主线程帧循环里显式执行。
|
||||
- `m_mainThreadCondition` 当前没有被使用。
|
||||
- 当前没有异常隔离;某个回调抛出异常时,会中断后续回调执行路径。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](TaskSystem.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](TaskSystem.md)
|
||||
- [RunOnMainThread](RunOnMainThread.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 <XCEngine/Threading/TaskSystem.h>
|
||||
## 返回值
|
||||
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/Thread.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Thread object;
|
||||
}
|
||||
```
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Thread.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Thread.md)
|
||||
- [Start](Start.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 <XCEngine/Threading/Thread.h>
|
||||
## 注意事项
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Thread object;
|
||||
// 对象离开作用域时会自动触发析构。
|
||||
}
|
||||
```
|
||||
- 这意味着析构可能阻塞直到线程函数结束。
|
||||
- 如果你希望线程独立运行而不在析构时阻塞,应先显式调用 [Detach](Detach.md)。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Thread.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Thread.md)
|
||||
- [Join](Join.md)
|
||||
- [Detach](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 <XCEngine/Threading/Thread.h>
|
||||
## 注意事项
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Thread object;
|
||||
// 根据上下文补齐参数后调用 Thread::Detach(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 一旦分离,线程执行与 `Thread` 对象生命周期脱钩,之后析构不会再 `Join()` 这条线程。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Thread.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Thread.md)
|
||||
- [Join](Join.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<std::thread::id>` 求 hash
|
||||
3. 把结果转成 `Id`
|
||||
|
||||
**示例:**
|
||||
## 返回值
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/Thread.h>
|
||||
- `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)
|
||||
|
||||
@@ -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 <XCEngine/Threading/Thread.h>
|
||||
- `Id` - 当前缓存的线程标识;尚未启动时通常为 `0`。
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Thread object;
|
||||
// 根据上下文补齐参数后调用 Thread::GetId(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
## 注意事项
|
||||
|
||||
- 这个值与 [GetCurrentId](GetCurrentId.md) 的实现口径不同,不应假设两者可以直接比较。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Thread.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Thread.md)
|
||||
- [GetCurrentId](GetCurrentId.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 <XCEngine/Threading/Thread.h>
|
||||
## 注意事项
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Thread object;
|
||||
// 根据上下文补齐参数后调用 Thread::GetName(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 这只是 `Thread` 对象内部保存的名称字符串,不代表 OS 级线程名一定被设置。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Thread.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Thread.md)
|
||||
- [Start](Start.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 <XCEngine/Threading/Thread.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Thread object;
|
||||
// 根据上下文补齐参数后调用 Thread::Join(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Thread.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Thread.md)
|
||||
- [Detach](Detach.md)
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
# Thread::Sleep
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
让当前线程休眠指定毫秒数。
|
||||
|
||||
```cpp
|
||||
static void Sleep(uint32_t milliseconds);
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:**
|
||||
- `milliseconds` - 参数语义详见头文件声明。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
|
||||
**示例:**
|
||||
当前实现直接调用:
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/Thread.h>
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,32 +1,36 @@
|
||||
# Thread::Start
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
启动一个新线程。
|
||||
|
||||
```cpp
|
||||
template<typename Func> void Start(Func&& func, const Containers::String& name = "Thread");
|
||||
template<typename Func>
|
||||
void Start(Func&& func, const Containers::String& name = "Thread");
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:**
|
||||
- `func` - 参数语义详见头文件声明。
|
||||
- `name` - 参数语义详见头文件声明。
|
||||
当前模板实现会:
|
||||
|
||||
**返回:** `template<typename Func> void` - 返回值语义详见头文件声明。
|
||||
1. 把 `m_name = name`
|
||||
2. 执行 `m_thread = std::thread(std::forward<Func>(func))`
|
||||
3. 把 `m_thread.native_handle()` 转成整数,写入 `m_id`
|
||||
|
||||
**示例:**
|
||||
## 参数
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/Thread.h>
|
||||
- `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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,30 +1,20 @@
|
||||
# Thread::Yield
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
让出当前线程时间片。
|
||||
|
||||
```cpp
|
||||
static void Yield();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。
|
||||
## 行为说明
|
||||
|
||||
**参数:** 无。
|
||||
当前实现直接调用 `std::this_thread::yield()`。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 返回值
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/Threading/Thread.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::Threading::Thread object;
|
||||
// 根据上下文补齐参数后调用 Thread::Yield(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 无。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](Thread.md)
|
||||
- [返回模块目录](../Threading.md)
|
||||
- [返回类型总览](Thread.md)
|
||||
- [Sleep](Sleep.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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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`
|
||||
|
||||
Reference in New Issue
Block a user