94 lines
2.7 KiB
C++
94 lines
2.7 KiB
C++
#pragma once
|
|
#include <cstddef>
|
|
#include <vector>
|
|
#include <new>
|
|
|
|
namespace vde::foundation {
|
|
|
|
/**
|
|
* @brief 固定块大小的内存池
|
|
*
|
|
* 使用空闲链表实现 O(1) 的分配和释放。按固定大小的 chunk 预先分配内存,
|
|
* 适合频繁创建/销毁同类型小对象的场景(如半边网格的顶点和面)。
|
|
*
|
|
* @tparam T 池中存储的对象类型
|
|
*
|
|
* @note 内存池不调用对象的构造函数/析构函数,仅管理原始内存
|
|
* @note 适合 POD 类型或通过 placement new 手动管理生命周期的类型
|
|
* @warning 不在单个对象释放时归还内存给操作系统;仅在池析构时统一释放所有 chunk
|
|
*
|
|
* @code{.cpp}
|
|
* MemoryPool<Vertex> pool(4096);
|
|
* Vertex* v = pool.allocate(); // O(1)
|
|
* // ... 使用 v ...
|
|
* pool.deallocate(v); // O(1)
|
|
* @endcode
|
|
*
|
|
* @ingroup foundation
|
|
*/
|
|
template <typename T>
|
|
class MemoryPool {
|
|
public:
|
|
/**
|
|
* @brief 构造内存池
|
|
* @param chunk_size 每个内存块可容纳的对象数(默认 1024)
|
|
*/
|
|
explicit MemoryPool(size_t chunk_size = 1024) : chunk_size_(chunk_size) {}
|
|
|
|
/**
|
|
* @brief 析构内存池,释放所有已分配的内存块
|
|
*/
|
|
~MemoryPool() { for (auto* p : chunks_) ::operator delete(p); }
|
|
|
|
/**
|
|
* @brief 从池中分配 n 个 T 对象的内存
|
|
*
|
|
* 当前实现忽略 n 参数,每次始终分配一个对象。
|
|
* 若空闲链表为空,自动分配新的 chunk。
|
|
*
|
|
* @param n 对象数量(当前未使用,保留用于 API 兼容)
|
|
* @return 指向未初始化内存的指针
|
|
*
|
|
* @pre n 应小于 chunk_size_
|
|
*/
|
|
T* allocate(size_t n = 1) {
|
|
if (free_list_ == nullptr) allocate_chunk();
|
|
T* p = static_cast<T*>(free_list_);
|
|
free_list_ = *reinterpret_cast<void**>(free_list_);
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief 将内存归还到池中
|
|
*
|
|
* 将对象内存插入空闲链表头部,不调用析构函数。
|
|
*
|
|
* @param p 之前从 allocate() 获取的指针
|
|
*/
|
|
void deallocate(T* p, size_t = 1) {
|
|
*reinterpret_cast<void**>(p) = free_list_;
|
|
free_list_ = p;
|
|
}
|
|
|
|
private:
|
|
/**
|
|
* @brief 分配一个新的内存块并初始化空闲链表
|
|
*/
|
|
void allocate_chunk() {
|
|
void* chunk = ::operator new(chunk_size_ * sizeof(T));
|
|
chunks_.push_back(chunk);
|
|
char* base = static_cast<char*>(chunk);
|
|
for (size_t i = 0; i < chunk_size_; ++i) {
|
|
void* ptr = base + i * sizeof(T);
|
|
*reinterpret_cast<void**>(ptr) = free_list_;
|
|
free_list_ = ptr;
|
|
}
|
|
}
|
|
|
|
size_t chunk_size_;
|
|
void* free_list_ = nullptr;
|
|
std::vector<void*> chunks_;
|
|
};
|
|
|
|
} // namespace vde::foundation
|