动态内存池代码
mem_pool.h
#pragma once #include <cstdint> #include <vector> #include <string> #include "macros.h" namespace Common { // 内存池模板类,T为存储对象的类型 template<typename T> class MemPool final { public: // 显式构造函数,预分配num_elems个对象的空间 explicit MemPool(std::size_t num_elems) : store_(num_elems, {T(), true}) /* 预分配vector存储空间,每个元素初始化为默认对象且标记为空闲 */ { // 断言:ObjectBlock的第一个成员必须是T对象 ASSERT(reinterpret_cast<const ObjectBlock *>(&(store_[0].object_)) == &(store_[0]), "T object should be first member of ObjectBlock."); } // 分配一个对象,使用可变参数构造T对象,返回T类型指针 template<typename... Args> T *allocate(Args... args) noexcept { auto obj_block = &(store_[next_free_index_]); // 断言:当前索引处的块必须为空闲 ASSERT(obj_block->is_free_, "Expected free ObjectBlock at index:" + std::to_string(next_free_index_)); T *ret = &(obj_block->object_); // 使用定位new在预分配内存上构造对象 ret = new(ret) T(args...); obj_block->is_free_ = false; // 标记为已分配 updateNextFreeIndex(); // 更新下一个空闲索引 return ret; } // 释放对象,将其标记为空闲 auto deallocate(const T *elem) noexcept { // 计算elem在store_中的索引 const auto elem_index = (reinterpret_cast<const ObjectBlock *>(elem) - &store_[0]); // 断言:元素必须属于本内存池 ASSERT(elem_index >= 0 && static_cast<size_t>(elem_index) < store_.size(), "Element being deallocated does not belong to this Memory pool."); // 断言:当前块必须是已分配状态 ASSERT(!store_[elem_index].is_free_, "Expected in-use ObjectBlock at index:" + std::to_string(elem_index)); store_[elem_index].is_free_ = true; // 标记为空闲 } // 禁用默认构造、拷贝构造、移动构造和赋值操作 MemPool() = delete; MemPool(const MemPool &) = delete; MemPool(const MemPool &&) = delete; MemPool &operator=(const MemPool &) = delete; MemPool &operator=(const MemPool &&) = delete; private: // 更新下一个空闲块的索引 auto updateNextFreeIndex() noexcept { const auto initial_free_index = next_free_index_; // 循环查找下一个空闲块 while (!store_[next_free_index_].is_free_) { ++next_free_index_; // 如果到达末尾则回到开头 if (UNLIKELY(next_free_index_ == store_.size())) { next_free_index_ = 0; } // 如果回到了起始索引,说明池已满 if (UNLIKELY(initial_free_index == next_free_index_)) { ASSERT(initial_free_index != next_free_index_, "Memory Pool out of space."); } } } // 内部结构体,包含一个对象和空闲标记 struct ObjectBlock { T object_; // 存储的对象 bool is_free_ = true; // 空闲标记,true表示可用 }; // 存储所有对象块的vector std::vector<ObjectBlock> store_; // 指向下一个空闲块的索引 size_t next_free_index_ = 0; }; }
macro.h头文件
#pragma once #include <cstring> #include <iostream> #define LIKELY(x) __builtin_expect(!!(x), 1) #define UNLIKELY(x) __builtin_expect(!!(x), 0) inline auto ASSERT(bool cond, const std::string &msg) noexcept { if (UNLIKELY(!cond)) { std::cerr << "ASSERT : " << msg << std::endl; exit(EXIT_FAILURE); } } inline auto FATAL(const std::string &msg) noexcept { std::cerr << "FATAL : " << msg << std::endl; exit(EXIT_FAILURE); }
使用例子:
#include "mem_pool.h" struct MyStruct { int d_[3]; }; int main(int, char **) { using namespace Common; MemPool<double> prim_pool(50); MemPool<MyStruct> struct_pool(50); for(auto i = 0; i < 60; ++i) { auto p_ret = prim_pool.allocate(i); auto s_ret = struct_pool.allocate(MyStruct{i, i+1, i+2}); std::cout << "prim elem:" << *p_ret << " allocated at:" << p_ret << std::endl; std::cout << "struct elem:" << s_ret->d_[0] << "," << s_ret->d_[1] << "," << s_ret->d_[2] << " allocated at:" << s_ret << std::endl; if(i % 5 == 0) { std::cout << "deallocating prim elem:" << *p_ret << " from:" << p_ret << std::endl; std::cout << "deallocating struct elem:" << s_ret->d_[0] << "," << s_ret->d_[1] << "," << s_ret->d_[2] << " from:" << s_ret << std::endl; prim_pool.deallocate(p_ret); struct_pool.deallocate(s_ret); } } return 0; }
系统当前共有 426 篇文章