docs: rebuild Threading API content

This commit is contained in:
2026-03-26 20:59:59 +08:00
parent 9a2d77b81d
commit 8f486611d5
78 changed files with 1648 additions and 1061 deletions

View File

@@ -1,30 +1,28 @@
# LambdaTask::LambdaTask() # LambdaTask::Constructor
构造对象 构造一个 lambda 任务
```cpp ```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 - `func` - 要保存的可调用对象。
#include <XCEngine/Threading/LambdaTask.h> - `priority` - 任务优先级;默认值为 `TaskPriority::Normal`
void Example() { ## 返回值
XCEngine::Threading::LambdaTask object;
} - 无。
```
## 相关文档 ## 相关文档
- [返回类总览](LambdaTask.md) - [返回类总览](LambdaTask.md)
- [返回模块目录](../Threading.md) - [Execute](Execute.md)

View File

@@ -1,30 +1,24 @@
# LambdaTask::Execute # LambdaTask::Execute
公开方法,详见头文件声明 执行保存的可调用对象
```cpp ```cpp
void Execute() override; void Execute() override;
``` ```
该方法声明于 `XCEngine/Threading/LambdaTask.h`,当前页面用于固定 `LambdaTask` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 无。 当前实现只有一行:
**返回:** `void` - 无返回值。
**示例:**
```cpp ```cpp
#include <XCEngine/Threading/LambdaTask.h> m_func();
void Example() {
XCEngine::Threading::LambdaTask object;
// 根据上下文补齐参数后调用 LambdaTask::Execute(...)。
(void)object;
}
``` ```
## 返回值
- 无。
## 相关文档 ## 相关文档
- [返回类总览](LambdaTask.md) - [返回类总览](LambdaTask.md)
- [返回模块目录](../Threading.md) - [ITask::Execute](../Task/Execute.md)

View File

@@ -2,30 +2,32 @@
**命名空间**: `XCEngine::Threading` **命名空间**: `XCEngine::Threading`
**类型**: `class` **类型**: `class template`
**头文件**: `XCEngine/Threading/LambdaTask.h` **头文件**: `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) | 构造对象。 | | [Constructor](Constructor.md) | 构造 lambda 任务。 |
| [Execute](Execute.md) | 公开方法,详见头文件声明。 | | [Execute](Execute.md) | 执行保存的可调用对象。 |
## 相关文档 ## 相关文档
- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [ITask](../Task/Task.md)

View File

@@ -1,28 +1,19 @@
# Mutex::Mutex() # Mutex::Constructor
构造对象 默认构造一个互斥锁
```cpp ```cpp
Mutex() = default; 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) - [返回类总览](Mutex.md)
- [返回模块目录](../Threading.md)

View File

@@ -1,29 +1,23 @@
# Mutex::~Mutex() # Mutex::Destructor
销毁对象并释放相关资源 销毁互斥锁对象。
```cpp ```cpp
~Mutex() = default; ~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) - [返回类总览](Mutex.md)
- [返回模块目录](../Threading.md)

View 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)

View File

@@ -6,32 +6,36 @@
**头文件**: `XCEngine/Threading/Mutex.h` **头文件**: `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` 的行为,而是为了:
| 声明 | 类型 | 说明 | - 统一命名空间与 include 路径。
|------|------|------| - 同时支持 `Lock()` 这种引擎风格接口。
| `Mutex` | `class` | 头文件中的公开声明。 | - 也支持 `lock()` / `unlock()` / `try_lock()` 这种标准库 Lockable 习惯用法。
## 公共方法 ## 当前实现边界
| 方法 | 描述 | - 它不是递归锁;同一线程重复加锁会死锁。
- 没有超时锁接口。
- 没有显式的 owner 检查或调试断言。
- 小写接口之所以能声明成 `const`,是因为底层 `std::mutex` 被保存为 `mutable`
## 公开方法
| 方法 | 说明 |
|------|------| |------|------|
| [Mutex()](Constructor.md) | 构造对象。 | | [Constructor](Constructor.md) | 默认构造互斥锁。 |
| [~Mutex()](Destructor.md) | 销毁对象并释放相关资源。 | | [Destructor](Destructor.md) | 销毁互斥锁。 |
| [Lock](Lock.md) | 公开方法,详见头文件声明。 | | [Lock](Lock.md) | 阻塞直到获得锁;同页也说明 `lock()` 别名。 |
| [Unlock](Unlock.md) | 公开方法,详见头文件声明。 | | [Unlock](Unlock.md) | 释放锁;同页也说明 `unlock()` 别名。 |
| [TryLock](TryLock.md) | 公开方法,详见头文件声明。 | | [TryLock](TryLock.md) | 尝试获得锁;同页也说明 `try_lock()` 别名。 |
| [lock](lock.md) | 公开方法,详见头文件声明。 |
| [unlock](unlock.md) | 公开方法,详见头文件声明。 |
| [try_lock](try_lock.md) | 公开方法,详见头文件声明。 |
## 相关文档 ## 相关文档
- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [SpinLock](../SpinLock/SpinLock.md)

View File

@@ -1,30 +1,26 @@
# Mutex::TryLock # Mutex::TryLock
公开方法,详见头文件声明 尝试获得互斥锁
```cpp ```cpp
bool TryLock(); 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() { - `bool` - 成功获得锁时返回 `true`;否则返回 `false`
XCEngine::Threading::Mutex object;
// 根据上下文补齐参数后调用 Mutex::TryLock(...)。
(void)object;
}
```
## 相关文档 ## 相关文档
- [返回类总览](Mutex.md) - [返回类总览](Mutex.md)
- [返回模块目录](../Threading.md) - [Lock](Lock.md)

View File

@@ -0,0 +1,26 @@
# Mutex::Unlock
释放互斥锁。
```cpp
void Unlock();
void unlock() const;
```
## 行为说明
当前实现有两套入口:
- `Unlock()`:引擎风格命名。
- `unlock()`:标准 Lockable 风格别名。
两者都直接转发到底层 `std::mutex::unlock()`
## 返回值
- 无。
## 相关文档
- [返回类型总览](Mutex.md)
- [Lock](Lock.md)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -1,28 +1,23 @@
# ReadWriteLock::ReadWriteLock() # ReadWriteLock::Constructor
构造对象 默认构造一个读写锁
```cpp ```cpp
ReadWriteLock() = default; 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) - [返回类总览](ReadWriteLock.md)
- [返回模块目录](../Threading.md)

View File

@@ -1,29 +1,19 @@
# ReadWriteLock::~ReadWriteLock() # ReadWriteLock::Destructor
销毁对象并释放相关资源 销毁读写锁对象。
```cpp ```cpp
~ReadWriteLock() = default; ~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) - [返回类总览](ReadWriteLock.md)
- [返回模块目录](../Threading.md)

View File

@@ -1,30 +1,31 @@
# ReadWriteLock::ReadLock # ReadWriteLock::ReadLock
公开方法,详见头文件声明 以共享方式进入读写锁
```cpp ```cpp
void ReadLock(); void ReadLock();
``` ```
该方法声明于 `XCEngine/Threading/ReadWriteLock.h`,当前页面用于固定 `ReadWriteLock` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 无。 当前实现会先拿内部互斥量,然后等待下面这个条件成立:
**返回:** `void` - 无返回值。
**示例:**
```cpp ```cpp
#include <XCEngine/Threading/ReadWriteLock.h> !m_writerActive && m_writersWaiting == 0
void Example() {
XCEngine::Threading::ReadWriteLock object;
// 根据上下文补齐参数后调用 ReadWriteLock::ReadLock(...)。
(void)object;
}
``` ```
条件满足后,`m_readers` 加一。
## 返回值
- 无。
## 注意事项
- 只要有写者在等待,新读者也会被拦住,因此当前策略是写者优先而不是纯读者优先。
## 相关文档 ## 相关文档
- [返回类总览](ReadWriteLock.md) - [返回类总览](ReadWriteLock.md)
- [返回模块目录](../Threading.md) - [ReadUnlock](ReadUnlock.md)
- [WriteLock](WriteLock.md)

View File

@@ -1,30 +1,23 @@
# ReadWriteLock::ReadUnlock # ReadWriteLock::ReadUnlock
公开方法,详见头文件声明 释放共享读锁
```cpp ```cpp
void ReadUnlock(); 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) - [返回类总览](ReadWriteLock.md)
- [返回模块目录](../Threading.md) - [ReadLock](ReadLock.md)

View File

@@ -6,30 +6,33 @@
**头文件**: `XCEngine/Threading/ReadWriteLock.h` **头文件**: `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) | 构造对象。 | | [Constructor](Constructor.md) | 默认构造读写锁。 |
| [~ReadWriteLock()](Destructor.md) | 销毁对象并释放相关资源。 | | [Destructor](Destructor.md) | 销毁读写锁。 |
| [ReadLock](ReadLock.md) | 公开方法,详见头文件声明。 | | [ReadLock](ReadLock.md) | 以共享方式进入。 |
| [ReadUnlock](ReadUnlock.md) | 公开方法,详见头文件声明。 | | [ReadUnlock](ReadUnlock.md) | 释放共享读锁。 |
| [WriteLock](WriteLock.md) | 公开方法,详见头文件声明。 | | [WriteLock](WriteLock.md) | 以独占方式进入。 |
| [WriteUnlock](WriteUnlock.md) | 公开方法,详见头文件声明。 | | [WriteUnlock](WriteUnlock.md) | 释放独占写锁。 |
## 相关文档 ## 相关文档
- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [Mutex](../Mutex/Mutex.md)

