From fd792b7df1c8c3687e33cc4b350114a57c052eca Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Fri, 20 Mar 2026 02:35:24 +0800 Subject: [PATCH] docs: update memory and threading API docs --- docs/api/memory/allocator/allocator.md | 19 ++-- .../memory/allocator/get-peak-allocated.md | 4 +- docs/api/memory/allocator/get-total-freed.md | 8 +- .../memory/linear-allocator/constructor.md | 36 ++++++++ .../linear-allocator/get-allocation-count.md | 31 +++++++ .../api/memory/linear-allocator/get-marker.md | 6 +- docs/api/memory/linear-allocator/get-name.md | 27 ++++++ .../linear-allocator/get-peak-allocated.md | 33 +++++++ .../linear-allocator/get-total-allocated.md | 36 ++++++++ .../linear-allocator/get-total-freed.md | 30 ++++++ .../linear-allocator/linear-allocator.md | 62 ++++--------- .../linear-allocator/~linear-allocator.md | 2 +- docs/api/memory/manager/manager.md | 22 +++-- docs/api/memory/memory.md | 2 + .../memorymanager/createlinearallocator.md | 32 +++++++ .../memorymanager/createpoolallocator.md | 37 ++++++++ .../memorymanager/createproxyallocator.md | 36 ++++++++ .../memory/memorymanager/dumpmemoryleaks.md | 31 +++++++ .../memorymanager/generatememoryreport.md | 37 ++++++++ docs/api/memory/memorymanager/get.md | 39 ++++++++ .../memorymanager/getsystemallocator.md | 27 ++++++ docs/api/memory/memorymanager/initialize.md | 33 +++++++ .../api/memory/memorymanager/memorymanager.md | 85 +++++++++++++++++ .../memorymanager/settrackallocations.md | 35 +++++++ docs/api/memory/memorymanager/shutdown.md | 35 +++++++ docs/api/memory/pool-allocator/constructor.md | 40 ++++++++ .../pool-allocator/get-allocation-count.md | 40 ++++++++ .../memory/pool-allocator/get-block-size.md | 2 +- docs/api/memory/pool-allocator/get-name.md | 29 ++++++ .../pool-allocator/get-peak-allocated.md | 33 +++++++ .../pool-allocator/get-total-allocated.md | 33 +++++++ .../memory/pool-allocator/get-total-freed.md | 33 +++++++ .../memory/pool-allocator/pool-allocator.md | 25 +++-- docs/api/memory/proxy-allocator/free.md | 8 +- .../proxy-allocator/get-allocation-count.md | 37 ++++++++ docs/api/memory/proxy-allocator/get-name.md | 32 +++++++ .../proxy-allocator/get-peak-allocated.md | 37 ++++++++ .../proxy-allocator/get-total-allocated.md | 35 +++++++ .../memory/proxy-allocator/get-total-freed.md | 35 +++++++ .../memory/proxy-allocator/proxy-allocator.md | 17 ++-- docs/api/memory/proxy-allocator/reallocate.md | 2 +- .../proxy-allocator/~proxy-allocator.md | 37 -------- docs/api/threading/lambdatask/execute.md | 40 ++++++++ docs/api/threading/lambdatask/lambdatask.md | 2 +- docs/api/threading/mutex/lock.md | 2 +- docs/api/threading/mutex/lock_const.md | 43 +++++++++ docs/api/threading/mutex/mutex.md | 49 ++++++---- docs/api/threading/mutex/try_lock.md | 36 ++++++++ docs/api/threading/mutex/try_lock_const.md | 41 +++++++++ docs/api/threading/mutex/trylock.md | 2 +- docs/api/threading/mutex/unlock.md | 2 +- docs/api/threading/mutex/unlock_const.md | 34 +++++++ .../threading/readwritelock/constructor.md | 35 +++++++ .../api/threading/readwritelock/destructor.md | 40 ++++++++ docs/api/threading/readwritelock/readlock.md | 11 ++- .../api/threading/readwritelock/readunlock.md | 9 +- .../threading/readwritelock/readwritelock.md | 70 ++++++++++---- docs/api/threading/readwritelock/writelock.md | 10 +- .../threading/readwritelock/writeunlock.md | 15 ++- docs/api/threading/spinlock/lock.md | 2 +- docs/api/threading/spinlock/lock_1.md | 31 +++++++ docs/api/threading/spinlock/spinlock.md | 5 +- docs/api/threading/spinlock/try_lock.md | 32 +++++++ docs/api/threading/spinlock/unlock_1.md | 31 +++++++ .../threading/task-group/add-dependency.md | 90 ++++++++++++++++++ .../threading/task-group/add-task-callback.md | 55 +++++++++++ docs/api/threading/task-group/add-task.md | 62 +++++++++++++ .../api/threading/task-group/adddependency.md | 44 --------- docs/api/threading/task-group/addtask.md | 60 ------------ docs/api/threading/task-group/cancel.md | 52 ++++++----- docs/api/threading/task-group/get-progress.md | 50 ++++++++++ docs/api/threading/task-group/getprogress.md | 40 -------- docs/api/threading/task-group/is-complete.md | 50 ++++++++++ docs/api/threading/task-group/iscomplete.md | 38 -------- .../task-group/set-complete-callback.md | 82 +++++++++++++++++ .../task-group/setcompletecallback.md | 36 -------- docs/api/threading/task-group/task-group.md | 92 ++++++++++++------- .../api/threading/task-group/task-priority.md | 59 ++++++++++++ docs/api/threading/task-group/wait-for.md | 89 ++++++++++++++++++ docs/api/threading/task-group/wait.md | 51 +++++----- docs/api/threading/task-group/waitfor.md | 39 -------- .../threading/task-system/createtaskgroup.md | 2 + .../threading/task-system/destroytaskgroup.md | 2 + .../task-system/getworkerthreadcount.md | 2 + docs/api/threading/task-system/initialize.md | 2 + docs/api/threading/task-system/parallelfor.md | 2 + .../threading/task-system/runonmainthread.md | 2 + docs/api/threading/task-system/shutdown.md | 2 + docs/api/threading/task-system/submit.md | 12 ++- docs/api/threading/task-system/task-system.md | 5 +- docs/api/threading/task-system/update.md | 2 + docs/api/threading/task-system/wait.md | 11 +-- docs/api/threading/task/task.md | 9 +- docs/api/threading/thread/detach.md | 44 +++++---- docs/api/threading/thread/getcurrentid.md | 33 +++++-- docs/api/threading/thread/getid.md | 36 +++++--- docs/api/threading/thread/getname.md | 41 +++++++-- docs/api/threading/thread/join.md | 44 +++++---- docs/api/threading/thread/sleep.md | 25 +++-- docs/api/threading/thread/start.md | 40 +++++--- docs/api/threading/thread/thread.md | 45 +++++---- docs/api/threading/thread/yield.md | 44 +++++---- docs/api/threading/threading.md | 2 + 103 files changed, 2485 insertions(+), 673 deletions(-) create mode 100644 docs/api/memory/linear-allocator/constructor.md create mode 100644 docs/api/memory/linear-allocator/get-allocation-count.md create mode 100644 docs/api/memory/linear-allocator/get-name.md create mode 100644 docs/api/memory/linear-allocator/get-peak-allocated.md create mode 100644 docs/api/memory/linear-allocator/get-total-allocated.md create mode 100644 docs/api/memory/linear-allocator/get-total-freed.md create mode 100644 docs/api/memory/memorymanager/createlinearallocator.md create mode 100644 docs/api/memory/memorymanager/createpoolallocator.md create mode 100644 docs/api/memory/memorymanager/createproxyallocator.md create mode 100644 docs/api/memory/memorymanager/dumpmemoryleaks.md create mode 100644 docs/api/memory/memorymanager/generatememoryreport.md create mode 100644 docs/api/memory/memorymanager/get.md create mode 100644 docs/api/memory/memorymanager/getsystemallocator.md create mode 100644 docs/api/memory/memorymanager/initialize.md create mode 100644 docs/api/memory/memorymanager/memorymanager.md create mode 100644 docs/api/memory/memorymanager/settrackallocations.md create mode 100644 docs/api/memory/memorymanager/shutdown.md create mode 100644 docs/api/memory/pool-allocator/constructor.md create mode 100644 docs/api/memory/pool-allocator/get-allocation-count.md create mode 100644 docs/api/memory/pool-allocator/get-name.md create mode 100644 docs/api/memory/pool-allocator/get-peak-allocated.md create mode 100644 docs/api/memory/pool-allocator/get-total-allocated.md create mode 100644 docs/api/memory/pool-allocator/get-total-freed.md create mode 100644 docs/api/memory/proxy-allocator/get-allocation-count.md create mode 100644 docs/api/memory/proxy-allocator/get-name.md create mode 100644 docs/api/memory/proxy-allocator/get-peak-allocated.md create mode 100644 docs/api/memory/proxy-allocator/get-total-allocated.md create mode 100644 docs/api/memory/proxy-allocator/get-total-freed.md delete mode 100644 docs/api/memory/proxy-allocator/~proxy-allocator.md create mode 100644 docs/api/threading/lambdatask/execute.md create mode 100644 docs/api/threading/mutex/lock_const.md create mode 100644 docs/api/threading/mutex/try_lock.md create mode 100644 docs/api/threading/mutex/try_lock_const.md create mode 100644 docs/api/threading/mutex/unlock_const.md create mode 100644 docs/api/threading/readwritelock/constructor.md create mode 100644 docs/api/threading/readwritelock/destructor.md create mode 100644 docs/api/threading/spinlock/lock_1.md create mode 100644 docs/api/threading/spinlock/try_lock.md create mode 100644 docs/api/threading/spinlock/unlock_1.md create mode 100644 docs/api/threading/task-group/add-dependency.md create mode 100644 docs/api/threading/task-group/add-task-callback.md create mode 100644 docs/api/threading/task-group/add-task.md delete mode 100644 docs/api/threading/task-group/adddependency.md delete mode 100644 docs/api/threading/task-group/addtask.md create mode 100644 docs/api/threading/task-group/get-progress.md delete mode 100644 docs/api/threading/task-group/getprogress.md create mode 100644 docs/api/threading/task-group/is-complete.md delete mode 100644 docs/api/threading/task-group/iscomplete.md create mode 100644 docs/api/threading/task-group/set-complete-callback.md delete mode 100644 docs/api/threading/task-group/setcompletecallback.md create mode 100644 docs/api/threading/task-group/task-priority.md create mode 100644 docs/api/threading/task-group/wait-for.md delete mode 100644 docs/api/threading/task-group/waitfor.md diff --git a/docs/api/memory/allocator/allocator.md b/docs/api/memory/allocator/allocator.md index 5a9f19c2..0e9293d0 100644 --- a/docs/api/memory/allocator/allocator.md +++ b/docs/api/memory/allocator/allocator.md @@ -4,6 +4,8 @@ **类型**: `class` (abstract interface) +**头文件**: `XCEngine/Memory/Allocator.h` + **描述**: 内存分配器抽象接口,定义标准分配协议。 ## 概述 @@ -16,24 +18,24 @@ | 方法 | 描述 | |------|------| -| `Allocate` | 分配内存 | -| `Free` | 释放内存 | -| `Reallocate` | 重新分配内存 | +| [`Allocate`](allocate.md) | 分配内存 | +| [`Free`](free.md) | 释放内存 | +| [`Reallocate`](reallocate.md) | 重新分配内存 | ### 统计信息 | 方法 | 描述 | |------|------| -| `GetTotalAllocated` | 获取已分配总字节数 | -| `GetTotalFreed` | 获取已释放总字节数 | -| `GetPeakAllocated` | 获取峰值分配字节数 | -| `GetAllocationCount` | 获取分配次数 | +| [`GetTotalAllocated`](get-total-allocated.md) | 获取已分配总字节数 | +| [`GetTotalFreed`](get-total-freed.md) | 获取已释放总字节数 | +| [`GetPeakAllocated`](get-peak-allocated.md) | 获取峰值分配字节数 | +| [`GetAllocationCount`](get-allocation-count.md) | 获取分配次数 | ### 元信息 | 方法 | 描述 | |------|------| -| `GetName` | 获取分配器名称 | +| [`GetName`](get-name.md) | 获取分配器名称 | ## 使用示例 @@ -70,3 +72,4 @@ public: - [MemoryManager](../manager/manager.md) - 内存管理器 - [LinearAllocator](../linear-allocator/linear-allocator.md) - 线性分配器 - [PoolAllocator](../pool-allocator/pool-allocator.md) - 内存池分配器 +- [ProxyAllocator](../proxy-allocator/proxy-allocator.md) - 代理分配器 diff --git a/docs/api/memory/allocator/get-peak-allocated.md b/docs/api/memory/allocator/get-peak-allocated.md index da1f31e4..9fb7f03c 100644 --- a/docs/api/memory/allocator/get-peak-allocated.md +++ b/docs/api/memory/allocator/get-peak-allocated.md @@ -30,9 +30,9 @@ public: void Free(void* ptr) override { if (ptr) { - size_t size = 256; // 需要外部记录 + // size 需要分配器内部记录或通过其他机制获取 ::operator delete(ptr); - m_current -= size; + m_current -= 256; // 示例中硬编码 } } diff --git a/docs/api/memory/allocator/get-total-freed.md b/docs/api/memory/allocator/get-total-freed.md index 4f1d5bdb..ee9cb385 100644 --- a/docs/api/memory/allocator/get-total-freed.md +++ b/docs/api/memory/allocator/get-total-freed.md @@ -18,22 +18,20 @@ virtual size_t GetTotalFreed() const = 0; #include class MyAllocator : public IAllocator { - size_t m_freed = 0; public: void* Allocate(size_t size, size_t alignment = 0) override { return ::operator new(size); } void Free(void* ptr) override { if (ptr) { - size_t size = 256; // 需要外部记录 + // size 需要分配器内部记录或通过其他机制获取 ::operator delete(ptr); - m_freed += size; } } void* Reallocate(void* ptr, size_t newSize) override { /* ... */ } size_t GetTotalAllocated() const override { return 0; } - size_t GetTotalFreed() const override { return m_freed; } + size_t GetTotalFreed() const override { return 0; } // 示例未实际统计 size_t GetPeakAllocated() const override { return 0; } size_t GetAllocationCount() const override { return 0; } const char* GetName() const override { return "MyAllocator"; } @@ -42,7 +40,7 @@ public: MyAllocator alloc; void* ptr = alloc.Allocate(128); alloc.Free(ptr); -size_t freed = alloc.GetTotalFreed(); // 返回 128 +size_t freed = alloc.GetTotalFreed(); // 返回 0(示例未统计) ``` ## 相关文档 diff --git a/docs/api/memory/linear-allocator/constructor.md b/docs/api/memory/linear-allocator/constructor.md new file mode 100644 index 00000000..8fe40fd4 --- /dev/null +++ b/docs/api/memory/linear-allocator/constructor.md @@ -0,0 +1,36 @@ +# LinearAllocator::LinearAllocator + +```cpp +explicit LinearAllocator(size_t size, IAllocator* parent = nullptr); +``` + +构造一个线性分配器,预分配指定大小的缓冲区。如果提供了 `parent` 分配器,则使用它分配底层缓冲区;否则使用系统默认分配(`_aligned_malloc`,8 字节对齐)。 + +**参数:** +- `size` - 预分配的缓冲区大小(字节数) +- `parent` - 父分配器,用于分配底层缓冲区,默认为 `nullptr`(使用系统分配) + +**返回:** 无 + +**复杂度:** O(n),需要分配 `size` 大小的缓冲区 + +**示例:** + +```cpp +#include + +// 使用系统分配器创建 1MB 线性分配器 +LinearAllocator allocator1(1024 * 1024); + +// 使用指定的父分配器 +IAllocator* parent = MemoryManager::Get().GetSystemAllocator(); +LinearAllocator allocator2(1024 * 1024, parent); + +// 默认 8 字节对齐 +void* ptr = allocator1.Allocate(256); +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 +- [IAllocator](../allocator/allocator.md) - 分配器接口 diff --git a/docs/api/memory/linear-allocator/get-allocation-count.md b/docs/api/memory/linear-allocator/get-allocation-count.md new file mode 100644 index 00000000..852c0744 --- /dev/null +++ b/docs/api/memory/linear-allocator/get-allocation-count.md @@ -0,0 +1,31 @@ +# LinearAllocator::GetAllocationCount + +```cpp +size_t GetAllocationCount() const override; +``` + +返回自分配器创建以来的累计分配次数。线性分配器不支持单个块释放,始终返回 0。 + +**参数:** 无 + +**返回:** 始终返回 `0` + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); + +allocator.Allocate(256); +allocator.Allocate(128); +allocator.Allocate(64); + +size_t count = allocator.GetAllocationCount(); // 0(不支持计数) +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/linear-allocator/get-marker.md b/docs/api/memory/linear-allocator/get-marker.md index 73bcf41e..7d335ee4 100644 --- a/docs/api/memory/linear-allocator/get-marker.md +++ b/docs/api/memory/linear-allocator/get-marker.md @@ -4,13 +4,13 @@ void* GetMarker() const; ``` -获取当前分配位置的标记。标记是内部偏移量(`m_offset`)的快照,可用于 `SetMarker` 恢复到该位置。此方法用于实现临时分配的撤销功能。 +获取当前分配位置的标记。标记是内部偏移量(`m_offset`)的快照,以 `void*` 类型返回。将此值传给 `SetMarker` 可恢复到该位置。此方法用于实现临时分配的撤销功能。 **参数:** 无 -**返回:** 当前位置标记(偏移量值),类型为 `void*` +**返回:** 当前位置标记(偏移量值,类型为 `void*`) -**注意:** 返回值是偏移量数值,不是指针。将其传给 `SetMarker` 可恢复到此分配位置。 +**注意:** 返回值是偏移量数值的指针表示,不是真实内存指针。将其传给 `SetMarker` 可恢复到此分配位置。 **复杂度:** O(1) diff --git a/docs/api/memory/linear-allocator/get-name.md b/docs/api/memory/linear-allocator/get-name.md new file mode 100644 index 00000000..01cccc58 --- /dev/null +++ b/docs/api/memory/linear-allocator/get-name.md @@ -0,0 +1,27 @@ +# LinearAllocator::GetName + +```cpp +const char* GetName() const override; +``` + +返回分配器的名称字符串,用于调试和日志输出。 + +**参数:** 无 + +**返回:** 固定返回 `"LinearAllocator"` + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); + +const char* name = allocator.GetName(); // "LinearAllocator" +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/linear-allocator/get-peak-allocated.md b/docs/api/memory/linear-allocator/get-peak-allocated.md new file mode 100644 index 00000000..18ac10e5 --- /dev/null +++ b/docs/api/memory/linear-allocator/get-peak-allocated.md @@ -0,0 +1,33 @@ +# LinearAllocator::GetPeakAllocated + +```cpp +size_t GetPeakAllocated() const override; +``` + +返回自分配器创建以来的峰值分配字节数。对于线性分配器,这等于总容量(`m_capacity`)。 + +**参数:** 无 + +**返回:** 峰值分配字节数(等于容量) + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); + +size_t peak = allocator.GetPeakAllocated(); // 1024(容量) + +allocator.Allocate(512); +size_t used = allocator.GetUsedSize(); // 512 + +// 即使未达到容量,峰值仍为容量大小 +size_t peak_after = allocator.GetPeakAllocated(); // 1024 +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/linear-allocator/get-total-allocated.md b/docs/api/memory/linear-allocator/get-total-allocated.md new file mode 100644 index 00000000..efa78f4b --- /dev/null +++ b/docs/api/memory/linear-allocator/get-total-allocated.md @@ -0,0 +1,36 @@ +# LinearAllocator::GetTotalAllocated + +```cpp +size_t GetTotalAllocated() const override; +``` + +返回自分配器创建以来的累计分配字节数。对于线性分配器,这等于当前已使用的字节数(`m_offset`)。 + +**参数:** 无 + +**返回:** 累计已分配的字节数 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); + +size_t total1 = allocator.GetTotalAllocated(); // 0 + +allocator.Allocate(256); +allocator.Allocate(128); + +size_t total2 = allocator.GetTotalAllocated(); // 384 + +allocator.Clear(); + +size_t total3 = allocator.GetTotalAllocated(); // 0(Clear 后重置) +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/linear-allocator/get-total-freed.md b/docs/api/memory/linear-allocator/get-total-freed.md new file mode 100644 index 00000000..ce5a375a --- /dev/null +++ b/docs/api/memory/linear-allocator/get-total-freed.md @@ -0,0 +1,30 @@ +# LinearAllocator::GetTotalFreed + +```cpp +size_t GetTotalFreed() const override; +``` + +返回自分配器创建以来的累计释放字节数。线性分配器不支持单个块释放,始终返回 0。 + +**参数:** 无 + +**返回:** 始终返回 `0` + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); + +void* ptr = allocator.Allocate(256); +allocator.Free(ptr); // 无实际效果 + +size_t freed = allocator.GetTotalFreed(); // 0 +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/linear-allocator/linear-allocator.md b/docs/api/memory/linear-allocator/linear-allocator.md index 5da70dd3..003af947 100644 --- a/docs/api/memory/linear-allocator/linear-allocator.md +++ b/docs/api/memory/linear-allocator/linear-allocator.md @@ -4,6 +4,8 @@ **类型**: `class` +**头文件**: `XCEngine/Memory/LinearAllocator.h` + **描述**: 线性分配器,适合帧分配和临时对象。 ## 概述 @@ -14,51 +16,21 @@ | 方法 | 描述 | |------|------| -| `LinearAllocator` | 构造线性分配器 | -| `~LinearAllocator` | 析构函数,释放底层缓冲区 | -| `Allocate` | 顺序分配内存 | -| `Free` | 无效果(不支持) | -| `Reallocate` | 不支持(始终返回 nullptr) | -| `Clear` | 清空所有分配 | -| `GetMarker` | 获取当前位置标记 | -| `SetMarker` | 回滚到指定标记位置 | -| `GetUsedSize` | 获取已使用字节数 | -| `GetCapacity` | 获取总容量 | - -## 构造函数 - -```cpp -explicit LinearAllocator(size_t size, IAllocator* parent = nullptr); -~LinearAllocator() override; -``` - -构造一个线性分配器,预分配指定大小的缓冲区。如果提供了 `parent` 分配器,则使用它分配底层缓冲区;否则使用系统默认分配(`_aligned_malloc`,8 字节对齐)。 - -**参数:** -- `size` - 预分配的缓冲区大小(字节数) -- `parent` - 父分配器,用于分配底层缓冲区,默认为 `nullptr`(使用系统分配) - -**返回:** 无 - -**复杂度:** O(n),需要分配 `size` 大小的缓冲区 - -**注意:** `Free` 和 `Reallocate` 方法无实际效果。`Free` 是空操作,`Reallocate` 始终返回 `nullptr`。 - -**示例:** - -```cpp -#include - -// 使用系统分配器创建 1MB 线性分配器 -LinearAllocator allocator1(1024 * 1024); - -// 使用指定的父分配器 -IAllocator* parent = MemoryManager::Get().GetSystemAllocator(); -LinearAllocator allocator2(1024 * 1024, parent); - -// 默认 8 字节对齐 -void* ptr = allocator1.Allocate(256); -``` +| [`LinearAllocator`](constructor.md) | 构造线性分配器 | +| [`~LinearAllocator`](~linear-allocator.md) | 析构函数,释放底层缓冲区 | +| [`Allocate`](allocate.md) | 顺序分配内存 | +| [`Free`](free.md) | 无效果(不支持) | +| [`Reallocate`](reallocate.md) | 不支持(始终返回 nullptr) | +| [`Clear`](clear.md) | 清空所有分配 | +| [`GetMarker`](get-marker.md) | 获取当前位置标记 | +| [`SetMarker`](set-marker.md) | 回滚到指定标记位置 | +| [`GetUsedSize`](get-used-size.md) | 获取已使用字节数 | +| [`GetCapacity`](get-capacity.md) | 获取总容量 | +| [`GetName`](get-name.md) | 获取分配器名称 | +| [`GetTotalAllocated`](get-total-allocated.md) | 获取累计分配字节数 | +| [`GetTotalFreed`](get-total-freed.md) | 获取累计释放字节数 | +| [`GetPeakAllocated`](get-peak-allocated.md) | 获取峰值分配字节数 | +| [`GetAllocationCount`](get-allocation-count.md) | 获取分配次数 | ## 相关文档 diff --git a/docs/api/memory/linear-allocator/~linear-allocator.md b/docs/api/memory/linear-allocator/~linear-allocator.md index b7c2384c..9112c655 100644 --- a/docs/api/memory/linear-allocator/~linear-allocator.md +++ b/docs/api/memory/linear-allocator/~linear-allocator.md @@ -4,7 +4,7 @@ ~LinearAllocator() override; ``` -销毁线性分配器,释放预分配的缓冲区。如果提供了 `parent` 分配器,则使用它释放缓冲区;否则使用系统默认释放(`::operator delete`)。 +销毁线性分配器,释放预分配的缓冲区。如果提供了 `parent` 分配器,则使用它释放缓冲区;否则使用系统默认释放(`_aligned_free`)。 **参数:** 无 diff --git a/docs/api/memory/manager/manager.md b/docs/api/memory/manager/manager.md index 10061e26..940b17a0 100644 --- a/docs/api/memory/manager/manager.md +++ b/docs/api/memory/manager/manager.md @@ -4,6 +4,8 @@ **类型**: `class` (singleton) +**头文件**: `XCEngine/Memory/MemoryManager.h` + **描述**: 全局内存管理器单例,提供系统分配器和各种专用分配器的创建。 ## 概述 @@ -14,21 +16,21 @@ | 方法 | 描述 | |------|------| -| `Get` | 获取单例实例 | +| [`Get`](get.md) | 获取单例实例 | ## 公共方法 | 方法 | 描述 | |------|------| -| `Initialize` | 初始化内存管理器 | -| `Shutdown` | 关闭内存管理器 | -| `GetSystemAllocator` | 获取系统默认分配器 | -| `CreateLinearAllocator` | 创建线性分配器 | -| `CreatePoolAllocator` | 创建内存池分配器 | -| `CreateProxyAllocator` | 创建代理分配器 | -| `SetTrackAllocations` | 设置是否跟踪分配 | -| `DumpMemoryLeaks` | 输出内存泄漏报告 | -| `GenerateMemoryReport` | 生成内存使用报告 | +| [`Initialize`](initialize.md) | 初始化内存管理器 | +| [`Shutdown`](shutdown.md) | 关闭内存管理器 | +| [`GetSystemAllocator`](get-system-allocator.md) | 获取系统默认分配器 | +| [`CreateLinearAllocator`](create-linear-allocator.md) | 创建线性分配器 | +| [`CreatePoolAllocator`](create-pool-allocator.md) | 创建内存池分配器 | +| [`CreateProxyAllocator`](create-proxy-allocator.md) | 创建代理分配器 | +| [`SetTrackAllocations`](set-track-allocations.md) | 设置是否跟踪分配 | +| [`DumpMemoryLeaks`](dump-memory-leaks.md) | 输出内存泄漏报告 | +| [`GenerateMemoryReport`](generate-memory-report.md) | 生成内存使用报告 | ## 宏定义 diff --git a/docs/api/memory/memory.md b/docs/api/memory/memory.md index dae159f7..64e17eb6 100644 --- a/docs/api/memory/memory.md +++ b/docs/api/memory/memory.md @@ -4,6 +4,8 @@ **类型**: `module` +**头文件**: `XCEngine/Memory/Memory.h` + **描述**: XCEngine 的内存管理模块,提供多种内存分配器实现。 ## 概述 diff --git a/docs/api/memory/memorymanager/createlinearallocator.md b/docs/api/memory/memorymanager/createlinearallocator.md new file mode 100644 index 00000000..bc2bffce --- /dev/null +++ b/docs/api/memory/memorymanager/createlinearallocator.md @@ -0,0 +1,32 @@ +# MemoryManager::CreateLinearAllocator + +```cpp +std::unique_ptr CreateLinearAllocator(size_t size); +``` + +创建并返回一个新的 LinearAllocator 实例,使用系统分配器作为底层。返回的 `unique_ptr` 管理分配器生命周期。 + +**参数:** +- `size` - 分配器缓冲区大小(字节) + +**返回:** LinearAllocator 的 unique_ptr + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +auto linear = MemoryManager::Get().CreateLinearAllocator(1024 * 1024); +void* ptr = linear->Allocate(256); +void* marker = linear->GetMarker(); +linear->Allocate(128); +linear->SetMarker(marker); +linear->Clear(); +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 +- [LinearAllocator](../linear-allocator/linear-allocator.md) - 线性分配器 diff --git a/docs/api/memory/memorymanager/createpoolallocator.md b/docs/api/memory/memorymanager/createpoolallocator.md new file mode 100644 index 00000000..9b993f44 --- /dev/null +++ b/docs/api/memory/memorymanager/createpoolallocator.md @@ -0,0 +1,37 @@ +# MemoryManager::CreatePoolAllocator + +```cpp +std::unique_ptr CreatePoolAllocator(size_t blockSize, size_t count); +``` + +创建并返回一个新的 PoolAllocator 实例,使用系统分配器作为底层。返回的 `unique_ptr` 管理分配器生命周期。 + +**参数:** +- `blockSize` - 每个内存块的大小(字节) +- `count` - 内存池中块的数量 + +**返回:** PoolAllocator 的 unique_ptr + +**复杂度:** O(blockSize * count)(需要预分配所有块) + +**示例:** + +```cpp +#include + +struct Particle { + float x, y, z; + float life; +}; + +auto pool = MemoryManager::Get().CreatePoolAllocator(sizeof(Particle), 1000); +void* block = pool->Allocate(); +auto* p = new (block) Particle{1.0f, 2.0f, 3.0f, 5.0f}; +p->~Particle(); +pool->Free(block); +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 +- [PoolAllocator](../pool-allocator/pool-allocator.md) - 内存池分配器 diff --git a/docs/api/memory/memorymanager/createproxyallocator.md b/docs/api/memory/memorymanager/createproxyallocator.md new file mode 100644 index 00000000..184611df --- /dev/null +++ b/docs/api/memory/memorymanager/createproxyallocator.md @@ -0,0 +1,36 @@ +# MemoryManager::CreateProxyAllocator + +```cpp +std::unique_ptr CreateProxyAllocator(const char* name); +``` + +创建并返回一个新的 ProxyAllocator 实例,包装系统分配器并使用指定名称。返回的 `unique_ptr` 管理分配器生命周期。 + +**参数:** +- `name` - 代理分配器的名称 + +**返回:** ProxyAllocator 的 unique_ptr + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +auto proxy = MemoryManager::Get().CreateProxyAllocator("FrameData"); +void* ptr = proxy->Allocate(1024); +void* ptr2 = proxy->Allocate(512); + +const auto& stats = proxy->GetStats(); +printf("Peak: %zu bytes, Count: %zu\n", + stats.peakAllocated, stats.allocationCount); + +proxy->Free(ptr); +proxy->Free(ptr2); +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 +- [ProxyAllocator](../proxy-allocator/proxy-allocator.md) - 代理分配器 diff --git a/docs/api/memory/memorymanager/dumpmemoryleaks.md b/docs/api/memory/memorymanager/dumpmemoryleaks.md new file mode 100644 index 00000000..09bfe9f9 --- /dev/null +++ b/docs/api/memory/memorymanager/dumpmemoryleaks.md @@ -0,0 +1,31 @@ +# MemoryManager::DumpMemoryLeaks + +```cpp +void DumpMemoryLeaks(); +``` + +输出当前未释放的内存分配信息。如果启用了内存跟踪,此方法会遍历所有记录并报告疑似泄漏的分配。应在程序退出前调用,以便发现资源泄漏。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +#include + +MemoryManager::Get().Initialize(); + +// ... 程序运行 ... + +// 程序退出前检查泄漏 +MemoryManager::Get().DumpMemoryLeaks(); +MemoryManager::Get().Shutdown(); +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 diff --git a/docs/api/memory/memorymanager/generatememoryreport.md b/docs/api/memory/memorymanager/generatememoryreport.md new file mode 100644 index 00000000..de0e1109 --- /dev/null +++ b/docs/api/memory/memorymanager/generatememoryreport.md @@ -0,0 +1,37 @@ +# MemoryManager::GenerateMemoryReport + +```cpp +void GenerateMemoryReport(); +``` + +生成并输出当前内存使用情况的详细报告。报告内容包括各分配器的统计信息、峰值使用量、分配次数等。应在启用内存跟踪后调用。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +#include + +MemoryManager::Get().Initialize(); + +auto proxy = MemoryManager::Get().CreateProxyAllocator("GameFrame"); +proxy->Allocate(1024 * 1024); +proxy->Allocate(512 * 1024); + +// 生成内存报告 +MemoryManager::Get().GenerateMemoryReport(); + +proxy->Free(proxy->Allocate(256 * 1024)); +MemoryManager::Get().GenerateMemoryReport(); + +MemoryManager::Get().Shutdown(); +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 diff --git a/docs/api/memory/memorymanager/get.md b/docs/api/memory/memorymanager/get.md new file mode 100644 index 00000000..6e117beb --- /dev/null +++ b/docs/api/memory/memorymanager/get.md @@ -0,0 +1,39 @@ +# MemoryManager::Get + +```cpp +static MemoryManager& Get(); +``` + +获取 MemoryManager 单例实例。如果尚未创建则内部构造。此方法是获取内存管理器实例的唯一途径。 + +**参数:** 无 + +**返回:** MemoryManager 单例引用 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +// 获取单例 +MemoryManager& manager = MemoryManager::Get(); + +// 初始化 +manager.Initialize(); + +// 访问系统分配器 +IAllocator* sysAlloc = manager.GetSystemAllocator(); + +// 关闭 +manager.Shutdown(); + +// 多次调用返回同一实例 +MemoryManager& manager2 = MemoryManager::Get(); +// manager == manager2 为 true +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 diff --git a/docs/api/memory/memorymanager/getsystemallocator.md b/docs/api/memory/memorymanager/getsystemallocator.md new file mode 100644 index 00000000..f84b53a9 --- /dev/null +++ b/docs/api/memory/memorymanager/getsystemallocator.md @@ -0,0 +1,27 @@ +# MemoryManager::GetSystemAllocator + +```cpp +IAllocator* GetSystemAllocator(); +``` + +获取系统默认分配器。该分配器使用标准 C 库的 `std::malloc` 和平台特定的对齐分配函数(如 Windows 的 `_aligned_malloc`)作为后端,适用于通用内存分配场景。 + +**参数:** 无 + +**返回:** 系统分配器指针 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +void* ptr = sysAlloc->Allocate(1024); +sysAlloc->Free(ptr); +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 diff --git a/docs/api/memory/memorymanager/initialize.md b/docs/api/memory/memorymanager/initialize.md new file mode 100644 index 00000000..40f02564 --- /dev/null +++ b/docs/api/memory/memorymanager/initialize.md @@ -0,0 +1,33 @@ +# MemoryManager::Initialize + +```cpp +void Initialize(); +``` + +初始化内存管理器。创建系统默认分配器,设置内存跟踪标志。应在程序启动早期调用,且仅可调用一次。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +#include + +int main() { + // 程序启动时初始化 + MemoryManager::Get().Initialize(); + + // 使用内存系统... + + MemoryManager::Get().Shutdown(); + return 0; +} +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 diff --git a/docs/api/memory/memorymanager/memorymanager.md b/docs/api/memory/memorymanager/memorymanager.md new file mode 100644 index 00000000..581c41c0 --- /dev/null +++ b/docs/api/memory/memorymanager/memorymanager.md @@ -0,0 +1,85 @@ +# MemoryManager + +**命名空间**: `XCEngine::Memory` + +**类型**: `class` (singleton) + +**描述**: 全局内存管理器单例,提供系统分配器和各种专用分配器的创建与管理。 + +## 概述 + +`MemoryManager` 是 XCEngine 内存管理系统的核心单例。它负责维护系统分配器,提供分配器工厂方法,并支持内存泄漏检测和报告。 + +## 单例访问 + +| 方法 | 描述 | +|------|------| +| [`Get`](get.md) | 获取单例实例 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化内存管理器 | +| [`Shutdown`](shutdown.md) | 关闭内存管理器 | +| [`GetSystemAllocator`](getsystemallocator.md) | 获取系统默认分配器 | +| [`CreateLinearAllocator`](createlinearallocator.md) | 创建线性分配器 | +| [`CreatePoolAllocator`](createpoolallocator.md) | 创建内存池分配器 | +| [`CreateProxyAllocator`](createproxyallocator.md) | 创建代理分配器 | +| [`SetTrackAllocations`](settrackallocations.md) | 设置是否跟踪分配 | +| [`DumpMemoryLeaks`](dumpmemoryleaks.md) | 输出内存泄漏报告 | +| [`GenerateMemoryReport`](generatememoryreport.md) | 生成内存使用报告 | + +## 宏定义 + +### XE_ALLOC + +```cpp +#define XE_ALLOC(allocator, size, ...) allocator->Allocate(size, ##__VA_ARGS__) +``` + +内存分配宏。 + +### XE_FREE + +```cpp +#define XE_FREE(allocator, ptr) allocator->Free(ptr) +``` + +内存释放宏。 + +## 使用示例 + +```cpp +#include + +// 初始化 +MemoryManager::Get().Initialize(); + +// 获取系统分配器 +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); + +// 创建专用分配器 +auto linearAlloc = MemoryManager::Get().CreateLinearAllocator(1024 * 1024); +auto poolAlloc = MemoryManager::Get().CreatePoolAllocator(sizeof(MyObject), 1000); +auto proxyAlloc = MemoryManager::Get().CreateProxyAllocator("GameFrame"); + +// 使用宏分配 +void* ptr = XE_ALLOC(proxyAlloc, 256); +XE_FREE(proxyAlloc, ptr); + +// 跟踪内存 +MemoryManager::Get().SetTrackAllocations(true); +MemoryManager::Get().GenerateMemoryReport(); + +// 关闭 +MemoryManager::Get().Shutdown(); +``` + +## 相关文档 + +- [Memory 模块总览](../memory.md) - 返回模块总览 +- [IAllocator](../allocator/allocator.md) - 分配器接口 +- [LinearAllocator](../linear-allocator/linear-allocator.md) - 线性分配器 +- [PoolAllocator](../pool-allocator/pool-allocator.md) - 内存池分配器 +- [ProxyAllocator](../proxy-allocator/proxy-allocator.md) - 代理分配器 diff --git a/docs/api/memory/memorymanager/settrackallocations.md b/docs/api/memory/memorymanager/settrackallocations.md new file mode 100644 index 00000000..a10e06a1 --- /dev/null +++ b/docs/api/memory/memorymanager/settrackallocations.md @@ -0,0 +1,35 @@ +# MemoryManager::SetTrackAllocations + +```cpp +void SetTrackAllocations(bool track); +``` + +设置是否启用内存分配跟踪。启用后系统会记录所有分配操作,用于生成内存报告和泄漏检测。 + +**参数:** +- `track` - true 启用跟踪,false 禁用跟踪 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +MemoryManager::Get().Initialize(); + +// 禁用跟踪(提升性能) +MemoryManager::Get().SetTrackAllocations(false); + +// ... 大量内存操作 ... + +// 重新启用跟踪进行分析 +MemoryManager::Get().SetTrackAllocations(true); +MemoryManager::Get().GenerateMemoryReport(); +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 diff --git a/docs/api/memory/memorymanager/shutdown.md b/docs/api/memory/memorymanager/shutdown.md new file mode 100644 index 00000000..e7b102af --- /dev/null +++ b/docs/api/memory/memorymanager/shutdown.md @@ -0,0 +1,35 @@ +# MemoryManager::Shutdown + +```cpp +void Shutdown(); +``` + +关闭内存管理器。执行内存泄漏检测报告,释放系统分配器。应在程序退出前调用。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +#include + +int main() { + MemoryManager::Get().Initialize(); + + // ... 游戏主循环 ... + + // 程序退出前关闭 + MemoryManager::Get().DumpMemoryLeaks(); + MemoryManager::Get().Shutdown(); + + return 0; +} +``` + +## 相关文档 + +- [MemoryManager 总览](memorymanager.md) - 返回类总览 diff --git a/docs/api/memory/pool-allocator/constructor.md b/docs/api/memory/pool-allocator/constructor.md new file mode 100644 index 00000000..8b5cc517 --- /dev/null +++ b/docs/api/memory/pool-allocator/constructor.md @@ -0,0 +1,40 @@ +# PoolAllocator::PoolAllocator + +```cpp +PoolAllocator(size_t blockSize, size_t poolSize, size_t alignment = 8); +``` + +构造内存池分配器,预分配 `poolSize` 个大小为 `blockSize` 字节的内存块。内存块按 `alignment` 对齐(默认 8 字节)。内部维护一个空闲链表来管理分配。 + +**参数:** +- `blockSize` - 每个内存块的大小(字节) +- `poolSize` - 内存池中总块数 +- `alignment` - 对齐要求,默认为 8 字节 + +**返回:** 无 + +**复杂度:** O(n),需要预分配所有块 + +**示例:** + +```cpp +#include + +struct Particle { + float x, y, z; + float vx, vy, vz; + float life; +}; + +// 创建一个能容纳 1000 个 Particle 的内存池,16 字节对齐 +PoolAllocator pool(sizeof(Particle), 1000, alignof(Particle)); + +size_t blockSize = pool.GetBlockSize(); // sizeof(Particle) +size_t total = pool.GetTotalBlockCount(); // 1000 +size_t free = pool.GetFreeBlockCount(); // 1000 +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 +- [`~PoolAllocator`](~pool-allocator.md) - 析构函数 \ No newline at end of file diff --git a/docs/api/memory/pool-allocator/get-allocation-count.md b/docs/api/memory/pool-allocator/get-allocation-count.md new file mode 100644 index 00000000..227c1830 --- /dev/null +++ b/docs/api/memory/pool-allocator/get-allocation-count.md @@ -0,0 +1,40 @@ +# PoolAllocator::GetAllocationCount + +```cpp +size_t GetAllocationCount() const override; +``` + +返回当前已分配块的数量。计算公式:`m_totalBlocks - m_freeBlocks`。 + +**参数:** 无 + +**返回:** 当前已分配块的数量 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int), 100); + +size_t count = pool.GetAllocationCount(); // 0 + +void* blocks[10]; +for (int i = 0; i < 10; ++i) { + blocks[i] = pool.Allocate(); +} + +count = pool.GetAllocationCount(); // 10 + +for (int i = 0; i < 5; ++i) { + pool.Free(blocks[i]); +} + +count = pool.GetAllocationCount(); // 5 +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/pool-allocator/get-block-size.md b/docs/api/memory/pool-allocator/get-block-size.md index 65c9cead..ba6a6a4c 100644 --- a/docs/api/memory/pool-allocator/get-block-size.md +++ b/docs/api/memory/pool-allocator/get-block-size.md @@ -4,7 +4,7 @@ size_t GetBlockSize() const; ``` -返回内存池中每个内存块的大小。此值在构造时确定,之后保持不变。 +返回内存池中每个内存块的大小。此值在构造时确定,之后保持不变。实际分配的内存可能按对齐要求调整,但块大小返回原始请求值。 **参数:** 无 diff --git a/docs/api/memory/pool-allocator/get-name.md b/docs/api/memory/pool-allocator/get-name.md new file mode 100644 index 00000000..0df12e8a --- /dev/null +++ b/docs/api/memory/pool-allocator/get-name.md @@ -0,0 +1,29 @@ +# PoolAllocator::GetName + +```cpp +const char* GetName() const override; +``` + +返回分配器的名称字符串 "PoolAllocator"。用于调试和日志记录。 + +**参数:** 无 + +**返回:** 固定返回 `"PoolAllocator"` 字符串 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include +#include + +PoolAllocator pool(sizeof(int), 100); + +const char* name = pool.GetName(); // "PoolAllocator" +std::cout << "Allocator: " << name << std::endl; +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/pool-allocator/get-peak-allocated.md b/docs/api/memory/pool-allocator/get-peak-allocated.md new file mode 100644 index 00000000..6fc842ae --- /dev/null +++ b/docs/api/memory/pool-allocator/get-peak-allocated.md @@ -0,0 +1,33 @@ +# PoolAllocator::GetPeakAllocated + +```cpp +size_t GetPeakAllocated() const override; +``` + +返回峰值分配的内存总量(字节)。由于池在构造时预分配所有块,峰值即为 `m_totalBlocks * m_blockSize`。 + +**参数:** 无 + +**返回:** 内存池总容量(字节) + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int), 100); + +size_t peak = pool.GetPeakAllocated(); // 100 * sizeof(int) + +// 即使分配了部分块,峰值仍然是总容量 +void* block1 = pool.Allocate(); +void* block2 = pool.Allocate(); +size_t current = pool.GetTotalAllocated(); // 2 * sizeof(int) +peak = pool.GetPeakAllocated(); // 100 * sizeof(int) +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/pool-allocator/get-total-allocated.md b/docs/api/memory/pool-allocator/get-total-allocated.md new file mode 100644 index 00000000..1ab4fc46 --- /dev/null +++ b/docs/api/memory/pool-allocator/get-total-allocated.md @@ -0,0 +1,33 @@ +# PoolAllocator::GetTotalAllocated + +```cpp +size_t GetTotalAllocated() const override; +``` + +返回当前已分配的内存总量(字节)。计算公式:`(m_totalBlocks - m_freeBlocks) * m_blockSize`。 + +**参数:** 无 + +**返回:** 当前已分配块的字节数 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int), 100); + +size_t allocated = pool.GetTotalAllocated(); // 0 + +void* block = pool.Allocate(); +allocated = pool.GetTotalAllocated(); // sizeof(int) + +pool.Free(block); +allocated = pool.GetTotalAllocated(); // 0 +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/pool-allocator/get-total-freed.md b/docs/api/memory/pool-allocator/get-total-freed.md new file mode 100644 index 00000000..0eaf8fea --- /dev/null +++ b/docs/api/memory/pool-allocator/get-total-freed.md @@ -0,0 +1,33 @@ +# PoolAllocator::GetTotalFreed + +```cpp +size_t GetTotalFreed() const override; +``` + +返回当前空闲的内存总量(字节)。计算公式:`m_freeBlocks * m_blockSize`。 + +**参数:** 无 + +**返回:** 当前空闲块的字节数 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int), 100); + +size_t freed = pool.GetTotalFreed(); // 100 * sizeof(int) + +void* block = pool.Allocate(); +freed = pool.GetTotalFreed(); // 99 * sizeof(int) + +pool.Free(block); +freed = pool.GetTotalFreed(); // 100 * sizeof(int) +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/memory/pool-allocator/pool-allocator.md b/docs/api/memory/pool-allocator/pool-allocator.md index 565fffef..216609a9 100644 --- a/docs/api/memory/pool-allocator/pool-allocator.md +++ b/docs/api/memory/pool-allocator/pool-allocator.md @@ -4,6 +4,8 @@ **类型**: `class` +**头文件**: `XCEngine/Memory/PoolAllocator.h` + **描述**: 内存池分配器,预分配固定大小的内存块池。 ## 概述 @@ -14,15 +16,20 @@ | 方法 | 描述 | |------|------| -| `PoolAllocator` | 构造内存池分配器 | -| `~PoolAllocator` | 析构函数,释放整个内存池 | -| `Allocate` | 分配一个内存块 | -| `Free` | 释放内存块回空闲链表 | -| `Reallocate` | 不支持(始终返回 nullptr) | -| `Contains` | 检查指针是否属于此池 | -| `GetBlockSize` | 获取块大小 | -| `GetFreeBlockCount` | 获取空闲块数量 | -| `GetTotalBlockCount` | 获取总块数 | +| [`PoolAllocator`](constructor.md) | 构造内存池分配器 | +| [`~PoolAllocator`](~pool-allocator.md) | 析构函数,释放整个内存池 | +| [`Allocate`](allocate.md) | 分配一个内存块 | +| [`Free`](free.md) | 释放内存块回空闲链表 | +| [`Reallocate`](reallocate.md) | 不支持(始终返回 nullptr) | +| [`Contains`](contains.md) | 检查指针是否属于此池 | +| [`GetBlockSize`](get-block-size.md) | 获取块大小 | +| [`GetFreeBlockCount`](get-free-block-count.md) | 获取空闲块数量 | +| [`GetTotalBlockCount`](get-total-block-count.md) | 获取总块数 | +| [`GetName`](get-name.md) | 获取分配器名称 | +| [`GetTotalAllocated`](get-total-allocated.md) | 获取当前已分配内存 | +| [`GetTotalFreed`](get-total-freed.md) | 获取当前空闲内存 | +| [`GetPeakAllocated`](get-peak-allocated.md) | 获取峰值分配内存 | +| [`GetAllocationCount`](get-allocation-count.md) | 获取当前分配块数量 | ## 构造函数 diff --git a/docs/api/memory/proxy-allocator/free.md b/docs/api/memory/proxy-allocator/free.md index c4ebd3b8..1c0ec6db 100644 --- a/docs/api/memory/proxy-allocator/free.md +++ b/docs/api/memory/proxy-allocator/free.md @@ -4,9 +4,7 @@ void Free(void* ptr) override; ``` -释放内存并记录统计。调用转发到底层分配器,同时更新统计信息:递增 `totalFreed`(累加当前 `allocationCount`),并递减 `allocationCount`。 - -**注意:** `totalFreed` 累加的是每次释放时的 `allocationCount`(分配计数)而非实际字节大小。这是一个简化的实现,用于追踪释放操作次数。 +释放内存并记录统计。调用转发到底层分配器,同时更新统计信息:递增 `totalFreed`(累加释放字节数),并递减 `allocationCount`。 **参数:** - `ptr` - 指向要释放的内存块 @@ -31,9 +29,9 @@ proxy.Free(p1); proxy.Free(p2); const auto& stats = proxy.GetStats(); -// totalFreed 累加了每次释放时的 allocationCount(次数,非字节) +// totalFreed 累加了释放的字节数 // allocationCount 最终为 0 -printf("Total allocated: %zu bytes, Freed count: %zu, Current count: %zu\n", +printf("Total allocated: %zu bytes, Freed: %zu bytes, Current count: %zu\n", stats.totalAllocated, stats.totalFreed, stats.allocationCount); ``` diff --git a/docs/api/memory/proxy-allocator/get-allocation-count.md b/docs/api/memory/proxy-allocator/get-allocation-count.md new file mode 100644 index 00000000..62e68cda --- /dev/null +++ b/docs/api/memory/proxy-allocator/get-allocation-count.md @@ -0,0 +1,37 @@ +# ProxyAllocator::GetAllocationCount + +```cpp +size_t GetAllocationCount() const override; +``` + +获取当前未释放的分配次数。 + +**参数:** 无 + +**返回:** 当前未释放的分配次数 + +**线程安全:** ✅ + +**复杂度:** O(1) + +**示例:** + +```cpp +#include +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "TrackedAlloc"); + +proxy.Allocate(100); +proxy.Allocate(200); +void* p = proxy.Allocate(300); +proxy.Free(p); + +size_t count = proxy.GetAllocationCount(); +printf("Current allocation count: %zu\n", count); +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/get-name.md b/docs/api/memory/proxy-allocator/get-name.md new file mode 100644 index 00000000..e6aeebbc --- /dev/null +++ b/docs/api/memory/proxy-allocator/get-name.md @@ -0,0 +1,32 @@ +# ProxyAllocator::GetName + +```cpp +const char* GetName() const override; +``` + +获取分配器的名称字符串。 + +**参数:** 无 + +**返回:** 分配器名称字符串 + +**线程安全:** ✅ + +**复杂度:** O(1) + +**示例:** + +```cpp +#include +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "TrackedAlloc"); + +const char* name = proxy.GetName(); +printf("Allocator name: %s\n", name); +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/get-peak-allocated.md b/docs/api/memory/proxy-allocator/get-peak-allocated.md new file mode 100644 index 00000000..0ffc4706 --- /dev/null +++ b/docs/api/memory/proxy-allocator/get-peak-allocated.md @@ -0,0 +1,37 @@ +# ProxyAllocator::GetPeakAllocated + +```cpp +size_t GetPeakAllocated() const override; +``` + +获取峰值分配的字节数。 + +**参数:** 无 + +**返回:** 峰值分配的字节数 + +**线程安全:** ✅ + +**复杂度:** O(1) + +**示例:** + +```cpp +#include +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "TrackedAlloc"); + +proxy.Allocate(100); +proxy.Allocate(200); +proxy.Free(proxy.Allocate(50)); +proxy.Free(proxy.Allocate(100)); + +size_t peakAllocated = proxy.GetPeakAllocated(); +printf("Peak allocated: %zu bytes\n", peakAllocated); +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/get-total-allocated.md b/docs/api/memory/proxy-allocator/get-total-allocated.md new file mode 100644 index 00000000..cb589677 --- /dev/null +++ b/docs/api/memory/proxy-allocator/get-total-allocated.md @@ -0,0 +1,35 @@ +# ProxyAllocator::GetTotalAllocated + +```cpp +size_t GetTotalAllocated() const override; +``` + +获取累计分配的字节数。 + +**参数:** 无 + +**返回:** 累计分配的字节数 + +**线程安全:** ✅ + +**复杂度:** O(1) + +**示例:** + +```cpp +#include +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "TrackedAlloc"); + +proxy.Allocate(100); +proxy.Allocate(200); + +size_t totalAllocated = proxy.GetTotalAllocated(); +printf("Total allocated: %zu bytes\n", totalAllocated); +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/get-total-freed.md b/docs/api/memory/proxy-allocator/get-total-freed.md new file mode 100644 index 00000000..5d7e86d0 --- /dev/null +++ b/docs/api/memory/proxy-allocator/get-total-freed.md @@ -0,0 +1,35 @@ +# ProxyAllocator::GetTotalFreed + +```cpp +size_t GetTotalFreed() const override; +``` + +获取累计释放的字节数。 + +**参数:** 无 + +**返回:** 累计释放的字节数 + +**线程安全:** ✅ + +**复杂度:** O(1) + +**示例:** + +```cpp +#include +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "TrackedAlloc"); + +void* p1 = proxy.Allocate(100); +proxy.Free(p1); + +size_t totalFreed = proxy.GetTotalFreed(); +printf("Total freed: %zu bytes\n", totalFreed); +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/proxy-allocator.md b/docs/api/memory/proxy-allocator/proxy-allocator.md index 40f67364..ea0c0525 100644 --- a/docs/api/memory/proxy-allocator/proxy-allocator.md +++ b/docs/api/memory/proxy-allocator/proxy-allocator.md @@ -4,6 +4,8 @@ **类型**: `class` +**头文件**: `XCEngine/Memory/ProxyAllocator.h` + **描述**: 代理分配器,用于统计和跟踪底层分配器的分配情况。 ## 概述 @@ -14,12 +16,15 @@ | 方法 | 描述 | |------|------| -| `ProxyAllocator` | 构造代理分配器 | -| `~ProxyAllocator` | 析构函数 | -| `Allocate` | 分配内存并记录统计 | -| `Free` | 释放内存并记录统计 | -| `Reallocate` | 转发到底层分配器 | -| `GetStats` | 获取详细统计信息 | +| [`Allocate`](allocate.md) | 分配内存并记录统计 | +| [`Free`](free.md) | 释放内存并记录统计 | +| [`Reallocate`](reallocate.md) | 转发到底层分配器 | +| [`GetStats`](get-stats.md) | 获取详细统计信息 | +| [`GetTotalAllocated`](get-total-allocated.md) | 获取累计分配字节数 | +| [`GetTotalFreed`](get-total-freed.md) | 获取累计释放字节数 | +| [`GetPeakAllocated`](get-peak-allocated.md) | 获取峰值分配字节数 | +| [`GetAllocationCount`](get-allocation-count.md) | 获取分配次数 | +| [`GetName`](get-name.md) | 获取分配器名称 | ## 构造函数 diff --git a/docs/api/memory/proxy-allocator/reallocate.md b/docs/api/memory/proxy-allocator/reallocate.md index 6d1f0e8c..7a9087ac 100644 --- a/docs/api/memory/proxy-allocator/reallocate.md +++ b/docs/api/memory/proxy-allocator/reallocate.md @@ -4,7 +4,7 @@ void* Reallocate(void* ptr, size_t newSize) override; ``` -重新分配内存。调用转发到底层分配器,不记录额外统计信息(底层分配器的返回值直接返回)。此方法线程安全,内部使用互斥锁保护。 +重新分配内存。调用转发到底层分配器,同时更新统计信息(峰值分配和当前分配量)。此方法线程安全,内部使用互斥锁保护。 **参数:** - `ptr` - 现有内存块指针 diff --git a/docs/api/memory/proxy-allocator/~proxy-allocator.md b/docs/api/memory/proxy-allocator/~proxy-allocator.md deleted file mode 100644 index 68846e76..00000000 --- a/docs/api/memory/proxy-allocator/~proxy-allocator.md +++ /dev/null @@ -1,37 +0,0 @@ -# ProxyAllocator::~ProxyAllocator - -```cpp -~ProxyAllocator() override; -``` - -销毁代理分配器。此析构函数不释放底层分配器,只清理代理分配器自身的统计信息(互斥锁等)。底层分配器由创建者负责管理。 - -**参数:** 无 - -**返回:** 无 - -**注意:** 析构函数不释放底层分配器。如果需要释放底层分配器,应先调用 `Shutdown` 或显式销毁底层分配器。 - -**示例:** - -```cpp -#include -#include - -{ - MemoryManager::Get().Initialize(); - IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); - - auto proxy = MemoryManager::Get().CreateProxyAllocator("TrackedAlloc"); - proxy->Allocate(1024); - - // proxy 超出作用域时自动销毁 - // 底层 sysAlloc 仍有效 - - MemoryManager::Get().Shutdown(); -} -``` - -## 相关文档 - -- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/threading/lambdatask/execute.md b/docs/api/threading/lambdatask/execute.md new file mode 100644 index 00000000..7dc52bcc --- /dev/null +++ b/docs/api/threading/lambdatask/execute.md @@ -0,0 +1,40 @@ +# LambdaTask::Execute + +```cpp +void Execute() override +``` + +执行封装的可调用对象。调用时执行构造时传入的 lambda 或可调用函数。 + +**参数:** 无 + +**返回:** 无 + +**注意:** +- 如果封装的可调用对象抛出异常,异常会向上传播到 TaskSystem。 +- 任务系统的工作线程不会捕获此类异常。 + +**示例:** + +```cpp +// 创建并提交 LambdaTask +TaskSystem::Get().Submit( + std::make_unique>>( + []() { + printf("Task executed!\n"); + }, + TaskPriority::Normal + ) +); + +// 使用便捷重载直接提交 +TaskSystem::Get().Submit([]() { + int result = ComputeHeavyWork(); + printf("Result: %d\n", result); +}, TaskPriority::High); +``` + +## 相关文档 + +- [LambdaTask 总览](lambdatask.md) - 返回类总览 +- [ITask::Execute](../task/execute.md) - 基类方法文档 diff --git a/docs/api/threading/lambdatask/lambdatask.md b/docs/api/threading/lambdatask/lambdatask.md index 15c6ea23..54a5ff60 100644 --- a/docs/api/threading/lambdatask/lambdatask.md +++ b/docs/api/threading/lambdatask/lambdatask.md @@ -28,7 +28,7 @@ | 方法 | 描述 | |------|------| -| `Execute()` | 执行封装的可调用对象(继承自 ITask,可重写) | +| [`Execute()`](execute.md) | 执行封装的可调用对象(继承自 ITask,纯虚方法重写) | ## 使用示例 diff --git a/docs/api/threading/mutex/lock.md b/docs/api/threading/mutex/lock.md index 7fc8e74e..c8a4a951 100644 --- a/docs/api/threading/mutex/lock.md +++ b/docs/api/threading/mutex/lock.md @@ -19,7 +19,7 @@ void Lock() **示例:** ```cpp -Threading::Mutex mtx; +XCEngine::Threading::Mutex mtx; int counter = 0; void Increment() { diff --git a/docs/api/threading/mutex/lock_const.md b/docs/api/threading/mutex/lock_const.md new file mode 100644 index 00000000..773d4446 --- /dev/null +++ b/docs/api/threading/mutex/lock_const.md @@ -0,0 +1,43 @@ +# Mutex::lock + +```cpp +void lock() const; +``` + +获取互斥锁(const 版本)。如果锁已被其他线程持有,则阻塞当前线程直到锁可用。 + +该方法是 `std::lockable` 接口的实现,可与 `std::lock_guard`、`std::unique_lock` 等 RAII 工具配合使用。 + +**参数:** 无 + +**返回:** 无 + +**线程安全:** ✅ + +**复杂度:** 平均 O(1),最坏情况 O(n),n 为竞争线程数 + +**示例:** + +```cpp +#include "XCEngine/Threading/Mutex.h" +#include + +XCEngine::XCEngine::Threading::Mutex mtx; +int counter = 0; + +void Increment() { + mtx.lock(); + ++counter; + mtx.unlock(); +} + +// 使用 RAII 自动管理锁 +void SafeIncrement() { + std::lock_guard guard(mtx); + ++counter; +} +``` + +## 相关文档 + +- [Mutex 总览](mutex.md) - 返回类总览 diff --git a/docs/api/threading/mutex/mutex.md b/docs/api/threading/mutex/mutex.md index 3fe1e9e2..2cedc33e 100644 --- a/docs/api/threading/mutex/mutex.md +++ b/docs/api/threading/mutex/mutex.md @@ -6,43 +6,52 @@ **头文件**: `XCEngine/Threading/Mutex.h` -**描述**: 互斥锁封装类,基于 `std::mutex` 实现,提供线程安全的互斥访问。 +**描述**: 互斥锁,封装 std::mutex 提供线程同步 ## 概述 -`Mutex` 是对 `std::mutex` 的简单封装,提供了标准的 Lock/Unlock/TryLock 接口。它是 XCEngine 中最基础的同步原语,适用于保护共享数据的访问。 +Mutex 类是对 std::mutex 的封装,提供线程安全的互斥访问机制。该类确保同一时刻只有一个线程可以访问受保护的资源,防止数据竞争和竞态条件。 + +该类提供两套接口: +- `Lock/Unlock/TryLock`:XCEngine 风格接口 +- `lock/unlock/try_lock`:STL 兼容接口(const 成员函数) ## 公共方法 | 方法 | 描述 | |------|------| -| [`Lock`](lock.md) | 获取锁(阻塞) | -| [`Unlock`](unlock.md) | 释放锁 | -| [`TryLock`](trylock.md) | 尝试获取锁(非阻塞,成功返回 true) | - -## STL 兼容方法 - -支持 `lock()`, `unlock()`, `try_lock()` 以兼容 STL 的 lockable 概念。**注意**:这些方法为 `const` 成员函数。 +| [`Lock`](lock.md) | 获取互斥锁(非 const) | +| [`Unlock`](unlock.md) | 释放互斥锁(非 const) | +| [`TryLock`](trylock.md) | 尝试获取互斥锁(非 const) | +| [`lock`](lock_const.md) | 获取互斥锁(const,STL 兼容) | +| [`unlock`](unlock_const.md) | 释放互斥锁(const,STL 兼容) | +| [`try_lock`](try_lock_const.md) | 尝试获取互斥锁(const,STL 兼容) | ## 使用示例 ```cpp -Threading::Mutex mtx; +#include "XCEngine/Threading/Mutex.h" +#include +#include + +XCEngine::Threading::Mutex mutex; int sharedData = 0; -// 线程安全地修改共享数据 -void SafeIncrement() { - mtx.Lock(); +void increment() { + mutex.lock(); ++sharedData; - mtx.Unlock(); + mutex.unlock(); } -// 或使用 TryLock -void SafeTryIncrement() { - if (mtx.TryLock()) { - ++sharedData; - mtx.Unlock(); - } +int main() { + std::thread t1(increment); + std::thread t2(increment); + + t1.join(); + t2.join(); + + std::cout << "sharedData = " << sharedData << std::endl; + return 0; } ``` diff --git a/docs/api/threading/mutex/try_lock.md b/docs/api/threading/mutex/try_lock.md new file mode 100644 index 00000000..89da1cc9 --- /dev/null +++ b/docs/api/threading/mutex/try_lock.md @@ -0,0 +1,36 @@ +# Mutex::try_lock + +```cpp +bool try_lock() const; +``` + +尝试获取互斥锁,非阻塞。如果锁不可用,调用线程不会阻塞,而是立即返回。 + +**参数:** 无 + +**返回:** `bool` - 如果成功获取锁返回 `true`,否则返回 `false` + +**线程安全:** ✅ + +**示例:** + +```cpp +#include "XCEngine/Threading/Mutex.h" +#include + +XCEngine::Threading::Mutex mutex; + +void tryOperation() { + if (mutex.try_lock()) { + // 获取锁成功 + mutex.unlock(); + } else { + // 锁已被其他线程持有 + std::cout << "Lock not available" << std::endl; + } +} +``` + +## 相关文档 + +- [Mutex 类总览](mutex.md) - 返回类总览 diff --git a/docs/api/threading/mutex/try_lock_const.md b/docs/api/threading/mutex/try_lock_const.md new file mode 100644 index 00000000..aa6baed9 --- /dev/null +++ b/docs/api/threading/mutex/try_lock_const.md @@ -0,0 +1,41 @@ +# Mutex::try_lock + +```cpp +bool try_lock() const; +``` + +尝试获取互斥锁(非阻塞,const 版本)。如果锁可用则立即获取并返回 `true`,否则立即返回 `false` 而不阻塞。 + +该方法是 `std::lockable` 接口的实现。 + +**参数:** 无 + +**返回:** `bool` - 获取成功返回 `true`,锁不可用返回 `false` + +**线程安全:** ✅ + +**复杂度:** O(1) + +**示例:** + +```cpp +#include "XCEngine/Threading/Mutex.h" +#include + +XCEngine::XCEngine::Threading::Mutex mtx; +volatile bool updated = false; + +void TryUpdate() { + if (mtx.try_lock()) { + updated = true; + mtx.unlock(); + std::cout << "Update succeeded" << std::endl; + } else { + std::cout << "Update skipped (lock held)" << std::endl; + } +} +``` + +## 相关文档 + +- [Mutex 总览](mutex.md) - 返回类总览 diff --git a/docs/api/threading/mutex/trylock.md b/docs/api/threading/mutex/trylock.md index 8ae80c6a..e35c6bee 100644 --- a/docs/api/threading/mutex/trylock.md +++ b/docs/api/threading/mutex/trylock.md @@ -17,7 +17,7 @@ bool TryLock() **示例:** ```cpp -Threading::Mutex mtx; +XCEngine::Threading::Mutex mtx; volatile bool updated = false; void TryUpdate() { diff --git a/docs/api/threading/mutex/unlock.md b/docs/api/threading/mutex/unlock.md index b8c7c6a9..4466cc6f 100644 --- a/docs/api/threading/mutex/unlock.md +++ b/docs/api/threading/mutex/unlock.md @@ -17,7 +17,7 @@ void Unlock() **示例:** ```cpp -Threading::Mutex mtx; +XCEngine::Threading::Mutex mtx; std::vector data; void SafePush(int value) { diff --git a/docs/api/threading/mutex/unlock_const.md b/docs/api/threading/mutex/unlock_const.md new file mode 100644 index 00000000..1c6c4d82 --- /dev/null +++ b/docs/api/threading/mutex/unlock_const.md @@ -0,0 +1,34 @@ +# Mutex::unlock + +```cpp +void unlock() const; +``` + +释放互斥锁(const 版本),允许其他等待中的线程获取该锁。 + +**参数:** 无 + +**返回:** 无 + +**线程安全:** ✅ + +**复杂度:** O(1) + +**示例:** + +```cpp +#include "XCEngine/Threading/Mutex.h" + +XCEngine::XCEngine::Threading::Mutex mtx; +std::vector data; + +void SafePush(int value) { + mtx.lock(); + data.push_back(value); + mtx.unlock(); +} +``` + +## 相关文档 + +- [Mutex 总览](mutex.md) - 返回类总览 diff --git a/docs/api/threading/readwritelock/constructor.md b/docs/api/threading/readwritelock/constructor.md new file mode 100644 index 00000000..9156c928 --- /dev/null +++ b/docs/api/threading/readwritelock/constructor.md @@ -0,0 +1,35 @@ +# ReadWriteLock::ReadWriteLock + +```cpp +ReadWriteLock() = default; +``` + +默认构造函数。构造一个未锁定的读写锁。 + +**参数:** 无 + +**返回:** 无 + +**线程安全:** ✅ + +**复杂度:** O(1) + +**注意:** +- 构造后的锁处于未锁定状态。 +- 多个线程可以同时获取读锁。 + +**示例:** + +```cpp +#include "XCEngine/Threading/ReadWriteLock.h" + +XCEngine::Threading::ReadWriteLock rwLock; +``` + +## 相关文档 + +- [`ReadWriteLock`](readwritelock.md) - 返回类总览 +- [`ReadLock`](readlock.md) - 获取读锁 +- [`ReadUnlock`](readunlock.md) - 释放读锁 +- [`WriteLock`](writelock.md) - 获取写锁 +- [`WriteUnlock`](writeunlock.md) - 释放写锁 diff --git a/docs/api/threading/readwritelock/destructor.md b/docs/api/threading/readwritelock/destructor.md new file mode 100644 index 00000000..dcfbbd32 --- /dev/null +++ b/docs/api/threading/readwritelock/destructor.md @@ -0,0 +1,40 @@ +# ReadWriteLock::~ReadWriteLock + +```cpp +~ReadWriteLock() = default; +``` + +默认析构函数。销毁读写锁。 + +**参数:** 无 + +**返回:** 无 + +**线程安全:** ⚠️ + +**复杂度:** O(1) + +**注意:** +- 析构前必须确保锁处于未锁定状态。 +- 如果在持有锁的状态下销毁行为未定义。 + +**示例:** + +```cpp +#include "XCEngine/Threading/ReadWriteLock.h" + +{ + XCEngine::Threading::ReadWriteLock rwLock; + rwLock.ReadLock(); + // ... 使用共享数据 ... + rwLock.ReadUnlock(); +} // rwLock 在这里销毁 +``` + +## 相关文档 + +- [`ReadWriteLock`](readwritelock.md) - 返回类总览 +- [`ReadLock`](readlock.md) - 获取读锁 +- [`ReadUnlock`](readunlock.md) - 释放读锁 +- [`WriteLock`](writelock.md) - 获取写锁 +- [`WriteUnlock`](writeunlock.md) - 释放写锁 diff --git a/docs/api/threading/readwritelock/readlock.md b/docs/api/threading/readwritelock/readlock.md index 57a71f5a..99707b8a 100644 --- a/docs/api/threading/readwritelock/readlock.md +++ b/docs/api/threading/readwritelock/readlock.md @@ -10,17 +10,21 @@ void ReadLock() **返回:** 无 +**线程安全:** ✅ + **复杂度:** 平均 O(1) **注意:** - 多个读者可以同时持有读锁。 - 写锁具有优先权——正在等待的写者会阻塞新的读者,防止写者饥饿。 -- 读锁不可重入,同一线程不可嵌套持有读锁(会导致死锁)。 +- 读锁不可重入,同一线程不可嵌套持有读锁。 **示例:** ```cpp -ReadWriteLock rwLock; +#include "XCEngine/Threading/ReadWriteLock.h" + +XCEngine::Threading::ReadWriteLock rwLock; int sharedValue = 0; int ReadValue() { @@ -33,4 +37,5 @@ int ReadValue() { ## 相关文档 -- [ReadWriteLock 总览](readwritelock.md) - 返回类总览 +- [`ReadWriteLock`](readwritelock.md) - 返回类总览 +- [`ReadUnlock`](readunlock.md) - 释放读锁 diff --git a/docs/api/threading/readwritelock/readunlock.md b/docs/api/threading/readwritelock/readunlock.md index 7d2f6be2..cbe10dfd 100644 --- a/docs/api/threading/readwritelock/readunlock.md +++ b/docs/api/threading/readwritelock/readunlock.md @@ -10,6 +10,8 @@ void ReadUnlock() **返回:** 无 +**线程安全:** ✅ + **复杂度:** O(1) **注意:** 必须与 ReadLock 配对使用,且在持有读锁的线程中调用。 @@ -17,7 +19,9 @@ void ReadUnlock() **示例:** ```cpp -ReadWriteLock rwLock; +#include "XCEngine/Threading/ReadWriteLock.h" + +XCEngine::Threading::ReadWriteLock rwLock; float sharedData = 0.0f; float GetData() { @@ -30,4 +34,5 @@ float GetData() { ## 相关文档 -- [ReadWriteLock 总览](readwritelock.md) - 返回类总览 +- [`ReadWriteLock`](readwritelock.md) - 返回类总览 +- [`ReadLock`](readlock.md) - 获取读锁 diff --git a/docs/api/threading/readwritelock/readwritelock.md b/docs/api/threading/readwritelock/readwritelock.md index 56f3a4d5..d1087209 100644 --- a/docs/api/threading/readwritelock/readwritelock.md +++ b/docs/api/threading/readwritelock/readwritelock.md @@ -6,52 +6,86 @@ **头文件**: `XCEngine/Threading/ReadWriteLock.h` -**描述**: 读写锁实现,支持多个并发读取或单一写入,提高读多写少场景的并发性能。 +**描述**: 读写锁,允许多个读者或单个写者 ## 概述 `ReadWriteLock` 实现了一个经典的读写锁。它允许多个线程同时持有读锁,但在有写锁时,所有读锁都必须释放,写锁为独占访问。这对于读操作远多于写操作的共享数据非常有效。 +### 设计目的 + +- 提供比普通互斥锁更高的并发性能 +- 允许多个线程同时读取共享数据 +- 确保写入操作时的独占性访问 +- 防止写者饥饿(通过写者优先策略) + +### 使用场景 + +- 读多写少的共享数据访问 +- 需要保护长时间读取的数据结构 +- 数据库、缓存、配置等共享资源访问 + ## 公共方法 -### 读锁 - | 方法 | 描述 | |------|------| -| [`ReadLock`](readlock.md) | 获取读锁(可重入,支持多个并发读者) | +| [`ReadWriteLock`](constructor.md) | 构造一个读写锁 | +| [`~ReadWriteLock`](destructor.md) | 销毁读写锁 | +| [`ReadLock`](readlock.md) | 获取读锁(支持多个并发读者) | | [`ReadUnlock`](readunlock.md) | 释放读锁 | - -### 写锁 - -| 方法 | 描述 | -|------|------| | [`WriteLock`](writelock.md) | 获取写锁(独占,阻塞所有读者和写者) | | [`WriteUnlock`](writeunlock.md) | 释放写锁 | ## 使用示例 ```cpp -Threading::ReadWriteLock rwLock; -Containers::HashMap sharedMap; +#include "XCEngine/Threading/ReadWriteLock.h" +#include +#include +#include +#include + +XCEngine::Threading::ReadWriteLock rwLock; +std::map sharedCache; // 读操作(多个线程可同时读) -int* ReadData(const String& key) { +int ReadData(const std::string& key) { rwLock.ReadLock(); - int* value = sharedMap.Find(key); + int value = 0; + auto it = sharedCache.find(key); + if (it != sharedCache.end()) { + value = it->second; + } rwLock.ReadUnlock(); return value; } // 写操作(独占) -void WriteData(const String& key, int value) { +void WriteData(const std::string& key, int value) { rwLock.WriteLock(); - sharedMap.Insert(key, value); + sharedCache[key] = value; rwLock.WriteUnlock(); } + +int main() { + std::vector threads; + + threads.emplace_back(WriteData, "score", 100); + threads.emplace_back(ReadData, "score"); + threads.emplace_back(WriteData, "health", 200); + threads.emplace_back(ReadData, "health"); + + for (auto& t : threads) { + t.join(); + } + + return 0; +} ``` ## 相关文档 -- [Mutex](../mutex/mutex.md) - 互斥锁 -- [SpinLock](../spinlock/spinlock.md) - 自旋锁 -- [../threading/threading.md](../threading.md) - 模块总览 +- [`ReadLock`](readlock.md) - 获取读锁 +- [`ReadUnlock`](readunlock.md) - 释放读锁 +- [`WriteLock`](writelock.md) - 获取写锁 +- [`WriteUnlock`](writeunlock.md) - 释放写锁 diff --git a/docs/api/threading/readwritelock/writelock.md b/docs/api/threading/readwritelock/writelock.md index 0d2af801..c4a4daa1 100644 --- a/docs/api/threading/readwritelock/writelock.md +++ b/docs/api/threading/readwritelock/writelock.md @@ -10,6 +10,8 @@ void WriteLock() **返回:** 无 +**线程安全:** ✅ + **复杂度:** 平均 O(1),写者饥饿时可能 O(n) **注意:** @@ -20,7 +22,10 @@ void WriteLock() **示例:** ```cpp -ReadWriteLock rwLock; +#include "XCEngine/Threading/ReadWriteLock.h" +#include + +XCEngine::Threading::ReadWriteLock rwLock; std::vector buffer; void Append(int value) { @@ -32,4 +37,5 @@ void Append(int value) { ## 相关文档 -- [ReadWriteLock 总览](readwritelock.md) - 返回类总览 +- [`ReadWriteLock`](readwritelock.md) - 返回类总览 +- [`WriteUnlock`](writeunlock.md) - 释放写锁 diff --git a/docs/api/threading/readwritelock/writeunlock.md b/docs/api/threading/readwritelock/writeunlock.md index 778e6fc0..aa93dbf9 100644 --- a/docs/api/threading/readwritelock/writeunlock.md +++ b/docs/api/threading/readwritelock/writeunlock.md @@ -10,6 +10,8 @@ void WriteUnlock() **返回:** 无 +**线程安全:** ✅ + **复杂度:** O(1) **注意:** 必须在持有写锁的线程中调用。 @@ -17,10 +19,14 @@ void WriteUnlock() **示例:** ```cpp -ReadWriteLock rwLock; -std::unordered_map cache; +#include "XCEngine/Threading/ReadWriteLock.h" +#include +#include -void UpdateCache(const String& key, int value) { +XCEngine::Threading::ReadWriteLock rwLock; +std::unordered_map cache; + +void UpdateCache(const std::string& key, int value) { rwLock.WriteLock(); cache[key] = value; rwLock.WriteUnlock(); @@ -29,4 +35,5 @@ void UpdateCache(const String& key, int value) { ## 相关文档 -- [ReadWriteLock 总览](readwritelock.md) - 返回类总览 +- [`ReadWriteLock`](readwritelock.md) - 返回类总览 +- [`WriteLock`](writelock.md) - 获取写锁 diff --git a/docs/api/threading/spinlock/lock.md b/docs/api/threading/spinlock/lock.md index 5917c9d3..ef2553bd 100644 --- a/docs/api/threading/spinlock/lock.md +++ b/docs/api/threading/spinlock/lock.md @@ -15,7 +15,7 @@ void Lock() **注意:** - 适用于临界区极短(几个 CPU 指令)的场景,避免线程切换开销。 - 在锁持有时间较长或多核竞争激烈时,会浪费大量 CPU 周期,此时应使用 Mutex。 -- 同一线程不可重复 Lock 同一个 SpinLock。 +- 同一线程对同一个 SpinLock 重复加锁会导致死锁。 **示例:** diff --git a/docs/api/threading/spinlock/lock_1.md b/docs/api/threading/spinlock/lock_1.md new file mode 100644 index 00000000..e129a64a --- /dev/null +++ b/docs/api/threading/spinlock/lock_1.md @@ -0,0 +1,31 @@ +# SpinLock::lock + +```cpp +void lock() +``` + +STL 兼容的 `lock()` 方法,与 [`Lock`](lock.md) 等效。满足 STL `Lockable` 概念要求。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** 平均 O(1),最坏情况取决于竞争程度 + +**线程安全:** ✅ + +**示例:** + +```cpp +Threading::SpinLock spinLock; + +void STLCompatibleUsage() { + spinLock.lock(); + // 临界区操作 + spinLock.unlock(); +} +``` + +## 相关文档 + +- [SpinLock 总览](spinlock.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/threading/spinlock/spinlock.md b/docs/api/threading/spinlock/spinlock.md index c6d2f6da..3c026375 100644 --- a/docs/api/threading/spinlock/spinlock.md +++ b/docs/api/threading/spinlock/spinlock.md @@ -19,6 +19,9 @@ | [`Lock`](lock.md) | 获取锁(忙等待) | | [`Unlock`](unlock.md) | 释放锁 | | [`TryLock`](trylock.md) | 尝试获取锁(非阻塞) | +| [`lock`](lock_1.md) | STL 兼容的 Lock | +| [`unlock`](unlock_1.md) | STL 兼容的 Unlock | +| [`try_lock`](try_lock.md) | STL 兼容的 TryLock | ## STL 兼容方法 @@ -50,4 +53,4 @@ void SafeIncrement() { - [Mutex](../mutex/mutex.md) - 互斥锁 - [ReadWriteLock](../readwritelock/readwritelock.md) - 读写锁 -- [../threading/threading.md](../threading.md) - 模块总览 +- [../threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/spinlock/try_lock.md b/docs/api/threading/spinlock/try_lock.md new file mode 100644 index 00000000..00e638c9 --- /dev/null +++ b/docs/api/threading/spinlock/try_lock.md @@ -0,0 +1,32 @@ +# SpinLock::try_lock + +```cpp +bool try_lock() +``` + +STL 兼容的 `try_lock()` 方法,与 [`TryLock`](trylock.md) 等效。满足 STL `Lockable` 概念要求。 + +**参数:** 无 + +**返回:** `bool` - 获取成功返回 true,锁不可用返回 false + +**复杂度:** O(1) + +**线程安全:** ✅ + +**示例:** + +```cpp +Threading::SpinLock spinLock; + +void STLCompatibleTry() { + if (spinLock.try_lock()) { + // 临界区操作 + spinLock.unlock(); + } +} +``` + +## 相关文档 + +- [SpinLock 总览](spinlock.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/threading/spinlock/unlock_1.md b/docs/api/threading/spinlock/unlock_1.md new file mode 100644 index 00000000..87eb452d --- /dev/null +++ b/docs/api/threading/spinlock/unlock_1.md @@ -0,0 +1,31 @@ +# SpinLock::unlock + +```cpp +void unlock() +``` + +STL 兼容的 `unlock()` 方法,与 [`Unlock`](unlock.md) 等效。满足 STL `Lockable` 概念要求。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**线程安全:** ✅ + +**示例:** + +```cpp +Threading::SpinLock spinLock; + +void STLCompatibleUsage() { + spinLock.lock(); + // 临界区操作 + spinLock.unlock(); +} +``` + +## 相关文档 + +- [SpinLock 总览](spinlock.md) - 返回类总览 \ No newline at end of file diff --git a/docs/api/threading/task-group/add-dependency.md b/docs/api/threading/task-group/add-dependency.md new file mode 100644 index 00000000..8074a4c9 --- /dev/null +++ b/docs/api/threading/task-group/add-dependency.md @@ -0,0 +1,90 @@ +# TaskGroup::AddDependency + +```cpp +void AddDependency(uint64_t taskId, uint64_t dependsOn); +``` + +为任务添加依赖关系。指定的任务 `taskId` 将在 `dependsOn` 任务完成后才会开始执行。 + +**参数:** +- `taskId` - 从属任务的 ID +- `dependsOn` - 被依赖任务的 ID,taskId 将在此任务完成后才执行 + +**返回:** 无 + +**线程安全:** ✅ 线程安全 + +**示例:** + +```cpp +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include +#include + +using namespace XCEngine::Threading; + +int main() { + TaskGroup group; + + uint64_t loadData = group.AddTask( + []() { std::cout << "Loading data...\n"; }, + TaskPriority::High + ); + + uint64_t processData = group.AddTask( + []() { std::cout << "Processing data...\n"; }, + TaskPriority::Normal + ); + + uint64_t saveData = group.AddTask( + []() { std::cout << "Saving data...\n"; }, + TaskPriority::Low + ); + + group.AddDependency(processData, loadData); + group.AddDependency(saveData, processData); + + std::cout << "Execution order: loadData -> processData -> saveData\n"; + + group.Wait(); + return 0; +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 + +## 详细描述 + +`AddDependency` 方法用于设置任务间的依赖关系。`taskId` 指定的任务将等待 `dependsOn` 指定的任务完成后才能开始执行。 + +依赖关系必须在任务执行前设置,建议在所有任务添加完成后统一设置依赖。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `taskId` | `uint64_t` | 依赖其他任务的任务ID | +| `dependsOn` | `uint64_t` | 被依赖的任务ID | + +## 返回值 + +无 + +## 示例 + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +uint64_t loadData = group->AddTask([]() { /* 加载数据 */ }); +uint64_t processData = group->AddTask([]() { /* 处理数据 */ }); +uint64_t saveData = group->AddTask([]() { /* 保存数据 */ }); + +// processData必须在loadData完成后才能执行 +group->AddDependency(processData, loadData); + +// saveData必须在processData完成后才能执行 +group->AddDependency(saveData, processData); +``` diff --git a/docs/api/threading/task-group/add-task-callback.md b/docs/api/threading/task-group/add-task-callback.md new file mode 100644 index 00000000..6a0f3f81 --- /dev/null +++ b/docs/api/threading/task-group/add-task-callback.md @@ -0,0 +1,55 @@ +# TaskGroup::AddTask (Callback) + +```cpp +uint64_t AddTask(Callback&& func, TaskPriority priority = TaskPriority::Normal); +``` + +将函数回调添加为任务。该方法接受一个可调用对象(lambda、函数指针、std::function 等)作为任务执行体。 + +**参数:** +- `func` - 可调用对象,执行任务逻辑 +- `priority` - 任务优先级,默认为 Normal + +**返回:** 返回分配给任务的唯一 ID,可用于后续添加依赖关系 + +**线程安全:** ✅ 线程安全 + +**示例:** + +```cpp +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include + +using namespace XCEngine::Threading; + +int main() { + TaskGroup group; + + uint64_t task1 = group.AddTask( + []() { std::cout << "Task 1 executing\n"; }, + TaskPriority::Normal + ); + + uint64_t task2 = group.AddTask( + []() { std::cout << "Task 2 executing (High priority)\n"; }, + TaskPriority::High + ); + + uint64_t task3 = group.AddTask( + []() { std::cout << "Task 3 executing (Low priority)\n"; }, + TaskPriority::Low + ); + + group.AddDependency(task2, task1); + + group.Wait(); + return 0; +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 +- [AddTask(ITask)](add-task.md) - 添加 ITask 对象形式的任务 +- [TaskPriority](task-priority.md) - 任务优先级说明 diff --git a/docs/api/threading/task-group/add-task.md b/docs/api/threading/task-group/add-task.md new file mode 100644 index 00000000..609f0fd9 --- /dev/null +++ b/docs/api/threading/task-group/add-task.md @@ -0,0 +1,62 @@ +# TaskGroup::AddTask + +```cpp +uint64_t AddTask(std::unique_ptr task); +uint64_t AddTask(Callback&& func, TaskPriority priority = TaskPriority::Normal); +``` + +将任务添加到任务组。支持两种添加方式:传入 ITask 对象或传入回调函数。 + +**参数:** +- `task` - 唯一指针管理的 ITask 对象 +- `func` - 要执行的回调函数 +- `priority` - 任务优先级,默认为 `TaskPriority::Normal` + +**返回:** 返回分配的任务 ID,可用于设置依赖关系 + +**线程安全:** ✅ 线程安全 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include +#include + +using namespace XCEngine::Threading; + +class MyTask : public ITask { +public: + explicit MyTask(const std::string& name) : m_name(name) {} + + void Execute() override { + std::cout << "Executing: " << m_name << "\n"; + } + +private: + std::string m_name; +}; + +int main() { + TaskGroup group; + + auto task = std::make_unique("DataLoading"); + uint64_t taskId = group.AddTask(std::move(task)); + + uint64_t callbackId = group.AddTask([]() { + std::cout << "Lambda task executing\n"; + }, TaskPriority::High); + + group.AddDependency(callbackId, taskId); + + group.Wait(); + return 0; +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 diff --git a/docs/api/threading/task-group/adddependency.md b/docs/api/threading/task-group/adddependency.md deleted file mode 100644 index 94829a4e..00000000 --- a/docs/api/threading/task-group/adddependency.md +++ /dev/null @@ -1,44 +0,0 @@ -# TaskGroup::AddDependency - -```cpp -void AddDependency(uint64_t taskId, uint64_t dependsOn) -``` - -为任务添加依赖关系。被依赖的任务必须先完成,当前任务才会开始执行。 - -**参数:** -- `taskId` - 任务 ID(需要等待的任务) -- `dependsOn` - 依赖的父任务 ID - -**返回:** 无 - -**复杂度:** O(1) - -**注意:** -- 如果被依赖的任务不存在或已完成,调用无效果。 -- 支持添加多个依赖,但不支持循环依赖。 - -**示例:** - -```cpp -TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); - -uint64_t init = group->AddTask([]() { Initialize(); }); -uint64_t task1 = group->AddTask([]() { Phase1(); }); -uint64_t task2 = group->AddTask([]() { Phase2(); }); -uint64_t cleanup = group->AddTask([]() { Cleanup(); }); - -// task1 和 task2 依赖 init -group->AddDependency(task1, init); -group->AddDependency(task2, init); - -// cleanup 依赖 task1 和 task2 -group->AddDependency(cleanup, task1); -group->AddDependency(cleanup, task2); - -group->Wait(); -``` - -## 相关文档 - -- [TaskGroup 总览](task-group.md) - 返回类总览 diff --git a/docs/api/threading/task-group/addtask.md b/docs/api/threading/task-group/addtask.md deleted file mode 100644 index 53dadbeb..00000000 --- a/docs/api/threading/task-group/addtask.md +++ /dev/null @@ -1,60 +0,0 @@ -# TaskGroup::AddTask - -添加任务到任务组。有两个重载版本。 - -## 重载 1: 添加 ITask 对象 - -```cpp -uint64_t AddTask(std::unique_ptr task) -``` - -将一个已有的 ITask 对象添加到任务组。 - -**参数:** -- `task` - 要添加的 unique_ptr 任务对象 - -**返回:** `uint64_t` - 分配的任务 ID - -**复杂度:** O(1) - -## 重载 2: 添加 lambda 任务 - -```cpp -uint64_t AddTask(Callback&& func, TaskPriority priority = TaskPriority::Normal) -``` - -将一个 lambda 函数包装为任务添加到任务组。 - -**参数:** -- `func` - 要执行的可调用对象 -- `priority` - 任务优先级,默认 TaskPriority::Normal - -**返回:** `uint64_t` - 分配的任务 ID - -**复杂度:** O(1) - -**示例:** - -```cpp -TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); - -// 添加 lambda 任务 -uint64_t id1 = group->AddTask([]() { - printf("Task A running\n"); -}); - -uint64_t id2 = group->AddTask([]() { - printf("Task B running\n"); -}, TaskPriority::High); - -// 添加自定义 ITask -class MyTask : public ITask { -public: - void Execute() override { printf("Custom task\n"); } -}; -uint64_t id3 = group->AddTask(std::make_unique()); -``` - -## 相关文档 - -- [TaskGroup 总览](task-group.md) - 返回类总览 diff --git a/docs/api/threading/task-group/cancel.md b/docs/api/threading/task-group/cancel.md index a7a55daa..55d88730 100644 --- a/docs/api/threading/task-group/cancel.md +++ b/docs/api/threading/task-group/cancel.md @@ -1,43 +1,47 @@ # TaskGroup::Cancel ```cpp -void Cancel() +void Cancel(); ``` -**注意:** 此方法为**部分实现**,存在已知问题。 - -取消任务组中所有尚未执行的任务。正在执行的任务将不受影响。 +取消任务组中所有尚未开始执行的任务。已经执行完成的任务和正在执行的任务不受影响。 **参数:** 无 **返回:** 无 -**复杂度:** O(n) - -**当前状态:** 此方法会调用各任务的 `OnCancel()` 回调,但不会减少 `m_pendingCount` 计数器。因此调用 `Wait()` 会导致永久阻塞。建议在 `Cancel()` 后使用 `IsComplete()` 轮询或使用带超时的 `WaitFor()`。 +**线程安全:** ✅ 线程安全 **示例:** ```cpp -TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include +#include -for (int i = 0; i < 100; ++i) { - group->AddTask([i]() { - if (ShouldCancel()) { - return; // 检查取消状态 - } - ProcessLongTask(i); - }); +using namespace XCEngine::Threading; + +int main() { + TaskGroup group; + + for (int i = 0; i < 10; ++i) { + group.AddTask([i]() { + std::cout << "Task " << i << " executing\n"; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + }); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(150)); + + std::cout << "Cancelling remaining tasks...\n"; + group.Cancel(); + + group.Wait(); + std::cout << "Tasks cancelled. Final progress: " << (group.GetProgress() * 100) << "%\n"; + + return 0; } - -// 如果用户点击取消按钮 -if (userClickedCancel) { - group->Cancel(); - printf("Tasks canceled. Progress: %.1f%%\n", group->GetProgress() * 100.0f); -} - -// 注意:Cancel() 后 Wait() 会永久阻塞,应使用 WaitFor() -group->WaitFor(std::chrono::seconds(1)); ``` ## 相关文档 diff --git a/docs/api/threading/task-group/get-progress.md b/docs/api/threading/task-group/get-progress.md new file mode 100644 index 00000000..5176967e --- /dev/null +++ b/docs/api/threading/task-group/get-progress.md @@ -0,0 +1,50 @@ +# TaskGroup::GetProgress + +```cpp +float GetProgress() const; +``` + +获取任务组的完成进度。 + +**参数:** 无 + +**返回:** +- `float` - 0.0 到 1.0 之间的进度值,0.0 表示没有任务或都没有完成,1.0 表示全部完成 + +**线程安全:** ✅ 线程安全 + +**示例:** + +```cpp +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include +#include + +using namespace XCEngine::Threading; + +int main() { + TaskGroup group; + + for (int i = 0; i < 4; ++i) { + group.AddTask([i]() { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + }); + } + + while (!group.IsComplete()) { + float progress = group.GetProgress(); + std::cout << "Progress: " << (progress * 100) << "%\n"; + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + + std::cout << "Final Progress: " << (group.GetProgress() * 100) << "%\n"; + + return 0; +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 +- [IsComplete](is-complete.md) - 检查是否完成 diff --git a/docs/api/threading/task-group/getprogress.md b/docs/api/threading/task-group/getprogress.md deleted file mode 100644 index bf695466..00000000 --- a/docs/api/threading/task-group/getprogress.md +++ /dev/null @@ -1,40 +0,0 @@ -# TaskGroup::GetProgress - -```cpp -float GetProgress() const -``` - -**注意:** 此方法当前为**空实现/桩代码**。 - -获取任务组的完成进度。 - -**参数:** 无 - -**返回:** `float` - 始终返回 `0.0f`(任务组为空时返回 `1.0f`) - -**复杂度:** O(1) - -**当前状态:** 此方法为空实现,始终返回 `0.0f`,因为 `m_completedCount` 未被更新。 - -**示例:** - -```cpp -TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); - -for (int i = 0; i < 1000; ++i) { - group->AddTask([i]() { ProcessItem(i); }); -} - -// 显示进度(注意:当前实现始终返回 0.0f) -while (!group->IsComplete()) { - float progress = group->GetProgress(); - printf("\rProgress: %.1f%%", progress * 100.0f); - Thread::Sleep(100); -} -printf("\n"); -``` - -## 相关文档 - -- [TaskGroup 总览](task-group.md) - 返回类总览 -- [IsComplete](iscomplete.md) - 检查是否完成 diff --git a/docs/api/threading/task-group/is-complete.md b/docs/api/threading/task-group/is-complete.md new file mode 100644 index 00000000..ab4de0c2 --- /dev/null +++ b/docs/api/threading/task-group/is-complete.md @@ -0,0 +1,50 @@ +# TaskGroup::IsComplete + +```cpp +bool IsComplete() const; +``` + +检查任务组中的所有任务是否已完成。 + +**参数:** 无 + +**返回:** +- `true` - 所有任务已完成(包括被取消的) +- `false` - 仍有任务在执行或等待执行 + +**线程安全:** ✅ 线程安全 + +**示例:** + +```cpp +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include +#include + +using namespace XCEngine::Threading; + +int main() { + TaskGroup group; + + group.AddTask([]() { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << "Task completed\n"; + }); + + std::cout << "Immediately after AddTask, IsComplete: " + << (group.IsComplete() ? "true" : "false") << "\n"; + + group.Wait(); + + std::cout << "After Wait, IsComplete: " + << (group.IsComplete() ? "true" : "false") << "\n"; + + return 0; +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 +- [GetProgress](get-progress.md) - 获取进度百分比 diff --git a/docs/api/threading/task-group/iscomplete.md b/docs/api/threading/task-group/iscomplete.md deleted file mode 100644 index 9c8d0eab..00000000 --- a/docs/api/threading/task-group/iscomplete.md +++ /dev/null @@ -1,38 +0,0 @@ -# TaskGroup::IsComplete - -```cpp -bool IsComplete() const -``` - -**注意:** 此方法当前为**空实现/桩代码**。 - -检查任务组中所有任务是否已完成。 - -**参数:** 无 - -**返回:** `bool` - 始终返回 `false`(空实现) - -**复杂度:** O(1)(空实现) - -**当前状态:** 此方法为空实现,始终返回 `false`,因为 `m_pendingCount` 计数器未正确递减。 - -**示例:** - -```cpp -TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); - -for (int i = 0; i < 100; ++i) { - group->AddTask([i]() { HeavyCompute(i); }); -} - -// 非阻塞轮询 -while (!group->IsComplete()) { - printf("Progress: %.1f%%\n", group->GetProgress() * 100.0f); - Thread::Sleep(500); -} -``` - -## 相关文档 - -- [TaskGroup 总览](task-group.md) - 返回类总览 -- [GetProgress](getprogress.md) - 获取完成进度 diff --git a/docs/api/threading/task-group/set-complete-callback.md b/docs/api/threading/task-group/set-complete-callback.md new file mode 100644 index 00000000..1d8c3851 --- /dev/null +++ b/docs/api/threading/task-group/set-complete-callback.md @@ -0,0 +1,82 @@ +# TaskGroup::SetCompleteCallback + +```cpp +void SetCompleteCallback(Callback&& callback); +``` + +设置任务组完成时的回调函数。当所有任务都执行完成后(包括被取消的任务),该回调将被调用。 + +**参数:** +- `callback` - 可调用对象,在所有任务完成后执行 + +**返回:** 无 + +**线程安全:** ✅ 线程安全 + +**示例:** + +```cpp +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include + +using namespace XCEngine::Threading; + +int main() { + TaskGroup group; + + group.SetCompleteCallback([]() { + std::cout << "All tasks have been completed!\n"; + }); + + for (int i = 0; i < 3; ++i) { + group.AddTask([i]() { + std::cout << "Task " << i << " executing\n"; + }); + } + + group.Wait(); + std::cout << "Back in main after Wait()\n"; + + return 0; +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 + +## 详细描述 + +`SetCompleteCallback` 方法用于设置当任务组中所有任务都完成时调用的回调函数。回调在最后一个任务完成时触发。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `callback` | `Callback&&` | 回调函数,类型为 `std::function` | + +## 返回值 + +无 + +## 示例 + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +group->SetCompleteCallback([]() { + printf("All tasks in group have completed!\n"); +}); + +for (int i = 0; i < 10; ++i) { + group->AddTask([i]() { + printf("Task %d completed\n", i); + }); +} + +// 等待所有任务完成,回调会被触发 +group->Wait(); + +TaskSystem::Get().DestroyTaskGroup(group); +``` diff --git a/docs/api/threading/task-group/setcompletecallback.md b/docs/api/threading/task-group/setcompletecallback.md deleted file mode 100644 index 45256a46..00000000 --- a/docs/api/threading/task-group/setcompletecallback.md +++ /dev/null @@ -1,36 +0,0 @@ -# TaskGroup::SetCompleteCallback - -```cpp -void SetCompleteCallback(Callback&& callback) -``` - -设置任务组完成回调。当所有任务都完成后,回调函数将在某个工作线程中被调用。 - -**参数:** -- `callback` - 完成时要调用的回调函数 - -**返回:** 无 - -**复杂度:** O(1) - -**示例:** - -```cpp -TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); - -group->AddTask([]() { LoadTextures(); }); -group->AddTask([]() { LoadMeshes(); }); -group->AddTask([]() { LoadAudio(); }); - -group->SetCompleteCallback([]() { - printf("All assets loaded!\n"); - ResourceManager::InitGPUResources(); -}); - -group->Wait(); -TaskSystem::Get().DestroyTaskGroup(group); -``` - -## 相关文档 - -- [TaskGroup 总览](task-group.md) - 返回类总览 diff --git a/docs/api/threading/task-group/task-group.md b/docs/api/threading/task-group/task-group.md index 646e6c30..14585706 100644 --- a/docs/api/threading/task-group/task-group.md +++ b/docs/api/threading/task-group/task-group.md @@ -6,61 +6,83 @@ **头文件**: `XCEngine/Threading/TaskGroup.h` -**描述**: 任务组管理类,用于组织多个任务并支持批量等待、进度跟踪和依赖管理。 +**描述**: 管理一组相关任务的执行和同步 ## 概述 -`TaskGroup` 提供了一种批量管理任务的机制。它允许添加多个任务、设置任务依赖关系、等待所有任务完成,并提供进度回调功能。 +TaskGroup 用于将多个相关任务组织在一起,统一管理它们的执行和同步。任务组内的任务可以声明依赖关系,确保任务按照正确的顺序执行。支持任务优先级设置、完成回调、进度查询和取消操作。 -## 公共类型 - -| 类型 | 描述 | -|------|------| -| `Callback = std::function` | 任务组回调函数类型 | +主要功能: +- 添加任务(ITask 对象或函数回调) +- 声明任务间依赖关系 +- 等待所有任务完成 +- 设置完成回调 +- 查询完成进度 +- 取消未执行的任务 ## 公共方法 | 方法 | 描述 | |------|------| -| `TaskGroup()` | 默认构造函数 | -| `~TaskGroup()` | 析构函数 | -| [`AddTask(unique_ptr)`](addtask.md) | 添加任务对象 | -| [`AddTask(callback)`](addtask.md) | 添加 lambda 任务 | -| [`AddDependency`](adddependency.md) | 添加任务依赖关系 | +| [`Task()`](task-group.md) | 默认构造函数 | +| [`~Task()`](task-group.md) | 析构函数 | +| [`AddTask`](add-task.md) | 添加任务到组(支持 ITask 或 Callback) | +| [`AddDependency`](add-dependency.md) | 添加任务依赖关系 | | [`Wait`](wait.md) | 阻塞等待所有任务完成 | -| [`WaitFor`](waitfor.md) | 超时等待 | -| [`SetCompleteCallback`](setcompletecallback.md) | 设置完成回调 | -| [`IsComplete`](iscomplete.md) | 检查所有任务是否完成 | -| [`GetProgress`](getprogress.md) | 获取完成进度(0.0f ~ 1.0f) | -| [`Cancel`](cancel.md) | 取消所有任务 | +| [`WaitFor`](wait-for.md) | 等待指定超时时间 | +| [`SetCompleteCallback`](set-complete-callback.md) | 设置完成回调函数 | +| [`IsComplete`](is-complete.md) | 检查所有任务是否完成 | +| [`GetProgress`](get-progress.md) | 获取任务组完成进度 | +| [`Cancel`](cancel.md) | 取消所有未执行的任务 | ## 使用示例 ```cpp -TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include -// 添加多个任务 -uint64_t task1 = group->AddTask([]() { /* 任务1 */ }); -uint64_t task2 = group->AddTask([]() { /* 任务2 */ }); +using namespace XCEngine::Threading; -// 设置依赖:task3 等待 task1 完成 -uint64_t task3 = group->AddTask([]() { /* 任务3 */ }); -group->AddDependency(task3, task1); +class MyTask : public ITask { +public: + explicit MyTask(const std::string& name) : m_name(name) {} -// 设置完成回调 -group->SetCompleteCallback([]() { - printf("All tasks completed!\n"); -}); + void Execute() override { + std::cout << "Task " << m_name << " executing\n"; + } -// 等待完成 -group->Wait(); + void OnComplete() override { + std::cout << "Task " << m_name << " completed\n"; + } -// 销毁 -TaskSystem::Get().DestroyTaskGroup(group); +private: + std::string m_name; +}; + +int main() { + TaskGroup group; + + uint64_t task1 = group.AddTask(std::make_unique("Task1")); + uint64_t task2 = group.AddTask([]() { + std::cout << "Lambda task executing\n"; + }, TaskPriority::High); + + group.AddDependency(task2, task1); + + group.SetCompleteCallback([]() { + std::cout << "All tasks completed!\n"; + }); + + group.Wait(); + + std::cout << "Progress: " << group.GetProgress() * 100 << "%\n"; + + return 0; +} ``` ## 相关文档 -- [ITask](../task/task.md) - 任务基类 -- [TaskSystem](../task-system/task-system.md) - 任务系统 -- [../threading/threading.md](../threading.md) - 模块总览 +- [ITask](../task/task.md) - 任务接口基类 +- [TaskSystem](../task-system/task-system.md) - 任务调度系统 diff --git a/docs/api/threading/task-group/task-priority.md b/docs/api/threading/task-group/task-priority.md new file mode 100644 index 00000000..8af36346 --- /dev/null +++ b/docs/api/threading/task-group/task-priority.md @@ -0,0 +1,59 @@ +# TaskPriority + +**命名空间**: `XCEngine::Threading` + +**类型**: `enum class` + +**头文件**: `XCEngine/Threading/Task.h` + +## 概述 + +`TaskPriority` 定义了任务的优先级,用于控制任务在任务系统中的执行顺序。优先级较高的任务会在优先级较低的任务之前执行。 + +## 枚举值 + +| 枚举值 | 数值 | 描述 | +|--------|------|------| +| `Critical` | 0 | 最高优先级,关键任务 | +| `High` | 1 | 高优先级 | +| `Normal` | 2 | 普通优先级(默认) | +| `Low` | 3 | 低优先级 | +| `Idle` | 4 | 最低优先级,仅在无其他任务时执行 | + +## 使用示例 + +```cpp +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include + +using namespace XCEngine::Threading; + +int main() { + TaskGroup group; + + group.AddTask([]() { + std::cout << "Critical task\n"; + }, TaskPriority::Critical); + + group.AddTask([]() { + std::cout << "High priority task\n"; + }, TaskPriority::High); + + group.AddTask([]() { + std::cout << "Normal task\n"; + }, TaskPriority::Normal); + + group.AddTask([]() { + std::cout << "Low priority task\n"; + }, TaskPriority::Low); + + group.Wait(); + return 0; +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 任务组类总览 +- [ITask](../task/task.md) - 任务接口基类 diff --git a/docs/api/threading/task-group/wait-for.md b/docs/api/threading/task-group/wait-for.md new file mode 100644 index 00000000..8b6c024e --- /dev/null +++ b/docs/api/threading/task-group/wait-for.md @@ -0,0 +1,89 @@ +# TaskGroup::WaitFor + +```cpp +bool WaitFor(std::chrono::milliseconds timeout); +``` + +等待任务组中的所有任务完成,最多等待指定的超时时间。 + +**参数:** +- `timeout` - 最大等待时间 + +**返回:** +- `true` - 所有任务在超时前已完成 +- `false` - 等待超时,仍有任务未完成 + +**线程安全:** ✅ 线程安全 + +**示例:** + +```cpp +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include +#include + +using namespace XCEngine::Threading; + +int main() { + TaskGroup group; + + group.AddTask([]() { + std::this_thread::sleep_for(std::chrono::seconds(5)); + std::cout << "Long running task completed\n"; + }); + + std::cout << "Waiting with 1 second timeout...\n"; + + if (group.WaitFor(std::chrono::milliseconds(1000))) { + std::cout << "All tasks completed within timeout\n"; + } else { + std::cout << "Timeout! Some tasks still running.\n"; + } + + group.Wait(); + std::cout << "All tasks finally completed after second wait.\n"; + + return 0; +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 +- [Wait](wait.md) - 无限等待 + +## 详细描述 + +`WaitFor` 方法会阻塞当前线程,直到所有任务完成或超过指定的超时时间。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `timeout` | `std::chrono::milliseconds` | 超时时间(毫秒) | + +## 返回值 + +返回 `bool` 类型: +- `true`: 所有任务在超时前完成 +- `false`: 发生超时 + +## 示例 + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +group->AddTask([]() { + std::this_thread::sleep_for(std::chrono::seconds(5)); +}); + +// 等待3秒超时 +if (group->WaitFor(std::chrono::milliseconds(3000))) { + printf("All tasks completed on time\n"); +} else { + printf("Wait timed out\n"); +} + +TaskSystem::Get().DestroyTaskGroup(group); +``` diff --git a/docs/api/threading/task-group/wait.md b/docs/api/threading/task-group/wait.md index 0d8765e2..2b7ab31d 100644 --- a/docs/api/threading/task-group/wait.md +++ b/docs/api/threading/task-group/wait.md @@ -1,46 +1,47 @@ # TaskGroup::Wait ```cpp -void Wait() +void Wait(); ``` -**注意:** 此方法当前为**空实现/桩代码**,不执行任何操作。 - -阻塞当前线程,等待任务组中所有任务完成。 +阻塞当前线程,直到任务组中的所有任务完成执行。 **参数:** 无 **返回:** 无 -**复杂度:** N/A(空实现) - -**当前状态:** 此方法为空实现,不执行任何操作。由于 `m_pendingCount` 计数器未正确更新,此方法永远无法正常运作。 - -**建议:** 使用 `WaitFor()` 代替以避免永久阻塞。 +**线程安全:** ✅ 线程安全 **示例:** ```cpp -TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); +#include "XCEngine/Threading/TaskGroup.h" +#include "XCEngine/Threading/Task.h" +#include +#include -for (int i = 0; i < 10; ++i) { - group->AddTask([i]() { - printf("Task %d running\n", i); - }); +using namespace XCEngine::Threading; + +int main() { + TaskGroup group; + + for (int i = 0; i < 5; ++i) { + group.AddTask([i]() { + std::cout << "Task " << i << " started\n"; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::cout << "Task " << i << " finished\n"; + }); + } + + std::cout << "Waiting for all tasks...\n"; + group.Wait(); + std::cout << "All tasks completed!\n"; + + return 0; } - -printf("Waiting for all tasks...\n"); -// 注意:Wait() 为空实现,建议使用 WaitFor() -if (group->WaitFor(std::chrono::seconds(5))) { - printf("All tasks completed within 5 seconds\n"); -} else { - printf("Timeout! Tasks may not have completed\n"); -} - -TaskSystem::Get().DestroyTaskGroup(group); ``` ## 相关文档 - [TaskGroup 总览](task-group.md) - 返回类总览 -- [WaitFor](waitfor.md) - 超时等待 +- [WaitFor](wait-for.md) - 带超时的等待 diff --git a/docs/api/threading/task-group/waitfor.md b/docs/api/threading/task-group/waitfor.md deleted file mode 100644 index f64c42f3..00000000 --- a/docs/api/threading/task-group/waitfor.md +++ /dev/null @@ -1,39 +0,0 @@ -# TaskGroup::WaitFor - -```cpp -bool WaitFor(std::chrono::milliseconds timeout) -``` - -等待任务组中所有任务完成,可在超时后返回。 - -**参数:** -- `timeout` - 最大等待时间 - -**返回:** `bool` - 所有任务在超时前完成返回 true,超时返回 false - -**复杂度:** O(n) - -**示例:** - -```cpp -TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); - -for (int i = 0; i < 5; ++i) { - group->AddTask([i]() { - Thread::Sleep(i * 100); - printf("Task %d done\n", i); - }); -} - -if (group->WaitFor(std::chrono::seconds(1))) { - printf("All tasks completed within 1 second\n"); -} else { - printf("Timeout! Some tasks still running\n"); - printf("Progress: %.1f%%\n", group->GetProgress() * 100.0f); -} -``` - -## 相关文档 - -- [TaskGroup 总览](task-group.md) - 返回类总览 -- [Wait](wait.md) - 无超时等待 diff --git a/docs/api/threading/task-system/createtaskgroup.md b/docs/api/threading/task-system/createtaskgroup.md index 6232ca43..a56923af 100644 --- a/docs/api/threading/task-system/createtaskgroup.md +++ b/docs/api/threading/task-system/createtaskgroup.md @@ -10,6 +10,8 @@ TaskGroup* CreateTaskGroup() **返回:** `TaskGroup*` - 新创建的任务组指针 +**线程安全:** ✅ (内部使用 SpinLock 保护) + **复杂度:** O(1) **注意:** diff --git a/docs/api/threading/task-system/destroytaskgroup.md b/docs/api/threading/task-system/destroytaskgroup.md index cc362db0..f4b29c93 100644 --- a/docs/api/threading/task-system/destroytaskgroup.md +++ b/docs/api/threading/task-system/destroytaskgroup.md @@ -11,6 +11,8 @@ void DestroyTaskGroup(TaskGroup* group) **返回:** 无 +**线程安全:** ✅ (内部使用 SpinLock 保护) + **复杂度:** O(1) **注意:** diff --git a/docs/api/threading/task-system/getworkerthreadcount.md b/docs/api/threading/task-system/getworkerthreadcount.md index d9ba16f6..e4acf71f 100644 --- a/docs/api/threading/task-system/getworkerthreadcount.md +++ b/docs/api/threading/task-system/getworkerthreadcount.md @@ -10,6 +10,8 @@ uint32_t GetWorkerThreadCount() const **返回:** `uint32_t` - 工作线程数量 +**线程安全:** ✅ (只读操作) + **复杂度:** O(1) **示例:** diff --git a/docs/api/threading/task-system/initialize.md b/docs/api/threading/task-system/initialize.md index 82ca1a02..6e079458 100644 --- a/docs/api/threading/task-system/initialize.md +++ b/docs/api/threading/task-system/initialize.md @@ -11,6 +11,8 @@ void Initialize(const TaskSystemConfig& config) **返回:** 无 +**线程安全:** ❌ (应在主线程初始化) + **复杂度:** O(n),n 为 workerThreadCount **注意:** diff --git a/docs/api/threading/task-system/parallelfor.md b/docs/api/threading/task-system/parallelfor.md index 589aecc4..0ef7ebe0 100644 --- a/docs/api/threading/task-system/parallelfor.md +++ b/docs/api/threading/task-system/parallelfor.md @@ -17,6 +17,8 @@ void ParallelFor(int32_t start, int32_t end, Func&& func) **返回:** 无 +**线程安全:** ✅ (内部通过 Submit 实现线程安全) + **复杂度:** O(n) **分区策略:** diff --git a/docs/api/threading/task-system/runonmainthread.md b/docs/api/threading/task-system/runonmainthread.md index 5afc1493..4270da15 100644 --- a/docs/api/threading/task-system/runonmainthread.md +++ b/docs/api/threading/task-system/runonmainthread.md @@ -11,6 +11,8 @@ void RunOnMainThread(std::function&& func) **返回:** 无 +**线程安全:** ✅ (内部使用 mutex 保护主线程队列) + **复杂度:** O(1) **使用场景:** diff --git a/docs/api/threading/task-system/shutdown.md b/docs/api/threading/task-system/shutdown.md index 6d1d0c45..af8bffaf 100644 --- a/docs/api/threading/task-system/shutdown.md +++ b/docs/api/threading/task-system/shutdown.md @@ -10,6 +10,8 @@ void Shutdown() **返回:** 无 +**线程安全:** ❌ (非线程安全,调用后应等待所有任务完成) + **复杂度:** O(n) **注意:** diff --git a/docs/api/threading/task-system/submit.md b/docs/api/threading/task-system/submit.md index beafa89f..3c9b69ff 100644 --- a/docs/api/threading/task-system/submit.md +++ b/docs/api/threading/task-system/submit.md @@ -33,6 +33,8 @@ uint64_t Submit(std::function&& func, TaskPriority priority = TaskPriori **复杂度:** O(log n) +**线程安全:** ✅ (内部使用 mutex 保护任务队列) + **示例:** ```cpp @@ -52,10 +54,12 @@ uint64_t id3 = TaskSystem::Get().Submit([]() { HeavyCompute(); }, TaskPriority::High); -// 等待任务完成 -TaskSystem::Get().Wait(id1); -TaskSystem::Get().Wait(id2); -TaskSystem::Get().Wait(id3); +// 使用 TaskGroup 等待任务完成 +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); +group->AddTask([]() { /* task 1 */ }); +group->AddTask([]() { /* task 2 */ }); +group->Wait(); +TaskSystem::Get().DestroyTaskGroup(group); ``` ## 相关文档 diff --git a/docs/api/threading/task-system/task-system.md b/docs/api/threading/task-system/task-system.md index dc40ef78..36f9fd48 100644 --- a/docs/api/threading/task-system/task-system.md +++ b/docs/api/threading/task-system/task-system.md @@ -12,7 +12,7 @@ `TaskSystem` 是 XCEngine 的核心并行任务调度系统。它创建多个工作线程,使用优先级队列调度任务。它还提供 `ParallelFor` 方法用于数据级并行,以及主线程任务队列。 -**注意:** 当前实现的 `stealTasks` 配置项未生效,任务系统使用单一全局任务队列而非工作窃取模式。 +**注意:** 当前实现的 `stealTasks` 配置项未生效,任务系统使用单一全局优先级任务队列。 ## 单例访问 @@ -24,7 +24,8 @@ | 方法 | 描述 | |------|------| -| [`Get`](get.md) | 获取单例实例 | +| [`TaskSystem()`](task-system.md) | 私有构造函数(单例) | +| [`~TaskSystem()`](task-system.md) | 析构函数 | | [`Initialize`](initialize.md) | 初始化任务系统 | | [`Shutdown`](shutdown.md) | 关闭任务系统 | | [`Submit(unique_ptr)`](submit.md) | 提交任务对象 | diff --git a/docs/api/threading/task-system/update.md b/docs/api/threading/task-system/update.md index adfe429e..0ef52215 100644 --- a/docs/api/threading/task-system/update.md +++ b/docs/api/threading/task-system/update.md @@ -10,6 +10,8 @@ void Update() **返回:** 无 +**线程安全:** ❌ (应在主线程调用) + **复杂度:** O(n),n 为队列中待执行任务数 **使用场景:** diff --git a/docs/api/threading/task-system/wait.md b/docs/api/threading/task-system/wait.md index d6e2e7df..bc16fab8 100644 --- a/docs/api/threading/task-system/wait.md +++ b/docs/api/threading/task-system/wait.md @@ -6,17 +6,10 @@ void Wait(uint64_t taskId) **注意:** 此方法当前为空实现,不执行任何操作。 -**参数:** -- `taskId` - 要等待的任务 ID - -**返回:** 无 - -**复杂度:** N/A(空实现) - -**当前状态:** 此方法为空实现,不执行任何操作。任务系统目前不支持按任务 ID 等待。 - **建议:** 使用 `TaskGroup::Wait` 代替此方法。 +**线程安全:** N/A (空实现) + **示例:** ```cpp diff --git a/docs/api/threading/task/task.md b/docs/api/threading/task/task.md index 4b33cf8d..0ac3f6bd 100644 --- a/docs/api/threading/task/task.md +++ b/docs/api/threading/task/task.md @@ -42,8 +42,6 @@ | 方法 | 描述 | |------|------| | `virtual ~ITask()` | 虚析构函数 | -| `ITask()` | 默认构造函数(受保护) | -| `ITask(TaskPriority priority)` | 带优先级的构造函数(受保护) | | [`Execute`](execute.md) | 任务执行逻辑(纯虚) | | [`OnComplete`](oncomplete.md) | 任务完成回调(可重写) | | [`OnCancel`](oncancel.md) | 任务取消回调(可重写) | @@ -56,6 +54,13 @@ | [`AddRef`](addref.md) | 增加引用计数 | | [`Release`](release.md) | 减少引用计数(引用归零时自动 delete) | +## 受保护方法 + +| 方法 | 描述 | +|------|------| +| `ITask()` | 默认构造函数 | +| `ITask(TaskPriority priority)` | 带优先级的构造函数 | + ## 使用示例 ```cpp diff --git a/docs/api/threading/thread/detach.md b/docs/api/threading/thread/detach.md index 4372841c..32e05617 100644 --- a/docs/api/threading/thread/detach.md +++ b/docs/api/threading/thread/detach.md @@ -1,36 +1,44 @@ # Thread::Detach ```cpp -void Detach() +void Detach(); ``` -分离线程,使其成为后台线程独立运行。分离后,线程的资源将在其终止时自动释放,调用线程不会被阻塞。 +分离线程,使其在后台独立运行。调用 `Detach()` 后,线程不再受 `Thread` 对象管理,其生命周期由 C++ 运行时库自行管理,直到线程函数执行完毕。 + +分离后的线程成为"守护线程",其资源在线程结束时自动由运行时回收。与 `Join()` 不同,`Detach()` 只能调用一次。 + +**警告:** 分离线程时必须确保其访问的所有数据在线程运行期间保持有效。分离后无法通过 `Thread` 对象同步或等待线程。 **参数:** 无 **返回:** 无 -**复杂度:** O(1) - -**注意:** -- 分离后的线程无法再被 Join 或进行任何同步操作。 -- 确保分离线程的所有资源访问都是线程安全的,因为主线程可能在分离线程结束前退出。 -- 如果 Thread 对象在分离线程结束前被销毁,行为取决于具体实现。 +**线程安全:** ❌ **示例:** ```cpp -Thread background; -background.Start([]() { - printf("Background task running\n"); - for (int i = 0; i < 3; ++i) { - Thread::Sleep(500); - printf("Background: tick %d\n", i); - } -}, "BackgroundThread"); +#include "XCEngine/Threading/Thread.h" +#include -background.Detach(); -printf("Main thread continues immediately\n"); +using namespace XCEngine::Threading; + +int main() { + Thread t; + t.Start([]() { + for (int i = 0; i < 3; ++i) { + std::cout << "Detached thread running: " << i << std::endl; + Thread::Sleep(50); + } + }, "DetachedThread"); + + std::cout << "Thread detached, main continues..." << std::endl; + t.Detach(); + + Thread::Sleep(200); + return 0; +} ``` ## 相关文档 diff --git a/docs/api/threading/thread/getcurrentid.md b/docs/api/threading/thread/getcurrentid.md index 6b5cbc2d..9dac16c1 100644 --- a/docs/api/threading/thread/getcurrentid.md +++ b/docs/api/threading/thread/getcurrentid.md @@ -1,27 +1,40 @@ # Thread::GetCurrentId ```cpp -static Id GetCurrentId() +static Id GetCurrentId(); ``` -获取当前执行线程的唯一标识符。这是一个静态方法,可以在任何线程上下文中调用。 +静态方法,返回当前执行线程的唯一标识符。此方法可在任意线程上下文中调用,包括主线程和工作线程。 + +线程 ID 通过 `std::this_thread::get_id()` 获取,并使用 `std::hash` 转换为 `uint64_t` 值。该值与 `Thread::GetId()` 返回的值格式一致,可以直接比较。 **参数:** 无 -**返回:** `Thread::Id` - 当前执行线程的唯一标识符 +**返回:** 调用线程的唯一标识符 -**复杂度:** O(1) +**线程安全:** ✅ **示例:** ```cpp -Thread worker; -worker.Start([]() { - printf("Worker thread id: %llu\n", (unsigned long long)Thread::GetCurrentId()); -}, "WorkerThread"); +#include "XCEngine/Threading/Thread.h" +#include -printf("Main thread id: %llu\n", (unsigned long long)Thread::GetCurrentId()); -worker.Join(); +using namespace XCEngine::Threading; + +int main() { + std::cout << "Main thread ID: " << Thread::GetCurrentId() << std::endl; + + Thread t; + t.Start([]() { + std::cout << "Worker thread ID: " << Thread::GetCurrentId() << std::endl; + std::cout << "Worker ID matches Thread.GetId(): " + << (Thread::GetCurrentId() == t.GetId() ? "Yes" : "No") << std::endl; + }, "CheckIdThread"); + + t.Join(); + return 0; +} ``` ## 相关文档 diff --git a/docs/api/threading/thread/getid.md b/docs/api/threading/thread/getid.md index 033812ab..8784d6f6 100644 --- a/docs/api/threading/thread/getid.md +++ b/docs/api/threading/thread/getid.md @@ -1,27 +1,41 @@ # Thread::GetId ```cpp -Id GetId() const +Id GetId() const; ``` -获取当前线程对象的唯一标识符。该 ID 在线程启动后有效。 +返回当前线程对象的唯一标识符。线程 ID 是 `uint64_t` 类型的值,通过 `std::thread::native_handle()` 获取原生线程句柄并转换为整数。 + +线程 ID 在线程启动后生效。在调用 `Start()` 之前,`GetId()` 返回 0。 **参数:** 无 -**返回:** `Thread::Id` - 线程的唯一标识符(uint64_t 类型) +**返回:** 线程的唯一标识符,线程未启动时返回 0 -**复杂度:** O(1) - -**注意:** 在调用 Start 之前返回 0。 +**线程安全:** ✅ **示例:** ```cpp -Thread worker; -printf("Before start: id=%llu\n", (unsigned long long)worker.GetId()); -worker.Start([]() {}, "Test"); -printf("After start: id=%llu\n", (unsigned long long)worker.GetId()); -worker.Join(); +#include "XCEngine/Threading/Thread.h" +#include + +using namespace XCEngine::Threading; + +int main() { + Thread t; + + std::cout << "Before Start - Thread ID: " << t.GetId() << std::endl; + + t.Start([]() { + std::cout << "Worker ID: " << Thread::GetCurrentId() << std::endl; + }, "WorkerThread"); + + std::cout << "After Start - Thread ID: " << t.GetId() << std::endl; + + t.Join(); + return 0; +} ``` ## 相关文档 diff --git a/docs/api/threading/thread/getname.md b/docs/api/threading/thread/getname.md index 6603fc2e..d7f7a20c 100644 --- a/docs/api/threading/thread/getname.md +++ b/docs/api/threading/thread/getname.md @@ -1,26 +1,47 @@ # Thread::GetName ```cpp -const Containers::String& GetName() const +const Containers::String& GetName() const; ``` -获取线程的名称。该名称在调用 Start 时设置。 +返回线程的名称。线程名称在调用 `Start()` 时通过参数指定,默认为 "Thread"。返回的引用指向内部存储的 `Containers::String` 对象。 + +线程名称主要用于调试、日志记录和性能分析工具中标识线程。 **参数:** 无 -**返回:** `const Containers::String&` - 线程名称的引用 +**返回:** 线程名称的常量引用 -**复杂度:** O(1) - -**注意:** 在调用 Start 之前返回空字符串。 +**线程安全:** ✅ **示例:** ```cpp -Thread worker; -worker.Start([]() {}, "ComputeThread"); -printf("Thread name: %s\n", worker.GetName().CStr()); -worker.Join(); +#include "XCEngine/Threading/Thread.h" +#include + +using namespace XCEngine::Threading; + +int main() { + Thread t1; + t1.Start([]() {}, "RenderingThread"); + + Thread t2; + t2.Start([]() {}, "PhysicsThread"); + + Thread t3; + t3.Start([]() {}); + + std::cout << "Thread 1 name: " << t1.GetName().CStr() << std::endl; + std::cout << "Thread 2 name: " << t2.GetName().CStr() << std::endl; + std::cout << "Thread 3 name: " << t3.GetName().CStr() << std::endl; + + t1.Join(); + t2.Join(); + t3.Join(); + + return 0; +} ``` ## 相关文档 diff --git a/docs/api/threading/thread/join.md b/docs/api/threading/thread/join.md index b0f16c79..064fbdef 100644 --- a/docs/api/threading/thread/join.md +++ b/docs/api/threading/thread/join.md @@ -1,35 +1,45 @@ # Thread::Join ```cpp -void Join() +void Join(); ``` -等待线程结束并回收其资源。调用线程将被阻塞,直到目标线程完成执行。 +等待线程执行完成并回收其资源。调用 `Join()` 会阻塞当前线程,直到目标线程结束运行。如果目标线程已经结束或从未启动,则此调用立即返回。 + +`Join()` 只能调用一次。在调用 `Join()` 后,`std::thread` 对象不再代表任何线程,不能再次调用 `Join()` 或 `Detach()`。 + +析构函数会自动调用 `Join()`,确保线程对象销毁前等待线程结束。 + +**注意:** 如果线程已经被分离(Detach)或已经 Join 过,调用此方法将导致未定义行为。 **参数:** 无 **返回:** 无 -**复杂度:** O(n),n 为目标线程的执行时间 - -**注意:** -- 如果线程已经被分离(Detach)或已经 Join 过,调用此方法将导致未定义行为。 -- 建议在使用完 Thread 对象后始终调用 Join 或 Detach。 +**线程安全:** ❌ **示例:** ```cpp -Thread worker; -worker.Start([]() { - for (int i = 0; i < 5; ++i) { - printf("Working...\n"); - Thread::Sleep(100); - } -}, "WorkerThread"); +#include "XCEngine/Threading/Thread.h" +#include -printf("Main thread waiting...\n"); -worker.Join(); -printf("Worker thread finished\n"); +using namespace XCEngine::Threading; + +int main() { + Thread t; + t.Start([]() { + for (int i = 0; i < 3; ++i) { + std::cout << "Working... " << i << std::endl; + Thread::Sleep(100); + } + }, "WorkerThread"); + + std::cout << "Waiting for thread to complete..." << std::endl; + t.Join(); + std::cout << "Thread completed!" << std::endl; + return 0; +} ``` ## 相关文档 diff --git a/docs/api/threading/thread/sleep.md b/docs/api/threading/thread/sleep.md index 9e837dda..b8138eb7 100644 --- a/docs/api/threading/thread/sleep.md +++ b/docs/api/threading/thread/sleep.md @@ -1,27 +1,34 @@ # Thread::Sleep ```cpp -static void Sleep(uint32_t milliseconds) +static void Sleep(uint32_t milliseconds); ``` -使当前线程休眠指定的时间。线程在休眠期间不会消耗 CPU 时间。 +静态方法,使当前线程进入休眠状态指定毫秒数。在休眠期间,线程不会消耗 CPU 时间片,让系统可以将资源分配给其他线程。 + +实现基于 `std::this_thread::sleep_for`,使用 `std::chrono::milliseconds` 包装休眠时长。休眠精度取决于操作系统调度器的精度。 **参数:** -- `milliseconds` - 休眠时间,以毫秒为单位 +- `milliseconds` - 休眠时长,以毫秒为单位 **返回:** 无 -**复杂度:** 取决于操作系统的调度精度,通常为 O(milliseconds) +**线程安全:** ✅ **示例:** ```cpp -printf("Start\n"); -Thread::Sleep(1000); // 休眠1秒 -printf("After 1 second\n"); +#include "XCEngine/Threading/Thread.h" +#include -Thread::Sleep(500); // 再休眠0.5秒 -printf("After 0.5 more seconds\n"); +using namespace XCEngine::Threading; + +int main() { + std::cout << "Sleeping for 500ms..." << std::endl; + Thread::Sleep(500); + std::cout << "Wake up!" << std::endl; + return 0; +} ``` ## 相关文档 diff --git a/docs/api/threading/thread/start.md b/docs/api/threading/thread/start.md index 505d7543..45e7c75c 100644 --- a/docs/api/threading/thread/start.md +++ b/docs/api/threading/thread/start.md @@ -2,34 +2,44 @@ ```cpp template -void Start(Func&& func, const Containers::String& name = "Thread") +void Start(Func&& func, const Containers::String& name = "Thread"); ``` -启动线程,执行传入的可调用对象。该方法创建一个新的执行线程,立即开始运行。 +启动一个新线程并执行传入的可调用对象。该方法是模板方法,可以接受任何可调用对象,包括普通函数、Lambda 表达式、仿函数等。 + +调用 `Start()` 后,线程立即开始执行。线程 ID 通过 `native_handle()` 获取并转换为 `uint64_t` 类型。 + +**注意:** `Start()` 不是线程安全的,不应在同一 `Thread` 对象上并发调用。 **参数:** -- `func` - 要在线程中执行的可调用对象(lambda、函数指针、仿函数等) -- `name` - 线程名称,用于调试和日志输出,默认值为 "Thread" +- `func` - 要执行的线程函数,可以是任意可调用对象 +- `name` - 线程名称,默认为 "Thread",用于调试和日志记录 **返回:** 无 -**复杂度:** O(1) - -**线程安全:** 该方法不是线程安全的,不应在同一 Thread 对象上并发调用。 +**线程安全:** ❌ **示例:** ```cpp -#include "Threading/Thread.h" +#include "XCEngine/Threading/Thread.h" +#include -Thread worker; -worker.Start([]() { - printf("Worker thread running\n"); - Thread::Sleep(100); - printf("Worker thread done\n"); -}, "WorkerThread"); +using namespace XCEngine::Threading; -worker.Join(); +void FreeFunction(int value) { + std::cout << "Free function called with: " << value << std::endl; +} + +int main() { + Thread t; + t.Start(FreeFunction, "FreeFuncThread"); + t.Start([]() { + std::cout << "Lambda thread executing" << std::endl; + }, "LambdaThread"); + t.Join(); + return 0; +} ``` ## 相关文档 diff --git a/docs/api/threading/thread/thread.md b/docs/api/threading/thread/thread.md index a6887b9d..86bea89a 100644 --- a/docs/api/threading/thread/thread.md +++ b/docs/api/threading/thread/thread.md @@ -6,24 +6,26 @@ **头文件**: `XCEngine/Threading/Thread.h` -**描述**: 线程封装类,提供跨平台线程创建和管理功能。 +**描述**: 线程类,封装 std::thread 提供命名的线程管理功能。 ## 概述 -`Thread` 类封装了 `std::thread`,提供统一的线程管理接口,包括启动、加入、分离等操作。 +`Thread` 类封装了 `std::thread`,提供统一的线程管理接口。设计用于跨平台线程创建和管理,支持为线程指定名称便于调试和日志记录。 -## 公共类型 +类提供实例方法用于启动、等待(Join)和分离(Detach)线程,以及静态工具方法用于获取当前线程 ID、线程睡眠和让出 CPU 时间片。 -| 类型 | 描述 | -|------|------| -| `using Id = uint64_t` | 线程唯一标识符类型 | +## 类型别名 + +| 类型 | 定义 | 描述 | +|------|------|------| +| `Id` | `uint64_t` | 线程唯一标识符类型 | ## 公共方法 | 方法 | 描述 | |------|------| -| `Thread()` | 默认构造函数 | -| `~Thread()` | 析构函数 | +| [`Thread()`](thread.md) | 默认构造函数 | +| [`~Thread()`](thread.md) | 析构函数 | | [`Start`](start.md) | 启动线程,执行传入的函数 | | [`Join`](join.md) | 等待线程结束 | | [`Detach`](detach.md) | 分离线程,使其独立运行 | @@ -36,25 +38,28 @@ ## 使用示例 ```cpp -#include "Threading/Thread.h" +#include "XCEngine/Threading/Thread.h" -// 创建并启动线程 -Thread thread; -thread.Start([]() { +using namespace XCEngine::Threading; + +void WorkerFunction() { printf("Worker thread running\n"); -}, "WorkerThread"); +} -// 等待线程结束 -thread.Join(); +int main() { + Thread thread; + thread.Start(WorkerFunction, "WorkerThread"); + thread.Join(); -// 使用静态方法 -Thread::Sleep(1000); // 休眠1秒 -Thread::Yield(); // 让出时间片 -auto currentId = Thread::GetCurrentId(); + Thread::Sleep(1000); + Thread::Yield(); + auto currentId = Thread::GetCurrentId(); + return 0; +} ``` ## 相关文档 - [Mutex](../mutex/mutex.md) - 互斥锁 - [TaskSystem](../task-system/task-system.md) - 任务调度系统 -- [../threading/threading.md](../threading.md) - 模块总览 +- [../threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/thread/yield.md b/docs/api/threading/thread/yield.md index 9024b9ab..7c94773b 100644 --- a/docs/api/threading/thread/yield.md +++ b/docs/api/threading/thread/yield.md @@ -1,37 +1,47 @@ # Thread::Yield ```cpp -static void Yield() +static void Yield(); ``` -让出当前线程的时间片,允许操作系统调度器将 CPU 时间分配给其他就绪线程。 +静态方法,向调度器提示当前线程愿意让出 CPU 时间片,让其他线程有机会执行。此方法适用于需要 busy-wait 或自旋等待的场景。 + +实现基于 `std::this_thread::yield()`。调度器行为取决于操作系统。 + +**警告:** 过度使用 `Yield()` 可能导致性能问题。在多数情况下,使用 `Sleep()` 是更好的选择。 **参数:** 无 **返回:** 无 -**复杂度:** O(1) - -**使用场景:** -- 在自旋等待某个条件时调用,避免浪费 CPU 周期。 -- 在长时间循环中定期让出时间片,提高其他线程的响应性。 +**线程安全:** ✅ **示例:** ```cpp -volatile bool ready = false; +#include "XCEngine/Threading/Thread.h" +#include +#include -Thread worker; -worker.Start([]() { - ready = true; -}, "WorkerThread"); +using namespace XCEngine::Threading; -// 忙等待,但定期让出时间片 -while (!ready) { - Thread::Yield(); +int main() { + std::atomic ready{false}; + + Thread t; + t.Start([&ready]() { + while (!ready.load()) { + Thread::Yield(); + } + std::cout << "Worker: ready flag is set!" << std::endl; + }, "YieldWorker"); + + Thread::Sleep(100); + ready.store(true); + + t.Join(); + return 0; } - -worker.Join(); ``` ## 相关文档 diff --git a/docs/api/threading/threading.md b/docs/api/threading/threading.md index c86e011b..6ac0e86a 100644 --- a/docs/api/threading/threading.md +++ b/docs/api/threading/threading.md @@ -4,6 +4,8 @@ **类型**: `module` +**头文件**: `XCEngine/Threading/Threading.h` + **描述**: XCEngine 的线程和并发模块,提供多线程编程所需的同步原语和任务系统。 ## 概述