line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#pragma once |
2
|
|
|
|
|
|
|
#include |
3
|
|
|
|
|
|
|
#include |
4
|
|
|
|
|
|
|
#include |
5
|
|
|
|
|
|
|
#include |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
namespace panda { |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
namespace detail { |
10
|
|
|
|
|
|
|
void* __get_global_ptr (const std::type_info& ti, const char* name, void* val); |
11
|
|
|
|
|
|
|
void* __get_global_tls_ptr (const std::type_info& ti, const char* name, void* val); |
12
|
|
|
|
|
|
|
} |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
template |
15
|
10
|
|
|
|
|
|
inline T* get_global_ptr (T* val, const char* name = NULL) { |
16
|
10
|
|
|
|
|
|
return reinterpret_cast(detail::__get_global_ptr(typeid(CLASS), name, reinterpret_cast(val))); |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
template |
20
|
|
|
|
|
|
|
inline T* get_global_tls_ptr (T* val, const char* name = NULL) { |
21
|
|
|
|
|
|
|
return reinterpret_cast(detail::__get_global_tls_ptr(typeid(CLASS), name, reinterpret_cast(val))); |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
#define PANDA_GLOBAL_MEMBER_PTR(CLASS, TYPE, accessor, defval) \ |
25
|
|
|
|
|
|
|
static TYPE accessor () { \ |
26
|
|
|
|
|
|
|
static TYPE ptr; \ |
27
|
|
|
|
|
|
|
if (!ptr) ptr = panda::get_global_ptr(defval, #accessor); \ |
28
|
|
|
|
|
|
|
return ptr; \ |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
#define PANDA_GLOBAL_MEMBER(CLASS, TYPE, accessor, defval) \ |
32
|
|
|
|
|
|
|
static TYPE& accessor () { \ |
33
|
|
|
|
|
|
|
static TYPE* ptr; \ |
34
|
|
|
|
|
|
|
if (!ptr) { \ |
35
|
|
|
|
|
|
|
static TYPE val = defval; \ |
36
|
|
|
|
|
|
|
ptr = panda::get_global_ptr(&val, #accessor); \ |
37
|
|
|
|
|
|
|
} \ |
38
|
|
|
|
|
|
|
return *ptr; \ |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
#define PANDA_GLOBAL_MEMBER_AS_PTR(CLASS, TYPE, accessor, defval) \ |
42
|
|
|
|
|
|
|
static TYPE* accessor () { \ |
43
|
|
|
|
|
|
|
static TYPE* ptr; \ |
44
|
|
|
|
|
|
|
if (!ptr) { \ |
45
|
|
|
|
|
|
|
static TYPE val = defval; \ |
46
|
|
|
|
|
|
|
ptr = panda::get_global_ptr(&val, #accessor); \ |
47
|
|
|
|
|
|
|
} \ |
48
|
|
|
|
|
|
|
return ptr; \ |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
#define PANDA_TLS_MEMBER_PTR(CLASS, TYPE, accessor, defval) \ |
52
|
|
|
|
|
|
|
static TYPE accessor () { \ |
53
|
|
|
|
|
|
|
static thread_local TYPE _ptr; \ |
54
|
|
|
|
|
|
|
TYPE ptr = _ptr; \ |
55
|
|
|
|
|
|
|
if (!ptr) ptr = _ptr = panda::get_global_tls_ptr(defval, #accessor); \ |
56
|
|
|
|
|
|
|
return ptr; \ |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
#define PANDA_TLS_MEMBER(CLASS, TYPE, accessor, defval) \ |
60
|
|
|
|
|
|
|
static TYPE& accessor () { \ |
61
|
|
|
|
|
|
|
static thread_local TYPE* _ptr; \ |
62
|
|
|
|
|
|
|
TYPE* ptr = _ptr; \ |
63
|
|
|
|
|
|
|
if (!ptr) { \ |
64
|
|
|
|
|
|
|
static thread_local TYPE val = defval; \ |
65
|
|
|
|
|
|
|
ptr = _ptr = panda::get_global_tls_ptr(&val, #accessor); \ |
66
|
|
|
|
|
|
|
} \ |
67
|
|
|
|
|
|
|
return *ptr; \ |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
#define PANDA_TLS_MEMBER_AS_PTR(CLASS, TYPE, accessor, defval) \ |
71
|
|
|
|
|
|
|
static TYPE* accessor () { \ |
72
|
|
|
|
|
|
|
static thread_local TYPE* _ptr; \ |
73
|
|
|
|
|
|
|
TYPE* ptr = _ptr; \ |
74
|
|
|
|
|
|
|
if (!ptr) { \ |
75
|
|
|
|
|
|
|
static thread_local TYPE val = defval; \ |
76
|
|
|
|
|
|
|
ptr = _ptr = panda::get_global_tls_ptr(&val, #accessor); \ |
77
|
|
|
|
|
|
|
} \ |
78
|
|
|
|
|
|
|
return ptr; \ |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
struct MemoryPool { |
82
|
|
|
|
|
|
|
MemoryPool (size_t blocksize) : first_free(NULL) { |
83
|
|
|
|
|
|
|
this->blocksize = round_up(blocksize); |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
void* allocate () { |
87
|
|
|
|
|
|
|
if (!first_free) grow(); |
88
|
|
|
|
|
|
|
void* ret = first_free; |
89
|
|
|
|
|
|
|
first_free = *((void**)ret); |
90
|
|
|
|
|
|
|
return ret; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
void deallocate (void* elem) { |
94
|
|
|
|
|
|
|
#ifdef TEST_FULL |
95
|
|
|
|
|
|
|
if(!is_mine(elem)) abort(); // protection for debugging, normally you MUST NEVER pass a pointer that wasn't created via current mempool |
96
|
|
|
|
|
|
|
#endif |
97
|
|
|
|
|
|
|
*((void**)elem) = first_free; |
98
|
|
|
|
|
|
|
first_free = elem; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
~MemoryPool (); |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
private: |
104
|
|
|
|
|
|
|
struct Pool { |
105
|
|
|
|
|
|
|
char* list; |
106
|
|
|
|
|
|
|
size_t size; |
107
|
|
|
|
|
|
|
size_t len; |
108
|
|
|
|
|
|
|
}; |
109
|
|
|
|
|
|
|
size_t blocksize; |
110
|
|
|
|
|
|
|
std::vector pools; |
111
|
|
|
|
|
|
|
void* first_free; |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
void grow (); |
114
|
|
|
|
|
|
|
bool is_mine (void* elem); |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
inline static size_t round_up (size_t size) { |
117
|
|
|
|
|
|
|
assert(size > 0); |
118
|
|
|
|
|
|
|
const size_t factor = sizeof(void*); |
119
|
|
|
|
|
|
|
if ((size & (factor-1)) == 0) return size; |
120
|
|
|
|
|
|
|
size += factor; |
121
|
|
|
|
|
|
|
size &= ~((size_t)(factor-1)); |
122
|
|
|
|
|
|
|
return size; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
}; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
template |
127
|
|
|
|
|
|
|
struct StaticMemoryPool { |
128
|
|
|
|
|
|
|
PANDA_GLOBAL_MEMBER_PTR(StaticMemoryPool, MemoryPool*, global_instance, new MemoryPool(BLOCKSIZE)); |
129
|
|
|
|
|
|
|
PANDA_TLS_MEMBER_PTR (StaticMemoryPool, MemoryPool*, instance, new MemoryPool(BLOCKSIZE)); |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
static void* allocate () { return instance()->allocate(); } |
132
|
|
|
|
|
|
|
static void deallocate (void* p) { instance()->deallocate(p); } |
133
|
|
|
|
|
|
|
}; |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<7> : StaticMemoryPool<8> {}; |
136
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<6> : StaticMemoryPool<8> {}; |
137
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<5> : StaticMemoryPool<8> {}; |
138
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<4> : StaticMemoryPool<8> {}; |
139
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<3> : StaticMemoryPool<8> {}; |
140
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<2> : StaticMemoryPool<8> {}; |
141
|
|
|
|
|
|
|
template <> struct StaticMemoryPool<1> : StaticMemoryPool<8> {}; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
struct DynamicMemoryPool { |
145
|
|
|
|
|
|
|
static DynamicMemoryPool* global_instance () { return _global_instance; } |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
PANDA_TLS_MEMBER_PTR(DynamicMemoryPool, DynamicMemoryPool*, instance, new DynamicMemoryPool()); |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
DynamicMemoryPool (); |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
void* allocate (size_t size) { |
152
|
|
|
|
|
|
|
if (size == 0) return NULL; |
153
|
|
|
|
|
|
|
MemoryPool* pool; |
154
|
|
|
|
|
|
|
if (size <= 1024) { |
155
|
|
|
|
|
|
|
pool = small_pools[(size-1)>>2]; |
156
|
|
|
|
|
|
|
if (!pool) pool = small_pools[(size-1)>>2] = new MemoryPool((((size-1)>>2) + 1)<<2); |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
else if (size <= 16384) { |
159
|
|
|
|
|
|
|
pool = medium_pools[(size-1)>>6]; |
160
|
|
|
|
|
|
|
if (!pool) pool = medium_pools[(size-1)>>6] = new MemoryPool((((size-1)>>6) + 1)<<6); |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
else if (size <= 262144) { |
163
|
|
|
|
|
|
|
pool = big_pools[(size-1)>>10]; |
164
|
|
|
|
|
|
|
if (!pool) pool = big_pools[(size-1)>>10] = new MemoryPool((((size-1)>>10) + 1)<<10); |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
else throw std::invalid_argument("ObjectAllocator: object size cannot exceed 256k"); |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
return pool->allocate(); |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
void deallocate (void* ptr, size_t size) { |
172
|
|
|
|
|
|
|
if (ptr == NULL || size == 0) return; |
173
|
|
|
|
|
|
|
MemoryPool* pool; |
174
|
|
|
|
|
|
|
if (size <= 1024) pool = small_pools[(size-1)>>2]; |
175
|
|
|
|
|
|
|
else if (size <= 16384) pool = medium_pools[(size-1)>>6]; |
176
|
|
|
|
|
|
|
else if (size <= 262144) pool = big_pools[(size-1)>>10]; |
177
|
|
|
|
|
|
|
else throw std::invalid_argument("ObjectAllocator: object size cannot exceed 256k"); |
178
|
|
|
|
|
|
|
pool->deallocate(ptr); |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
~DynamicMemoryPool (); |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
private: |
184
|
|
|
|
|
|
|
static constexpr const int POOLS_CNT = 256; |
185
|
|
|
|
|
|
|
static DynamicMemoryPool* _global_instance; |
186
|
|
|
|
|
|
|
MemoryPool* small_pools[POOLS_CNT]; |
187
|
|
|
|
|
|
|
MemoryPool* medium_pools[POOLS_CNT]; |
188
|
|
|
|
|
|
|
MemoryPool* big_pools[POOLS_CNT]; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
}; |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
template |
193
|
|
|
|
|
|
|
struct AllocatedObject { |
194
|
|
|
|
|
|
|
static void* operator new (size_t, void* p) { return p; } |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
static void* operator new (size_t size) { |
197
|
|
|
|
|
|
|
if (size == sizeof(TARGET)) return StaticMemoryPool::allocate(); |
198
|
|
|
|
|
|
|
else return DynamicMemoryPool::instance()->allocate(size); |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
static void operator delete (void* p, size_t size) { |
202
|
|
|
|
|
|
|
if (size == sizeof(TARGET)) StaticMemoryPool::deallocate(p); |
203
|
|
|
|
|
|
|
else DynamicMemoryPool::instance()->deallocate(p, size); |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
}; |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
template |
208
|
|
|
|
|
|
|
struct AllocatedObject { |
209
|
|
|
|
|
|
|
static void* operator new (size_t, void* p) { return p; } |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
static void* operator new (size_t size) { |
212
|
|
|
|
|
|
|
if (size == sizeof(TARGET)) return StaticMemoryPool::global_instance()->allocate(); |
213
|
|
|
|
|
|
|
else return DynamicMemoryPool::global_instance()->allocate(size); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
static void operator delete (void* p, size_t size) { |
217
|
|
|
|
|
|
|
if (size == sizeof(TARGET)) StaticMemoryPool::global_instance()->deallocate(p); |
218
|
|
|
|
|
|
|
else DynamicMemoryPool::global_instance()->deallocate(p, size); |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
}; |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
} |