View File

@@ -1,30 +1,26 @@
# ReadWriteLock::WriteLock # ReadWriteLock::WriteLock
公开方法,详见头文件声明 以独占方式进入读写锁
```cpp ```cpp
void WriteLock(); 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) - [返回类总览](ReadWriteLock.md)
- [返回模块目录](../Threading.md) - [WriteUnlock](WriteUnlock.md)
- [ReadLock](ReadLock.md)

View File

@@ -1,30 +1,24 @@
# ReadWriteLock::WriteUnlock # ReadWriteLock::WriteUnlock
公开方法,详见头文件声明 释放独占写锁
```cpp ```cpp
void WriteUnlock(); 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) - [返回类总览](ReadWriteLock.md)
- [返回模块目录](../Threading.md) - [WriteLock](WriteLock.md)

View 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)

View File

@@ -6,30 +6,33 @@
**头文件**: `XCEngine/Threading/SpinLock.h` **头文件**: `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。
| 声明 | 类型 | 说明 | 这类锁通常只适合非常短的临界区,例如极小的元数据更新。商业引擎会保留它,是因为在高频、超短持锁窗口下,系统 mutex 的调度成本可能反而更高。
|------|------|------|
| `SpinLock` | `class` | 头文件中的公开声明。 |
## 公共方法 ## 当前实现边界
| 方法 | 描述 | - 失败时是空循环忙等,没有回退、没有 `Yield()`、没有 pause 指令。
- 没有公平性保证。
- 不是递归锁;同一线程重复进入会自旋死锁。
-`Mutex` 一样,同时提供了标准 Lockable 风格小写别名。
## 公开方法
| 方法 | 说明 |
|------|------| |------|------|
| [Lock](Lock.md) | 公开方法,详见头文件声明。 | | [Lock](Lock.md) | 阻塞自旋直到获得锁;同页也说明 `lock()` 别名。 |
| [Unlock](Unlock.md) | 公开方法,详见头文件声明。 | | [Unlock](Unlock.md) | 释放锁;同页也说明 `unlock()` 别名。 |
| [TryLock](TryLock.md) | 公开方法,详见头文件声明。 | | [TryLock](TryLock.md) | 尝试获得锁;同页也说明 `try_lock()` 别名。 |
| [lock](lock.md) | 公开方法,详见头文件声明。 |
| [unlock](unlock.md) | 公开方法,详见头文件声明。 |
| [try_lock](try_lock.md) | 公开方法,详见头文件声明。 |
## 相关文档 ## 相关文档
- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [Mutex](../Mutex/Mutex.md)

View File

@@ -1,30 +1,30 @@
# SpinLock::TryLock # SpinLock::TryLock
公开方法,详见头文件声明 尝试获得自旋锁
```cpp ```cpp
bool TryLock(); bool TryLock();
bool try_lock();
``` ```
该方法声明于 `XCEngine/Threading/SpinLock.h`,当前页面用于固定 `SpinLock` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 无。 当前实现有两套入口:
**返回:** `bool` - 返回值语义详见头文件声明 - `TryLock()`:引擎风格命名
- `try_lock()`:标准 Lockable 风格别名。
**示例:** 两者最终都调用同一份逻辑:
```cpp ```cpp
#include <XCEngine/Threading/SpinLock.h> return !m_flag.test_and_set(std::memory_order_acquire);
void Example() {
XCEngine::Threading::SpinLock object;
// 根据上下文补齐参数后调用 SpinLock::TryLock(...)。
(void)object;
}
``` ```
## 返回值
- `bool` - 成功获得锁时返回 `true`;否则返回 `false`
## 相关文档 ## 相关文档
- [返回类总览](SpinLock.md) - [返回类总览](SpinLock.md)
- [返回模块目录](../Threading.md) - [Lock](Lock.md)

View 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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -0,0 +1,24 @@
# ITask::AddRef
增加任务对象引用计数。
```cpp
void AddRef();
```
## 行为说明
当前头文件内联实现执行:
```cpp
m_refCount.fetch_add(1);
```
## 返回值
- 无。
## 相关文档
- [返回类型总览](Task.md)
- [Release](Release.md)

View File

@@ -0,0 +1,20 @@
# ITask::Destructor
通过基类指针安全销毁任务对象。
```cpp
virtual ~ITask() = default;
```
## 行为说明
虚析构函数保证派生任务能够通过 `ITask*` 正确析构。
## 返回值
- 无。
## 相关文档
- [返回类型总览](Task.md)
- [Release](Release.md)

View File

@@ -0,0 +1,20 @@
# ITask::Execute
执行任务主体。
```cpp
virtual void Execute() = 0;
```
## 行为说明
这是纯虚接口,具体任务逻辑由派生类实现。
## 返回值
- 无。
## 相关文档
- [返回类型总览](Task.md)
- [OnComplete](OnComplete.md)

View File

@@ -0,0 +1,20 @@
# ITask::GetId
读取任务 ID。
```cpp
uint64_t GetId() const;
```
## 行为说明
当前头文件内联实现直接返回 `m_id`
## 返回值
- `uint64_t` - 当前任务 ID。
## 相关文档
- [返回类型总览](Task.md)
- [SetId](SetId.md)

View File

@@ -0,0 +1,20 @@
# ITask::GetPriority
读取任务优先级。
```cpp
TaskPriority GetPriority() const;
```
## 行为说明
当前头文件内联实现直接返回 `m_priority`
## 返回值
- `TaskPriority` - 当前任务优先级。
## 相关文档
- [返回类型总览](Task.md)
- [SetPriority](SetPriority.md)

View File

@@ -0,0 +1,20 @@
# ITask::GetStatus
读取任务状态。
```cpp
TaskStatus GetStatus() const;
```
## 行为说明
当前头文件内联实现通过 `m_status.load()` 返回原子状态值。
## 返回值
- `TaskStatus` - 当前任务状态。
## 相关文档
- [返回类型总览](Task.md)
- [SetStatus](SetStatus.md)

View File

@@ -0,0 +1,20 @@
# ITask::OnCancel
任务取消时的回调钩子。
```cpp
virtual void OnCancel() {}
```
## 行为说明
当前基类默认实现为空,不做任何事。
## 返回值
- 无。
## 相关文档
- [返回类型总览](Task.md)
- [OnComplete](OnComplete.md)

View File

@@ -0,0 +1,20 @@
# ITask::OnComplete
任务完成后的回调钩子。
```cpp
virtual void OnComplete() {}
```
## 行为说明
当前基类默认实现为空,不做任何事。
## 返回值
- 无。
## 相关文档
- [返回类型总览](Task.md)
- [Execute](Execute.md)

View 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)

View File

@@ -0,0 +1,24 @@
# ITask::SetId
设置任务 ID。
```cpp
void SetId(uint64_t id);
```
## 行为说明
当前头文件内联实现直接执行 `m_id = id`
## 参数
- `id` - 要写入的任务 ID。
## 返回值
- 无。
## 相关文档
- [返回类型总览](Task.md)
- [GetId](GetId.md)

View File

@@ -0,0 +1,24 @@
# ITask::SetPriority
设置任务优先级。
```cpp
void SetPriority(TaskPriority priority);
```
## 行为说明
当前头文件内联实现直接执行 `m_priority = priority`
## 参数
- `priority` - 要写入的优先级。
## 返回值
- 无。
## 相关文档
- [返回类型总览](Task.md)
- [GetPriority](GetPriority.md)

View File

@@ -0,0 +1,24 @@
# ITask::SetStatus
设置任务状态。
```cpp
void SetStatus(TaskStatus status);
```
## 行为说明
当前头文件内联实现直接把 `status` 写入原子成员 `m_status`
## 参数
- `status` - 要写入的新状态。
## 返回值
- 无。
## 相关文档
- [返回类型总览](Task.md)
- [GetStatus](GetStatus.md)

View File

@@ -1,36 +1,74 @@
# Task # ITask
**命名空间**: `XCEngine::Threading` **命名空间**: `XCEngine::Threading`
**类型**: `enum class` **类型**: `class (abstract interface)` + `enum class`
**头文件**: `XCEngine/Threading/Task.h` **头文件**: `XCEngine/Threading/Task.h`
**描述**: 定义 `XCEngine/Threading` 子目录中的 `Task` public API **描述**: 定义任务优先级、任务状态以及带侵入式引用计数的抽象任务基类 `ITask`
## 概述 ## 概述
`Task.h` `XCEngine/Threading` 子目录 下的 public header当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 `Task.h` 暴露了三类核心概念:
## 声明概览 - `TaskPriority`:任务优先级枚举。
- `TaskStatus`:任务状态枚举。
- `ITask`:任务执行、完成回调、取消回调和引用计数的统一基类。
| 声明 | 类型 | 说明 | 这种设计很像很多商业引擎早期 job system 的起点:先用一个稳定任务抽象把“执行单元”统一起来,再围绕它搭调度器、主线程回调和任务组。
|------|------|------|
| `TaskPriority` | `enum class` | 头文件中的公开声明。 |
| `TaskStatus` | `enum class` | 头文件中的公开声明。 |
| `ITask` | `class` | 头文件中的公开声明。 |
## 枚举 ## 枚举
| 枚举值 | 数值 | 描述 | ### `TaskPriority`
|--------|------|------|
| `Critical` | `0` | 枚举项。 | 当前优先级从高到低依次是:
| `High` | `1` | 枚举项。 |
| `Normal` | `2` | 枚举项。 | - `Critical`
| `Low` | `3` | 枚举项。 | - `High`
| `Idle` | `4` | 枚举项。 | - `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` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [TaskSystem](../TaskSystem/TaskSystem.md)

View File

@@ -1,32 +1,44 @@
# TaskGroup::AddDependency # TaskGroup::AddDependency
添加元素或建立关联 记录一个任务对另一个任务的依赖关系
```cpp ```cpp
void AddDependency(uint64_t taskId, uint64_t dependsOn); void AddDependency(uint64_t taskId, uint64_t dependsOn);
``` ```
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前实现会在持锁状态下检查两个 ID 是否都位于 `m_tasks` 范围内;如果合法,就把 `dependsOn` 追加到 `m_tasks[taskId].dependencies`
- `taskId` - 参数语义详见头文件声明。
- `dependsOn` - 参数语义详见头文件声明。
**返回:** `void` - 无返回值 如果任一 ID 越界,函数会直接忽略这次调用
**示例:** ## 参数
```cpp - `taskId` - 依赖别人的任务。
#include <XCEngine/Threading/TaskGroup.h> - `dependsOn` - 被依赖的任务。
void Example() { ## 返回值
XCEngine::Threading::TaskGroup object;
// 根据上下文补齐参数后调用 TaskGroup::AddDependency(...) -
(void)object;
} ## 当前实现限制
```
- 当前只保存依赖 ID不会递增 `pendingDepCount`
- 当前没有环检测。
- 当前没有“依赖完成后解锁任务”的运行时逻辑。
- 由于 [TaskGroup](TaskGroup.md) 本身没有接入真正调度,这些依赖关系目前只是被记录下来,不会改变任务执行顺序。
## 设计说明
商业级任务系统里的依赖通常会驱动两个行为:
- 决定任务什么时候从 waiting 变成 ready。
- 决定整组任务什么时候可以触发 completion fence。
当前 `AddDependency()` 只覆盖了“数据结构里留一份关系记录”这一步。
## 相关文档 ## 相关文档
- [返回类总览](TaskGroup.md) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [AddTask](AddTask.md)
- [Wait](Wait.md)

View File

@@ -1,45 +1,52 @@
# TaskGroup::AddTask # TaskGroup::AddTask
添加元素或建立关联 向任务组添加一个任务对象或 lambda 任务
该方法在 `XCEngine/Threading/TaskGroup.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。
## 重载 1: 声明
```cpp ```cpp
uint64_t AddTask(std::unique_ptr<ITask> task); uint64_t AddTask(std::unique_ptr<ITask> task);
```
**参数:**
- `task` - 参数语义详见头文件声明。
**返回:** `uint64_t` - 返回值语义详见头文件声明。
## 重载 2: 声明
```cpp
uint64_t AddTask(Callback&& func, TaskPriority priority = TaskPriority::Normal); 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 `AddTask(Callback&&, TaskPriority)` 会先构造一个 `LambdaTask<Callback>`,然后转发到上面的重载。
#include <XCEngine/Threading/TaskGroup.h>
void Example() { ## 参数
XCEngine::Threading::TaskGroup object;
// 根据上下文补齐参数后调用 TaskGroup::AddTask(...) - `task` - 要加入任务组的任务对象
(void)object; - `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) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [AddDependency](AddDependency.md)
- [ITask](../Task/Task.md)
- [LambdaTask](../LambdaTask/LambdaTask.md)

View File

@@ -1,30 +1,44 @@
# TaskGroup::Cancel # TaskGroup::Cancel
判断当前条件下是否可执行 取消任务组中的未完成任务
```cpp ```cpp
void Cancel(); 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(...) - 当前不会把任务状态改成 `TaskStatus::Canceled`
(void)object; - 当前不会减少 `m_pendingCount`,因此也不会让 [Wait](Wait.md) / [IsComplete](IsComplete.md) 表现为“任务组结束了”。
} - 当前不会通知条件变量。
``` - 当前不会释放任务对象。
- `OnCancel()` 是在任务组内部锁保护下调用的;如果回调里再次操作同一个 `TaskGroup`,可能引入重入问题。
## 设计说明
真正可用的取消语义通常至少要覆盖三件事:
- 阻止尚未开始的任务继续进入执行。
- 让等待方得到确定的结束信号。
- 让任务对象生命周期仍然可控。
当前实现只覆盖了“通知任务自己被取消”这一层。
## 相关文档 ## 相关文档
- [返回类总览](TaskGroup.md) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [Wait](Wait.md)
- [ITask::OnCancel](../Task/OnCancel.md)

View File

@@ -1,28 +1,32 @@
# TaskGroup::TaskGroup() # TaskGroup::TaskGroup
构造对象 构造一个空的任务组
```cpp ```cpp
TaskGroup(); 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) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [TaskSystem::CreateTaskGroup](../TaskSystem/CreateTaskGroup.md)

