#pragma once #include #include #include namespace vde::foundation { /** * @brief 固定块大小的内存池 * * 使用空闲链表实现 O(1) 的分配和释放。按固定大小的 chunk 预先分配内存, * 适合频繁创建/销毁同类型小对象的场景(如半边网格的顶点和面)。 * * @tparam T 池中存储的对象类型 * * @note 内存池不调用对象的构造函数/析构函数,仅管理原始内存 * @note 适合 POD 类型或通过 placement new 手动管理生命周期的类型 * @warning 不在单个对象释放时归还内存给操作系统;仅在池析构时统一释放所有 chunk * * @code{.cpp} * MemoryPool pool(4096); * Vertex* v = pool.allocate(); // O(1) * // ... 使用 v ... * pool.deallocate(v); // O(1) * @endcode * * @ingroup foundation */ template 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(free_list_); free_list_ = *reinterpret_cast(free_list_); return p; } /** * @brief 将内存归还到池中 * * 将对象内存插入空闲链表头部,不调用析构函数。 * * @param p 之前从 allocate() 获取的指针 */ void deallocate(T* p, size_t = 1) { *reinterpret_cast(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(chunk); for (size_t i = 0; i < chunk_size_; ++i) { void* ptr = base + i * sizeof(T); *reinterpret_cast(ptr) = free_list_; free_list_ = ptr; } } size_t chunk_size_; void* free_list_ = nullptr; std::vector chunks_; }; } // namespace vde::foundation