forked from Zylann/godot_voxel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvoxel_memory_pool.cpp
105 lines (93 loc) · 2.47 KB
/
voxel_memory_pool.cpp
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
#include "voxel_memory_pool.h"
#include "core/print_string.h"
#include "core/variant.h"
namespace {
VoxelMemoryPool *g_memory_pool = nullptr;
} // namespace
void VoxelMemoryPool::create_singleton() {
CRASH_COND(g_memory_pool != nullptr);
g_memory_pool = memnew(VoxelMemoryPool);
}
void VoxelMemoryPool::destroy_singleton() {
CRASH_COND(g_memory_pool == nullptr);
VoxelMemoryPool *pool = g_memory_pool;
g_memory_pool = nullptr;
memdelete(pool);
}
VoxelMemoryPool *VoxelMemoryPool::get_singleton() {
CRASH_COND(g_memory_pool == nullptr);
return g_memory_pool;
}
VoxelMemoryPool::VoxelMemoryPool() {
_mutex = Mutex::create();
}
VoxelMemoryPool::~VoxelMemoryPool() {
#ifdef TOOLS_ENABLED
debug_print();
#endif
clear();
memdelete(_mutex);
}
uint8_t *VoxelMemoryPool::allocate(uint32_t size) {
MutexLock lock(_mutex);
Pool *pool = get_or_create_pool(size);
uint8_t *block;
if (pool->blocks.size() > 0) {
block = pool->blocks.back();
pool->blocks.pop_back();
} else {
block = (uint8_t *)memalloc(size * sizeof(uint8_t));
}
++_used_blocks;
return block;
}
void VoxelMemoryPool::recycle(uint8_t *block, uint32_t size) {
MutexLock lock(_mutex);
Pool *pool = _pools[size]; // If not found, entry will be created! It would be an error
// Check recycling before having allocated
CRASH_COND(pool == nullptr);
pool->blocks.push_back(block);
--_used_blocks;
}
void VoxelMemoryPool::clear() {
MutexLock lock(_mutex);
const uint32_t *key = nullptr;
while ((key = _pools.next(key))) {
Pool *pool = _pools.get(*key);
CRASH_COND(pool == nullptr);
for (auto it = pool->blocks.begin(); it != pool->blocks.end(); ++it) {
uint8_t *ptr = *it;
CRASH_COND(ptr == nullptr);
memfree(ptr);
}
}
_pools.clear();
}
void VoxelMemoryPool::debug_print() {
MutexLock lock(_mutex);
print_line("-------- VoxelMemoryPool ----------");
const uint32_t *key = nullptr;
int i = 0;
while ((key = _pools.next(key))) {
Pool *pool = _pools.get(*key);
print_line(String("Pool {0} for size {1}: {2} blocks").format(varray(i, *key, static_cast<int>(pool->blocks.size()))));
++i;
}
}
unsigned int VoxelMemoryPool::debug_get_used_blocks() const {
MutexLock lock(_mutex);
return _used_blocks;
}
VoxelMemoryPool::Pool *VoxelMemoryPool::get_or_create_pool(uint32_t size) {
Pool *pool;
Pool **ppool = _pools.getptr(size);
if (ppool == nullptr) {
pool = memnew(Pool);
CRASH_COND(pool == nullptr);
_pools.set(size, pool);
} else {
pool = *ppool;
CRASH_COND(pool == nullptr);
}
return pool;
}