View File

@@ -1,29 +1,32 @@
# TaskGroup::~TaskGroup() # TaskGroup::~TaskGroup
销毁对象并释放相关资源 销毁任务组对象。
```cpp ```cpp
~TaskGroup(); ~TaskGroup();
``` ```
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前析构函数是默认实现,不包含额外清理逻辑
**返回:** `void` - 无返回值 ## 返回值
**示例:** - 无。
```cpp ## 当前实现限制
#include <XCEngine/Threading/TaskGroup.h>
void Example() { - 当前不会释放 [AddTask](AddTask.md) 存入的裸任务指针。
XCEngine::Threading::TaskGroup object; - 如果你通过 `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) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [AddTask](AddTask.md)
- [TaskSystem::DestroyTaskGroup](../TaskSystem/DestroyTaskGroup.md)

View File

@@ -1,30 +1,32 @@
# TaskGroup::GetProgress # TaskGroup::GetProgress
获取相关状态或对象 返回任务组当前完成进度
```cpp ```cpp
float GetProgress() const; float GetProgress() const;
``` ```
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 无。 当前实现逻辑是:
**返回:** `float` - 返回值语义详见头文件声明 - 如果任务总数为 `0`,返回 `1.0f`
- 否则返回 `m_completedCount / m_tasks.size()`
**示例:** ## 返回值
```cpp - 取值范围目标上应在 `0.0f``1.0f` 之间。
#include <XCEngine/Threading/TaskGroup.h>
void Example() { ## 当前实现限制
XCEngine::Threading::TaskGroup object;
// 根据上下文补齐参数后调用 TaskGroup::GetProgress(...) - 当前源码里 `m_completedCount` 没有任何递增路径
(void)object; - 因此:
} - 空任务组返回 `1.0f`
``` - 只要添加过任务,当前几乎总是返回 `0.0f`
- 这个进度值当前不能反映真实执行进度。
## 相关文档 ## 相关文档
- [返回类总览](TaskGroup.md) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [IsComplete](IsComplete.md)
- [WaitFor](WaitFor.md)

