动态内存池代码
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;
}
系统当前共有 481 篇文章