-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmemory_pool.cpp
More file actions
134 lines (116 loc) · 3.89 KB
/
memory_pool.cpp
File metadata and controls
134 lines (116 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//
// Created by wnc on 2025/9/15.
//
#include "memory_pool.h"
#include <cstdlib>
#include <iostream>
// 对齐到4字节
static inline size_t align4(size_t size) {
return (size + 3) & ~static_cast<size_t>(3);
}
MemoryPool::MemoryPool(size_t block_size, size_t block_count)
: block_size_(align4(block_size)), block_count_(block_count) {
expandPool(block_count_);
}
MemoryPool::~MemoryPool() {
for (auto &p : big_blocks_) {
std::free(p.first);
}
}
// 实现移动构造函数
MemoryPool::MemoryPool(MemoryPool&& other) noexcept {
std::lock_guard<std::mutex> lock(other.mtx_);
block_size_ = other.block_size_;
block_count_ = other.block_count_;
capacity_ = other.capacity_;
free_list_ = std::move(other.free_list_);
big_blocks_ = std::move(other.big_blocks_);
allocations_ = std::move(other.allocations_);
// 注意 mutex 不能移动,只是每个对象自己管理
// 置空被移动对象的容器,保证析构安全
other.free_list_.clear();
other.big_blocks_.clear();
other.allocations_.clear();
}
// 实现移动赋值运算符
MemoryPool& MemoryPool::operator=(MemoryPool&& other) noexcept {
if (this != &other) {
std::lock_guard<std::mutex> lock1(mtx_);
std::lock_guard<std::mutex> lock2(other.mtx_);
block_size_ = other.block_size_;
block_count_ = other.block_count_;
capacity_ = other.capacity_;
free_list_ = std::move(other.free_list_);
big_blocks_ = std::move(other.big_blocks_);
allocations_ = std::move(other.allocations_);
// 置空被移动对象的容器,保证析构安全
other.free_list_.clear();
other.big_blocks_.clear();
other.allocations_.clear();
}
return *this;
}
void MemoryPool::expandPool(size_t count) {
void* bigBlock = std::malloc(block_size_ * count);
if (!bigBlock) throw std::bad_alloc();
// 记录每次大块的起始地址与总字节数
big_blocks_.push_back({bigBlock, block_size_ * count});
char* ptr = static_cast<char*>(bigBlock);
for (size_t i = 0; i < count; ++i) {
free_list_.push_back(ptr + i * block_size_);
}
capacity_ += count;
}
void* MemoryPool::allocate(const char* file, int line, const char* func) {
std::lock_guard<std::mutex> lock(mtx_);
if (free_list_.empty()) {
expandPool(block_count_);
}
void* ptr = free_list_.back();
free_list_.pop_back();
AllocationInfo info;
info.file = file;
info.line = line;
info.func = func;
info.tid = std::this_thread::get_id();
info.in_use = true;
allocations_[ptr] = info;
return ptr;
}
void MemoryPool::deallocate(void* ptr) {
std::lock_guard<std::mutex> lock(mtx_);
auto it = allocations_.find(ptr);
if (it == allocations_.end()) {
std::cerr << "错误:释放未记录指针 " << ptr << std::endl;
return;
}
if (!it->second.in_use) {
std::cerr << "错误:重复释放指针 " << ptr << std::endl;
return;
}
it->second.in_use = false;
free_list_.push_back(ptr);
}
void MemoryPool::reportLeaks() const {
std::lock_guard<std::mutex> lock(mtx_);
for (auto& it : allocations_) {
if (it.second.in_use) {
std::cerr << "内存泄漏指针 " << it.first
<< " 分配于 " << it.second.file << ":" << it.second.line
<< " 函数 " << it.second.func
<< " 线程 " << it.second.tid
<< " 大小 " << block_size_ << " 字节" << std::endl;
}
}
}
bool MemoryPool::owns(void* ptr) const {
if (!ptr) return false;
std::lock_guard<std::mutex> lock(mtx_);
char* cptr = static_cast<char*>(ptr);
for (const auto &p : big_blocks_) {
char* base = static_cast<char*>(p.first);
size_t sz = p.second;
if (cptr >= base && cptr < base + sz) return true;
}
return false;
}