View File

@@ -1,30 +1,32 @@
# TaskGroup::IsComplete # TaskGroup::IsComplete
查询当前状态 查询任务组是否完成
```cpp ```cpp
bool IsComplete() const; bool IsComplete() const;
``` ```
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 无。 当前实现直接返回:
**返回:** `bool` - 返回值语义详见头文件声明。
**示例:**
```cpp ```cpp
#include <XCEngine/Threading/TaskGroup.h> m_pendingCount.load() == 0
void Example() {
XCEngine::Threading::TaskGroup object;
// 根据上下文补齐参数后调用 TaskGroup::IsComplete(...)。
(void)object;
}
``` ```
## 返回值
-`m_pendingCount``0` 则返回 `true`
- 否则返回 `false`
## 当前实现限制
- 空任务组会返回 `true`
- 非空任务组当前通常会一直返回 `false`,因为源码里没有对应的递减逻辑。
- 这个结果也不会考虑 [Cancel](Cancel.md) 是否已调用。
## 相关文档 ## 相关文档
- [返回类总览](TaskGroup.md) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [Wait](Wait.md)
- [GetProgress](GetProgress.md)

View File

@@ -1,31 +1,39 @@
# TaskGroup::SetCompleteCallback # TaskGroup::SetCompleteCallback
设置相关状态或配置 设置任务组完成时要调用的回调函数
```cpp ```cpp
void SetCompleteCallback(Callback&& callback); void SetCompleteCallback(Callback&& callback);
``` ```
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前实现仅在持锁状态下把回调保存到 `m_completeCallback`
- `callback` - 参数语义详见头文件声明。
**返回:** `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) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [IsComplete](IsComplete.md)
- [Wait](Wait.md)

View File

@@ -6,34 +6,58 @@
**头文件**: `XCEngine/Threading/TaskGroup.h` **头文件**: `XCEngine/Threading/TaskGroup.h`
**描述**: 定义 `XCEngine/Threading` 子目录中的 `TaskGroup` public API **描述**: 表示一组带依赖关系的任务集合,目标是为任务批次提供等待、进度查询和完成回调入口
## 概述 ## 概述
`TaskGroup.h` `XCEngine/Threading` 子目录 下的 public header当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 `TaskGroup` 体现的是商业引擎里很常见的一个设计方向: 把一批相关任务组织成一个“组”,然后围绕这批任务暴露:
## 声明概览 - 批量添加任务。
- 任务之间的依赖关系。
- 整组完成等待。
- 整组完成回调。
- 进度查询与取消。
| 声明 | 类型 | 说明 | 这种抽象本身是合理的。像 Unity 的 job fence、Unreal 的 task graph event以及很多自研引擎里的 batch/fence/group 概念,本质上都在解决同一个问题: 上层系统往往关心“一批工作什么时候整体完成”,而不是只关心单个任务对象。
|------|------|------|
| `TaskGroup` | `class` | 头文件中的公开声明。 |
## 公共方法 ## 当前实现边界
| 方法 | 描述 | 当前 `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) | 构造对象。 | | [Constructor](Constructor.md) | 构造一个空任务组。 |
| [~TaskGroup()](Destructor.md) | 销毁对象并释放相关资源。 | | [Destructor](Destructor.md) | 销毁任务组对象。 |
| [AddTask](AddTask.md) | 添加元素或建立关联。 | | [AddTask](AddTask.md) | 向任务组添加一个任务或 lambda。 |
| [AddDependency](AddDependency.md) | 添加元素或建立关联。 | | [AddDependency](AddDependency.md) | 为任务记录依赖关系。 |
| [Wait](Wait.md) | 公开方法,详见头文件声明。 | | [Wait](Wait.md) | 阻塞等待任务组完成。 |
| [WaitFor](WaitFor.md) | 公开方法,详见头文件声明。 | | [WaitFor](WaitFor.md) | 限时等待任务组完成。 |
| [SetCompleteCallback](SetCompleteCallback.md) | 设置相关状态或配置。 | | [SetCompleteCallback](SetCompleteCallback.md) | 设置完成回调。 |
| [IsComplete](IsComplete.md) | 查询当前状态。 | | [IsComplete](IsComplete.md) | 查询任务组是否完成。 |
| [GetProgress](GetProgress.md) | 获取相关状态或对象。 | | [GetProgress](GetProgress.md) | 查询完成进度。 |
| [Cancel](Cancel.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` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [ITask](../Task/Task.md)
- [TaskSystem](../TaskSystem/TaskSystem.md)
- [Synchronization And Task System Limits](../../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md)

View File

@@ -1,30 +1,32 @@
# TaskGroup::Wait # TaskGroup::Wait
公开方法,详见头文件声明 阻塞当前线程,等待任务组完成
```cpp ```cpp
void Wait(); void Wait();
``` ```
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前实现会等待条件变量,直到谓词 `m_pendingCount.load() == 0` 为真
**返回:** `void` - 无返回值 ## 返回值
**示例:** - 无。
```cpp ## 当前实现限制
#include <XCEngine/Threading/TaskGroup.h>
void Example() { - 当前源码里 `m_pendingCount` 会在 [AddTask](AddTask.md) 时递增,但没有任何代码路径会把它递减。
XCEngine::Threading::TaskGroup object; - 这意味着只要任务组里添加过任务,`Wait()` 当前就不会因为正常任务完成而返回。
// 根据上下文补齐参数后调用 TaskGroup::Wait(...) - [Cancel](Cancel.md) 也不会通知条件变量,因此取消并不能唤醒这里的等待
(void)object;
} ## 使用建议
```
- 当前不要在生产代码中依赖这个接口实现真正的任务组同步。
- 如果你需要可靠同步,优先直接使用 [Thread::Join](../Thread/Join.md) 或更低层的锁/条件变量方案。
## 相关文档 ## 相关文档
- [返回类总览](TaskGroup.md) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [WaitFor](WaitFor.md)
- [IsComplete](IsComplete.md)

View File

@@ -1,31 +1,31 @@
# TaskGroup::WaitFor # TaskGroup::WaitFor
公开方法,详见头文件声明 在给定超时时间内等待任务组完成
```cpp ```cpp
bool WaitFor(std::chrono::milliseconds timeout); bool WaitFor(std::chrono::milliseconds timeout);
``` ```
该方法声明于 `XCEngine/Threading/TaskGroup.h`,当前页面用于固定 `TaskGroup` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前实现使用 `condition_variable::wait_for`,等待谓词 `m_pendingCount.load() == 0`
- `timeout` - 参数语义详见头文件声明。
**返回:** `bool` - 返回值语义详见头文件声明。 ## 参数
**示例:** - `timeout` - 最长等待时间。
```cpp ## 返回值
#include <XCEngine/Threading/TaskGroup.h>
void Example() { - 若谓词在超时前成立则返回 `true`
XCEngine::Threading::TaskGroup object; - 否则返回 `false`
// 根据上下文补齐参数后调用 TaskGroup::WaitFor(...)。
(void)object; ## 当前实现限制
}
``` - 与 [Wait](Wait.md) 一样,当前 `m_pendingCount` 只增不减,因此非空任务组几乎总会超时返回 `false`
- [Cancel](Cancel.md) 不会通知等待者,所以取消也不会帮助 `WaitFor()` 提前结束。
## 相关文档 ## 相关文档
- [返回类总览](TaskGroup.md) - [返回类总览](TaskGroup.md)
- [返回模块目录](../Threading.md) - [Wait](Wait.md)
- [GetProgress](GetProgress.md)

View File

@@ -1,30 +1,31 @@
# TaskSystem::CreateTaskGroup # TaskSystem::CreateTaskGroup
创建新对象或资源 创建一个新的任务组对象
```cpp ```cpp
TaskGroup* CreateTaskGroup(); TaskGroup* CreateTaskGroup();
``` ```
该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 无。 当前实现会:
**返回:** `TaskGroup*` - 返回值语义详见头文件声明 1. 通过 `new TaskGroup()` 分配一个任务组
2.`m_groupMutex` 保护下把该指针加入 `m_taskGroups`
3. 返回这个裸指针。
**示例:** ## 返回值
```cpp - 新创建的 `TaskGroup*`
#include <XCEngine/Threading/TaskSystem.h>
void Example() { ## 当前实现限制
XCEngine::Threading::TaskSystem object;
// 根据上下文补齐参数后调用 TaskSystem::CreateTaskGroup(...) - 当前只是在系统内部登记这个指针,并没有让任务组自动接入任务调度
(void)object; - 返回裸指针意味着所有权由调用方显式管理。
} - 当前 [Shutdown](Shutdown.md) 不会自动销毁这些任务组。
```
## 相关文档 ## 相关文档
- [返回类总览](TaskSystem.md) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [TaskGroup](../TaskGroup/TaskGroup.md)
- [DestroyTaskGroup](DestroyTaskGroup.md)

View File

@@ -1,31 +1,35 @@
# TaskSystem::DestroyTaskGroup # TaskSystem::DestroyTaskGroup
公开方法,详见头文件声明 销毁一个由任务系统创建的任务组
```cpp ```cpp
void DestroyTaskGroup(TaskGroup* group); void DestroyTaskGroup(TaskGroup* group);
``` ```
该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前实现会:
- `group` - 参数语义详见头文件声明。
**返回:** `void` - 无返回 1.`group == nullptr`,直接返回。
2.`m_groupMutex` 保护下,从 `m_taskGroups` 中查找并移除该指针。
3. 在锁外执行 `delete group`
**示例:** ## 参数
```cpp - `group` - 要销毁的任务组。
#include <XCEngine/Threading/TaskSystem.h>
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) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [CreateTaskGroup](CreateTaskGroup.md)
- [TaskGroup](../TaskGroup/TaskGroup.md)

