-
Notifications
You must be signed in to change notification settings - Fork 1
/
BlockAllocator.h
120 lines (95 loc) · 2.31 KB
/
BlockAllocator.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
119
120
#ifndef BlockAllocator_H
#define BlockAllocator_H
#include<vector>
#include<map>
#include<iostream>
class BlockAllocator {
public:
BlockAllocator( std::size_t typeSize,
std::size_t blockSize):
m_typeSize(typeSize), m_blockSize(blockSize){
init();
}
void * alloc() {
void * ret = m_next;
m_next+=m_typeSize;
Block & block = *m_current;
++block.m_allocated;
if(m_next==(&block.m_data.back())+1)
init();
return ret;
}
void dealloc(void * p) {
pointer cp = static_cast<pointer>(p);
// check if was last allocated
if (cp==m_next-m_typeSize) {
m_next=cp;
--(*m_current).m_allocated;
return;
}
// check if in current
Block & block = *m_current;
if (cp>= &block.m_data.front() && cp<m_next)
--block.m_allocated;
else { // check the other blocks
Blocks::iterator b = m_blocks.lower_bound(cp);
if (cp!=(*b).first) b--;
if ((--((*b).second->m_allocated))==0) {
delete (*b).second;
m_blocks.erase(b);
}
}
}
public:
struct Stat {
size_t blockSize;
size_t currentOccupancy;
size_t currentAvailable;
size_t nBlocks;
};
Stat stat() const {
Stat s = { m_blockSize, (*m_current).m_allocated,
(&*(*m_current).m_data.end()-m_next)/m_typeSize,
m_blocks.size()};
return s;
}
private:
void init() {
m_current = new Block();
m_current->m_data.resize(m_blockSize*m_typeSize);
m_current->m_allocated=0;
m_next = &(m_current->m_data.front());
m_blocks[m_next] = m_current;
}
struct Block {
std::size_t m_allocated;
std::vector<unsigned char> m_data;
};
typedef unsigned char * pointer;
typedef std::map<pointer,Block*> Blocks;
std::size_t m_typeSize;
std::size_t m_blockSize;
pointer m_next;
Block * m_current;
Blocks m_blocks;
};
template<typename T, size_t N>
class BlockAllocated {
public:
static void * operator new(size_t) {
return allocator()->alloc();
}
static void operator delete(void * p) {
allocator()->dealloc(p);
}
static BlockAllocator * allocator() {
static BlockAllocator local(sizeof(T), N);
return &local;
}
static BlockAllocator::Stat stat() {
return allocator()->stat();
}
private:
// static BlockAllocator * s_allocator;
};
#endif // BlockAllocator_H