yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
memory_pool.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cstdlib>
5#include <cstring>
6
7namespace yaze {
8namespace gfx {
9
11
13 static MemoryPool instance;
14 return instance;
15}
16
18 : total_allocations_(0),
19 total_deallocations_(0),
20 total_used_bytes_(0),
21 total_allocated_bytes_(0) {
22 // Initialize block pools with common graphics sizes
24 100); // 100KB for small tiles
26 50); // 200KB for medium tiles
28 20); // 320KB for large tiles
30 10); // 640KB for graphics sheets
31
33 (20 * kLargeBlockSize) + (10 * kHugeBlockSize);
34}
35
37 Clear();
38 // Clear() only resets block usage flags; the backing storage for each pool
39 // is owned here and must be released to avoid leaking the pre-allocated
40 // blocks (flagged by AddressSanitizer/LeakSanitizer at process exit).
41 for (auto* pool :
43 for (auto& block : *pool) {
44 std::free(block.data);
45 block.data = nullptr;
46 }
47 pool->clear();
48 }
49}
50
51void* MemoryPool::Allocate(size_t size) {
53
54 MemoryBlock* block = FindFreeBlock(size);
55 if (!block) {
56 // Fallback to system malloc if no pool block available
57 void* data = std::malloc(size);
58 if (data) {
59 total_used_bytes_ += size;
60 allocated_blocks_[data] = nullptr; // Mark as system allocated
61 }
62 return data;
63 }
64
65 block->in_use = true;
66 total_used_bytes_ += block->size;
67 allocated_blocks_[block->data] = block;
68
69 return block->data;
70}
71
72void MemoryPool::Deallocate(void* ptr) {
73 if (!ptr)
74 return;
75
77
78 auto it = allocated_blocks_.find(ptr);
79 if (it == allocated_blocks_.end()) {
80 // System allocated, use free
81 std::free(ptr);
82 return;
83 }
84
85 MemoryBlock* block = it->second;
86 if (block) {
87 block->in_use = false;
88 total_used_bytes_ -= block->size;
89 } else {
90 // System-allocated fallback (see Allocate): the map only tracked the
91 // pointer, so the backing storage must be released here to avoid leaking
92 // every overflow allocation.
93 std::free(ptr);
94 }
95
96 allocated_blocks_.erase(it);
97}
98
99void* MemoryPool::AllocateAligned(size_t size, size_t alignment) {
100 // For simplicity, allocate extra space and align manually
101 // In a production system, you'd want more sophisticated alignment handling
102 size_t aligned_size = size + alignment - 1;
103 void* ptr = Allocate(aligned_size);
104
105 if (ptr) {
106 uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
107 uintptr_t aligned_addr = (addr + alignment - 1) & ~(alignment - 1);
108 return reinterpret_cast<void*>(aligned_addr);
109 }
110
111 return nullptr;
112}
113
114std::pair<size_t, size_t> MemoryPool::GetMemoryStats() const {
116}
117
118std::pair<size_t, size_t> MemoryPool::GetAllocationStats() const {
120}
121
123 // Reset all blocks to unused state
124 for (auto& block : small_blocks_) {
125 block.in_use = false;
126 }
127 for (auto& block : medium_blocks_) {
128 block.in_use = false;
129 }
130 for (auto& block : large_blocks_) {
131 block.in_use = false;
132 }
133 for (auto& block : huge_blocks_) {
134 block.in_use = false;
135 }
136
137 allocated_blocks_.clear();
139}
140
142 // Determine which pool to use based on size
143 size_t pool_index = GetPoolIndex(size);
144
145 std::vector<MemoryBlock>* pools[] = {&small_blocks_, &medium_blocks_,
147
148 if (pool_index >= 4) {
149 return nullptr; // Size too large for any pool
150 }
151
152 auto& pool = *pools[pool_index];
153
154 // Find first unused block
155 auto it =
156 std::find_if(pool.begin(), pool.end(),
157 [](const MemoryBlock& block) { return !block.in_use; });
158
159 return (it != pool.end()) ? &(*it) : nullptr;
160}
161
162void MemoryPool::InitializeBlockPool(std::vector<MemoryBlock>& pool,
163 size_t block_size, size_t count) {
164 pool.reserve(count);
165
166 for (size_t i = 0; i < count; ++i) {
167 void* data = std::malloc(block_size);
168 if (data) {
169 pool.emplace_back(data, block_size);
170 }
171 }
172}
173
174size_t MemoryPool::GetPoolIndex(size_t size) const {
175 if (size <= kSmallBlockSize)
176 return 0;
177 if (size <= kMediumBlockSize)
178 return 1;
179 if (size <= kLargeBlockSize)
180 return 2;
181 if (size <= kHugeBlockSize)
182 return 3;
183 return 4; // Too large for any pool
184}
185
186} // namespace gfx
187} // namespace yaze
High-performance memory pool allocator for graphics data.
Definition memory_pool.h:38
static constexpr size_t kSmallBlockSize
Definition memory_pool.h:95
void Deallocate(void *ptr)
Deallocate memory block.
size_t GetPoolIndex(size_t size) const
static constexpr size_t kHugeBlockSize
void * Allocate(size_t size)
Allocate memory block of specified size.
void * AllocateAligned(size_t size, size_t alignment)
Allocate memory block aligned to specified boundary.
static constexpr size_t kLargeBlockSize
Definition memory_pool.h:98
std::vector< MemoryBlock > medium_blocks_
static constexpr size_t kMediumBlockSize
Definition memory_pool.h:96
std::unordered_map< void *, MemoryBlock * > allocated_blocks_
std::vector< MemoryBlock > huge_blocks_
std::vector< MemoryBlock > small_blocks_
MemoryBlock * FindFreeBlock(size_t size)
void Clear()
Clear all allocated blocks (for cleanup)
std::pair< size_t, size_t > GetAllocationStats() const
Get allocation statistics.
std::pair< size_t, size_t > GetMemoryStats() const
Get memory usage statistics.
static MemoryPool & Get()
void InitializeBlockPool(std::vector< MemoryBlock > &pool, size_t block_size, size_t count)
std::vector< MemoryBlock > large_blocks_