View File

@@ -1,29 +1,30 @@
# TaskSystem::Get # TaskSystem::Get
获取相关状态或对象 取得全局任务系统单例
```cpp ```cpp
static TaskSystem& Get(); static TaskSystem& Get();
``` ```
该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 无。 当前实现返回一个函数内静态对象:
**返回:** `TaskSystem&` - 返回值语义详见头文件声明。
**示例:**
```cpp ```cpp
#include <XCEngine/Threading/TaskSystem.h> static TaskSystem instance;
void Example() {
auto& instance = XCEngine::Threading::TaskSystem::Get();
(void)instance;
}
``` ```
## 返回值
- `TaskSystem` 的全局唯一实例引用。
## 注意事项
- 取得实例并不会自动调用 [Initialize](Initialize.md)。
- 由于构造函数和析构函数是私有的,外部只能通过这个入口访问任务系统。
- 当前单例持有线程、队列和任务组列表,因此生命周期等同于整个进程内的静态对象生命周期。
## 相关文档 ## 相关文档
- [返回类总览](TaskSystem.md) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [Initialize](Initialize.md)

View File

@@ -1,30 +1,25 @@
# TaskSystem::GetWorkerThreadCount # TaskSystem::GetWorkerThreadCount
获取相关状态或对象 返回当前记录的工作线程数
```cpp ```cpp
uint32_t GetWorkerThreadCount() const; uint32_t GetWorkerThreadCount() const;
``` ```
该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前实现直接返回成员 `m_workerThreadCount`
**返回:** `uint32_t` - 返回值语义详见头文件声明。 ## 返回值
**示例:** - 当前配置的工作线程数量。
```cpp ## 注意事项
#include <XCEngine/Threading/TaskSystem.h>
void Example() { - 在 [Initialize](Initialize.md) 之前,这个值默认是 `0`
XCEngine::Threading::TaskSystem object; - 这个值表示“初始化时决定的目标线程数”,不表示当前仍然活跃的线程数量。
// 根据上下文补齐参数后调用 TaskSystem::GetWorkerThreadCount(...)。
(void)object;
}
```
## 相关文档 ## 相关文档
- [返回类总览](TaskSystem.md) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [Initialize](Initialize.md)

