forked from wgtdkp/wgtcc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mem_pool.h
118 lines (84 loc) · 2.01 KB
/
mem_pool.h
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
#ifndef _WGTCC_MEM_POOL_H_
#define _WGTCC_MEM_POOL_H_
#include <cstddef>
#include <vector>
class MemPool
{
public:
MemPool(): allocated_(0) {}
virtual ~MemPool() {}
MemPool(const MemPool& other) = delete;
MemPool& operator=(const MemPool& other) = delete;
virtual void* Alloc() = 0;
virtual void Free(void* addr) = 0;
virtual void Clear() = 0;
protected:
size_t allocated_;
};
template <class T>
class MemPoolImp: public MemPool
{
public:
MemPoolImp() : root_(nullptr) {}
virtual ~MemPoolImp() {}
MemPoolImp(const MemPool& other) = delete;
MemPoolImp& operator=(MemPool& other) = delete;
virtual void* Alloc();
virtual void Free(void* addr);
virtual void Clear();
private:
enum {
COUNT = (4 * 1024) / sizeof(T)
};
union Chunk {
Chunk* _next;
char _mem[sizeof(T)];
};
struct Block {
Block() {
for (size_t i = 0; i < COUNT - 1; i++)
chunks_[i]._next = &chunks_[i+1];
chunks_[COUNT-1]._next = nullptr;
}
Chunk chunks_[COUNT];
};
std::vector<Block*> blocks_;
Chunk* root_;
};
template <class T>
void* MemPoolImp<T>::Alloc()
{
if (nullptr == root_) { //空间不够,需要分配空间
auto block = new Block();
root_ = block->chunks_;
//如果blocks实现为std::list, 那么push_back实际的overhead更大
//这也表明,即使我们不需要随机访问功能(那么std::vector的拷贝是一种overhead),
//仍然倾向于使用std::vector,
//当然std::vector的指数级capacity增长会造成内存浪费。
blocks_.push_back(block);
}
auto ret = root_;
root_ = root_->_next;
++allocated_;
return ret;
}
template <class T>
void MemPoolImp<T>::Free(void* addr)
{
if (nullptr == addr)
return;
auto chunk = static_cast<Chunk*>(addr);
chunk->_next = root_;
root_ = chunk;
--allocated_;
}
template <class T>
void MemPoolImp<T>::Clear()
{
for (auto block: blocks_)
delete block;
blocks_.resize(0);
root_ = nullptr;
allocated_ = 0;
}
#endif