View File

@@ -1,31 +1,39 @@
# TaskSystem::Initialize # TaskSystem::Initialize
初始化内部状态 初始化任务系统并创建工作线程
```cpp ```cpp
void Initialize(const TaskSystemConfig& config); 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 - `config` - 任务系统初始化配置。
#include <XCEngine/Threading/TaskSystem.h>
void Example() { ## 返回值
XCEngine::Threading::TaskSystem object;
// 根据上下文补齐参数后调用 TaskSystem::Initialize(...) -
(void)object;
} ## 当前实现限制
```
- 当前只真正使用 `workerThreadCount`,其余配置字段都会被忽略。
- 当前没有防止重复初始化的保护;多次调用会继续往 `m_workerThreads` 里追加线程。
- 当前不会把 `m_shutdown` 重置回 `false`,因此一旦执行过 [Shutdown](Shutdown.md),再次 `Initialize()` 的行为是不完整的。
- 当前不会清空历史队列或主线程回调队列。
- 当前不会给工作线程命名,也没有线程绑定、栈大小或亲和性设置。
## 相关文档 ## 相关文档
- [返回类总览](TaskSystem.md) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [TaskSystemConfig](../TaskSystemConfig/TaskSystemConfig.md)
- [Shutdown](Shutdown.md)

View File

@@ -1,33 +1,54 @@
# TaskSystem::ParallelFor # TaskSystem::ParallelFor
公开方法,详见头文件声明 把一个整数区间拆分成多个任务并提交执行
```cpp ```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 - `start` - 起始索引,包含。
#include <XCEngine/Threading/TaskSystem.h> - `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) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [Submit](Submit.md)
- [Synchronization And Task System Limits](../../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md)

View File

@@ -1,31 +1,31 @@
# TaskSystem::RunOnMainThread # TaskSystem::RunOnMainThread
公开方法,详见头文件声明 把一个回调排入主线程执行队列
```cpp ```cpp
void RunOnMainThread(std::function<void()>&& func); void RunOnMainThread(std::function<void()>&& func);
``` ```
该方法声明于 `XCEngine/Threading/TaskSystem.h`,当前页面用于固定 `TaskSystem` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前实现会在 `m_queueMutex` 保护下把回调追加到 `m_mainThreadQueue`
- `func` - 参数语义详见头文件声明。
**返回:** `void` - 无返回值 这些回调不会立即执行,而是等待 [Update](Update.md) 被调用时再统一消费
**示例:** ## 参数
```cpp - `func` - 需要在主线程执行的回调。
#include <XCEngine/Threading/TaskSystem.h>
void Example() { ## 返回值
XCEngine::Threading::TaskSystem object;
// 根据上下文补齐参数后调用 TaskSystem::RunOnMainThread(...) -
(void)object;
} ## 注意事项
```
- 当前实现本身不检查调用线程是否为主线程;“主线程”只是通过谁来调用 [Update](Update.md) 约定出来的。
- 当前没有队列容量限制,也没有通知等待主线程的机制。
## 相关文档 ## 相关文档
- [返回类总览](TaskSystem.md) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [Update](Update.md)

View File

@@ -1,30 +1,45 @@
# TaskSystem::Shutdown # TaskSystem::Shutdown
关闭并清理内部状态 关闭任务系统并回收工作线程
```cpp ```cpp
void Shutdown(); 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(...) - 当前不会清空 `m_taskQueue`,未执行的任务会被直接遗留
(void)object; - 当前不会释放队列中残留任务对应的对象。
} - 当前不会销毁已经通过 [CreateTaskGroup](CreateTaskGroup.md) 创建的任务组。
``` - 当前不会清空 `m_mainThreadQueue`
- `m_shutdown` 会一直保持为 `true`,这使得重新初始化路径当前不可用。
## 设计说明
商业级任务系统的关闭通常需要定义明确的 shutdown policy例如
- 等待现有任务自然跑完。
- 取消可取消任务并清理资源。
- 强制丢弃队列但保证对象生命周期可回收。
当前实现只覆盖了“停线程”这一步。
## 相关文档 ## 相关文档
- [返回类总览](TaskSystem.md) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [Initialize](Initialize.md)
- [Submit](Submit.md)

View File

@@ -1,45 +1,57 @@
# TaskSystem::Submit # TaskSystem::Submit
公开方法,详见头文件声明 提交一个任务对象或 lambda 到任务系统
该方法在 `XCEngine/Threading/TaskSystem.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。
## 重载 1: 声明
```cpp ```cpp
uint64_t Submit(std::unique_ptr<ITask> task); uint64_t Submit(std::unique_ptr<ITask> task);
```
**参数:**
- `task` - 参数语义详见头文件声明。
**返回:** `uint64_t` - 返回值语义详见头文件声明。
## 重载 2: 声明
```cpp
uint64_t Submit(std::function<void()>&& func, TaskPriority priority = TaskPriority::Normal); 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 `Submit(std::function<void()>&&, TaskPriority)` 会先 `new LambdaTask<std::function<void()>>`,再把它包装成 `std::unique_ptr<ITask>` 转发给另一个重载。
#include <XCEngine/Threading/TaskSystem.h>
void Example() { ## 参数
XCEngine::Threading::TaskSystem object;
// 根据上下文补齐参数后调用 TaskSystem::Submit(...) - `task` - 要提交的任务对象
(void)object; - `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) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [ITask](../Task/Task.md)
- [LambdaTask](../LambdaTask/LambdaTask.md)
- [Wait](Wait.md)

View File

@@ -6,35 +6,72 @@
**头文件**: `XCEngine/Threading/TaskSystem.h` **头文件**: `XCEngine/Threading/TaskSystem.h`
**描述**: 定义 `XCEngine/Threading` 子目录中的 `TaskSystem` public API **描述**: 提供全局任务调度入口、工作线程池、主线程回调队列以及任务组创建接口
## 概述 ## 概述
`TaskSystem.h` `XCEngine/Threading` 子目录 下的 public header当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。 `TaskSystem` 想解决的是“把零散后台工作统一交给一套中央调度器管理”这个问题。它当前暴露的 API 形状已经覆盖了商用引擎任务系统常见的几个入口:
## 声明概览 - 单例式全局访问。
- 工作线程池初始化与关闭。
- 按优先级提交任务。
- 批量任务入口 `ParallelFor()`
- 任务组创建与销毁。
- 回投主线程的回调队列。
| 声明 | 类型 | 说明 | 这种设计方向本身是对的。商业级引擎很少要求上层系统自己手搓 `std::thread`,而是倾向于通过中央 job system 统一调度、限流、统计和同步。
|------|------|------|
| `TaskSystem` | `class` | 头文件中的公开声明。 |
## 公共方法 ## 当前实现边界
| 方法 | 描述 | 当前 `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) | 获取相关状态或对象。 | | [Get](Get.md) | 取得全局单例实例。 |
| [Initialize](Initialize.md) | 初始化内部状态。 | | [Initialize](Initialize.md) | 初始化工作线程池。 |
| [Shutdown](Shutdown.md) | 关闭并清理内部状态。 | | [Shutdown](Shutdown.md) | 停止工作线程并关闭系统。 |
| [Submit](Submit.md) | 公开方法,详见头文件声明。 | | [Submit](Submit.md) | 提交一个任务对象或 lambda。 |
| [CreateTaskGroup](CreateTaskGroup.md) | 创建新对象或资源。 | | [CreateTaskGroup](CreateTaskGroup.md) | 创建任务组。 |
| [DestroyTaskGroup](DestroyTaskGroup.md) | 公开方法,详见头文件声明。 | | [DestroyTaskGroup](DestroyTaskGroup.md) | 销毁任务组。 |
| [Wait](Wait.md) | 公开方法,详见头文件声明。 | | [Wait](Wait.md) | 等待指定任务完成。 |
| [GetWorkerThreadCount](GetWorkerThreadCount.md) | 获取相关状态或对象。 | | [GetWorkerThreadCount](GetWorkerThreadCount.md) | 查询当前配置的工作线程数。 |
| [Update](Update.md) | 更新运行时状态。 | | [Update](Update.md) | 执行主线程回调队列。 |
| [ParallelFor](ParallelFor.md) | 公开方法,详见头文件声明。 | | [ParallelFor](ParallelFor.md) | 把区间拆成多个高优先级任务提交。 |
| [RunOnMainThread](RunOnMainThread.md) | 公开方法,详见头文件声明。 | | [RunOnMainThread](RunOnMainThread.md) | 把回调排入主线程队列。 |
## 设计说明
为什么引擎仍然需要这样的中心化系统,而不是到处直接开线程:
- 线程数量需要统一治理,否则很容易过量创建后台线程。
- 优先级、主线程回投、profiling 和依赖图等能力,通常都需要一个公共调度中心。
- 资源加载、脚本预处理、导航构建、烘焙和编辑器后台任务,往往都需要共享同一套任务基础设施。
这也是为什么很多商业引擎会把“线程原语”和“任务系统”都保留下来:
- 锁和线程解决底层同步与平台适配问题。
- 任务系统解决更高层的批处理、吞吐量和生命周期协调问题。
## 使用建议
- 当前源码中,低层同步原语比 `TaskSystem` 更成熟。
- 如果确实要继续推进这个模块,优先修正任务所有权、队列同步、等待语义和关闭语义,再谈 profiling、work stealing 或任务依赖图。
## 相关文档 ## 相关文档
- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [TaskSystemConfig](../TaskSystemConfig/TaskSystemConfig.md)
- [TaskGroup](../TaskGroup/TaskGroup.md)
- [Synchronization And Task System Limits](../../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md)

View File

@@ -1,30 +1,34 @@
# TaskSystem::Update # TaskSystem::Update
更新运行时状态 执行当前积压的主线程回调
```cpp ```cpp
void Update(); 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) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [RunOnMainThread](RunOnMainThread.md)

View File

@@ -1,31 +1,36 @@
# TaskSystem::Wait # TaskSystem::Wait
公开方法,详见头文件声明 等待指定任务完成
```cpp ```cpp
void Wait(uint64_t taskId); 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) - [返回类总览](TaskSystem.md)
- [返回模块目录](../Threading.md) - [Submit](Submit.md)
- [TaskGroup::Wait](../TaskGroup/Wait.md)

View File

@@ -6,29 +6,29 @@
**头文件**: `XCEngine/Threading/TaskSystemConfig.h` **头文件**: `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` | 这说明 `TaskSystem` 目前更接近“先把 API 形状搭出来”,而不是已经把所有调度策略和平台细节真正接上。
| `enableTaskProfiling` | `bool` | 结构体公开字段。 | `true` |
| `stealTasks` | `bool` | 结构体公开字段。 | `true` |
| `maxTaskQueueSize` | `uint32_t` | 结构体公开字段。 | `1024` |
| `threadStackSize` | `uint32_t` | 结构体公开字段。 | `0` |
## 相关文档 ## 相关文档
- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [TaskSystem](../TaskSystem/TaskSystem.md)

View File

@@ -1,28 +1,24 @@
# Thread::Thread() # Thread::Constructor
构造对象。 构造一个空线程包装对象。
```cpp ```cpp
Thread(); 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) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [Start](Start.md)

View File

@@ -1,29 +1,26 @@
# Thread::~Thread() # Thread::Destructor
销毁对象并释放相关资源 销毁线程包装对象。
```cpp ```cpp
~Thread(); ~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) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [Join](Join.md)
- [Detach](Detach.md)

View File

@@ -1,30 +1,24 @@
# Thread::Detach # Thread::Detach
公开方法,详见头文件声明 分离线程
```cpp ```cpp
void Detach(); void Detach();
``` ```
该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前实现会在 `m_thread.joinable()` 时调用 `m_thread.detach()`;否则什么也不做
**返回:** `void` - 无返回值 ## 返回值
**示例:** - 无。
```cpp ## 注意事项
#include <XCEngine/Threading/Thread.h>
void Example() { - 一旦分离,线程执行与 `Thread` 对象生命周期脱钩,之后析构不会再 `Join()` 这条线程。
XCEngine::Threading::Thread object;
// 根据上下文补齐参数后调用 Thread::Detach(...)。
(void)object;
}
```
## 相关文档 ## 相关文档
- [返回类总览](Thread.md) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [Join](Join.md)

View File

@@ -1,30 +1,28 @@
# Thread::GetCurrentId # Thread::GetCurrentId
获取相关状态或对象 获取当前线程标识
```cpp ```cpp
static Id GetCurrentId(); 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 - `Id` - 当前线程的 hash 化标识值。
#include <XCEngine/Threading/Thread.h>
void Example() { ## 注意事项
XCEngine::Threading::Thread object;
// 根据上下文补齐参数后调用 Thread::GetCurrentId(...) - 这个值不是 [GetId](GetId.md) 所用的 `native_handle()` 转换结果,因此两者不是统一编码
(void)object;
}
```
## 相关文档 ## 相关文档
- [返回类总览](Thread.md) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [GetId](GetId.md)

View File

@@ -1,30 +1,26 @@
# Thread::GetId # Thread::GetId
获取相关状态或对象 获取缓存的线程标识
```cpp ```cpp
Id GetId() const; Id GetId() const;
``` ```
该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前头文件内联实现直接返回 `m_id`
**返回:** `Id` - 返回值语义详见头文件声明 这个值只在 [Start](Start.md) 里更新,来源是 `native_handle()` 转成整数
**示例:** ## 返回值
```cpp - `Id` - 当前缓存的线程标识;尚未启动时通常为 `0`
#include <XCEngine/Threading/Thread.h>
void Example() { ## 注意事项
XCEngine::Threading::Thread object;
// 根据上下文补齐参数后调用 Thread::GetId(...) - 这个值与 [GetCurrentId](GetCurrentId.md) 的实现口径不同,不应假设两者可以直接比较
(void)object;
}
```
## 相关文档 ## 相关文档
- [返回类总览](Thread.md) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [GetCurrentId](GetCurrentId.md)

View File

@@ -1,30 +1,24 @@
# Thread::GetName # Thread::GetName
获取相关状态或对象 获取保存的线程名称
```cpp ```cpp
const Containers::String& GetName() const; 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() { - 这只是 `Thread` 对象内部保存的名称字符串,不代表 OS 级线程名一定被设置。
XCEngine::Threading::Thread object;
// 根据上下文补齐参数后调用 Thread::GetName(...)。
(void)object;
}
```
## 相关文档 ## 相关文档
- [返回类总览](Thread.md) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [Start](Start.md)

View File

@@ -1,30 +1,20 @@
# Thread::Join # Thread::Join
公开方法,详见头文件声明 等待线程结束
```cpp ```cpp
void Join(); 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) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [Detach](Detach.md)

View File

@@ -1,31 +1,28 @@
# Thread::Sleep # Thread::Sleep
公开方法,详见头文件声明 让当前线程休眠指定毫秒数
```cpp ```cpp
static void Sleep(uint32_t milliseconds); static void Sleep(uint32_t milliseconds);
``` ```
该方法声明于 `XCEngine/Threading/Thread.h`,当前页面用于固定 `Thread` 类目录下的方法级 canonical 路径。 ## 行为说明
**参数:** 当前实现直接调用:
- `milliseconds` - 参数语义详见头文件声明。
**返回:** `void` - 无返回值。
**示例:**
```cpp ```cpp
#include <XCEngine/Threading/Thread.h> std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
void Example() {
XCEngine::Threading::Thread object;
// 根据上下文补齐参数后调用 Thread::Sleep(...)。
(void)object;
}
``` ```
## 参数
- `milliseconds` - 休眠时长,单位毫秒。
## 返回值
- 无。
## 相关文档 ## 相关文档
- [返回类总览](Thread.md) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [Yield](Yield.md)

View File

@@ -1,32 +1,36 @@
# Thread::Start # Thread::Start
公开方法,详见头文件声明 启动一个新线程
```cpp ```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 - `func` - 线程入口函数或可调用对象。
#include <XCEngine/Threading/Thread.h> - `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) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [GetId](GetId.md)

View File

@@ -6,34 +6,41 @@
**头文件**: `XCEngine/Threading/Thread.h` **头文件**: `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`
| 声明 | 类型 | 说明 | 这类包装在引擎里很常见,因为很多系统希望在不直接暴露标准库类型的前提下,统一线程 API、线程名和工具层调试信息。
|------|------|------|
| `Thread` | `class` | 头文件中的公开声明。 |
## 公共方法 ## 当前实现边界
| 方法 | 描述 | - [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) | 构造对象。 | | [Constructor](Constructor.md) | 构造空线程对象。 |
| [~Thread()](Destructor.md) | 销毁对象并释放相关资源。 | | [Destructor](Destructor.md) | 析构时自动 join。 |
| [Start](Start.md) | 公开方法,详见头文件声明。 | | [Start](Start.md) | 启动线程。 |
| [Join](Join.md) | 公开方法,详见头文件声明。 | | [Join](Join.md) | 等待线程结束。 |
| [Detach](Detach.md) | 公开方法,详见头文件声明。 | | [Detach](Detach.md) | 分离线程。 |
| [GetId](GetId.md) | 获取相关状态或对象。 | | [GetId](GetId.md) | 获取缓存的线程标识。 |
| [GetName](GetName.md) | 获取相关状态或对象。 | | [GetName](GetName.md) | 获取保存的线程名称。 |
| [GetCurrentId](GetCurrentId.md) | 获取相关状态或对象。 | | [GetCurrentId](GetCurrentId.md) | 获取当前线程标识。 |
| [Sleep](Sleep.md) | 公开方法,详见头文件声明。 | | [Sleep](Sleep.md) | 让当前线程休眠。 |
| [Yield](Yield.md) | 公开方法,详见头文件声明。 | | [Yield](Yield.md) | 让出当前线程时间片。 |
## 相关文档 ## 相关文档
- [当前目录](../Threading.md) - 返回 `Threading` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [Synchronization And Task System Limits](../../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md)

View File

@@ -1,30 +1,20 @@
# Thread::Yield # Thread::Yield
公开方法,详见头文件声明 让出当前线程时间片
```cpp ```cpp
static void Yield(); 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) - [返回类总览](Thread.md)
- [返回模块目录](../Threading.md) - [Sleep](Sleep.md)

View File

@@ -4,11 +4,42 @@
**类型**: `module` **类型**: `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` - [Thread](Thread/Thread.md) - `Thread.h`
- [Threading](Threading/Threading.md) - `Threading.h` - [Threading](Threading/Threading.md) - `Threading.h`
## 相关指南
- [Synchronization And Task System Limits](../../_guides/Threading/Synchronization-And-TaskSystem-Limits.md) - 解释为什么引擎要同时保留锁、线程和任务系统抽象,以及当前实现距离商业级 job system 还差哪些关键能力。
## 相关文档 ## 相关文档
- [上级目录](../XCEngine.md) - [上级目录](../XCEngine.md)

View File

@@ -1,18 +1,35 @@
# Threading # Threading
**命名空间**: `XCEngine` **命名空间**: `XCEngine::Threading`
**类型**: `header` **类型**: `header`
**头文件**: `XCEngine/Threading/Threading.h` **头文件**: `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` 平行目录 - [当前模块](../Threading.md)
- [API 总索引](../../../main.md) - 返回顶层索引 - [TaskSystem](../TaskSystem/TaskSystem.md)

View File

@@ -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)

View File

@@ -1,14 +1,14 @@
# API 文档重构状态 # API 文档重构状态
**生成时间**: `2026-03-26 19:32:04` **生成时间**: `2026-03-26 20:57:38`
**来源**: `docs/api/_tools/audit_api_docs.py` **来源**: `docs/api/_tools/audit_api_docs.py`
## 摘要 ## 摘要
- Markdown 页面数(全部): `2445` - Markdown 页面数(全部): `2456`
- Markdown 页面数canonical: `2436` - Markdown 页面数canonical: `2446`
- Public headers 数: `185` - Public headers 数: `204`
- 有效头文件引用数(全部): `185` - 有效头文件引用数(全部): `185`
- 有效头文件引用数canonical: `185` - 有效头文件引用数canonical: `185`
- 无效头文件引用数: `0` - 无效头文件引用数: `0`
@@ -20,9 +20,9 @@
## 平行目录 ## 平行目录
- Canonical 根目录: `XCEngine` - Canonical 根目录: `XCEngine`
- 源码目录节点数: `24` - 源码目录节点数: `27`
- 已生成目录总览页节点数: `24` - 已生成目录总览页节点数: `24`
- 缺失目录总览页节点数: `0` - 缺失目录总览页节点数: `3`
- 支撑目录: `_meta, _tools` - 支撑目录: `_meta, _tools`
## 模块覆盖 ## 模块覆盖
@@ -30,15 +30,17 @@
| 模块 | Public headers | 已覆盖 | 未覆盖 | | 模块 | Public headers | 已覆盖 | 未覆盖 |
|------|----------------|--------|--------| |------|----------------|--------|--------|
| `Audio` | `11` | `11` | `0` | | `Audio` | `11` | `11` | `0` |
| `Components` | `8` | `8` | `0` | | `Components` | `10` | `8` | `2` |
| `Core` | `42` | `42` | `0` | | `Core` | `42` | `42` | `0` |
| `Debug` | `10` | `10` | `0` | | `Debug` | `10` | `10` | `0` |
| `Input` | `5` | `5` | `0` | | `Input` | `5` | `5` | `0` |
| `Memory` | `5` | `5` | `0` | | `Memory` | `5` | `5` | `0` |
| `Platform` | `11` | `11` | `0` | | `Platform` | `11` | `11` | `0` |
| `RHI` | `68` | `68` | `0` | | `RHI` | `68` | `68` | `0` |
| `Rendering` | `10` | `0` | `10` |
| `Resources` | `13` | `13` | `0` | | `Resources` | `13` | `13` | `0` |
| `Scene` | `2` | `2` | `0` | | `Scene` | `3` | `2` | `1` |
| `Scripting` | `6` | `0` | `6` |
| `Threading` | `10` | `10` | `0` | | `Threading` | `10` | `10` | `0` |
## 元信息覆盖 ## 元信息覆盖
@@ -49,3 +51,31 @@
| `类型` | `208` | | `类型` | `208` |
| `描述` | `208` | | `描述` | `208` |
| `头文件` | `185` | | `头文件` | `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`