1 #ifndef HALIDE_RUNTIME_MEMORY_ARENA_H
2 #define HALIDE_RUNTIME_MEMORY_ARENA_H
4 #include "../HalideRuntime.h"
48 void reclaim(
void *user_context,
void *ptr);
49 bool collect(
void *user_context);
50 void destroy(
void *user_context);
69 void *entries =
nullptr;
76 Block *create_block(
void *user_context);
77 bool collect_block(
void *user_context, Block *block);
78 void destroy_block(
void *user_context, Block *block);
79 Block *lookup_block(
void *user_context,
uint32_t index);
81 void *create_entry(
void *user_context, Block *block,
uint32_t index);
82 void destroy_entry(
void *user_context, Block *block,
uint32_t index);
83 void *lookup_entry(
void *user_context, Block *block,
uint32_t index);
93 blocks(user_context, {
sizeof(MemoryArena::Block), 32, 32}, alloc) {
106 if (result ==
nullptr) {
107 halide_error(user_context,
"MemoryArena: Failed to create instance! Out of memory!\n");
111 result->
initialize(user_context, cfg, system_allocator);
118 instance->
destroy(user_context);
120 system_allocator.
deallocate(user_context, instance);
127 blocks.
initialize(user_context, {
sizeof(MemoryArena::Block), 32, 32}, system_allocator);
132 if (!blocks.
empty()) {
133 for (
size_t i = blocks.
size(); i--;) {
134 Block *block = lookup_block(user_context, i);
136 destroy_block(user_context, block);
144 for (
size_t i = blocks.
size(); i--;) {
145 Block *block = lookup_block(user_context, i);
147 if (collect_block(user_context, block)) {
148 blocks.
remove(user_context, i);
157 for (
size_t i = blocks.
size(); i--;) {
158 Block *block = lookup_block(user_context, i);
160 if (block->free_index != invalid_entry) {
161 return create_entry(user_context, block, block->free_index);
166 halide_error(user_context,
"MemoryArena: Failed to reserve new entry! Maxmimum blocks reached!\n");
172 Block *block = create_block(user_context);
173 void *entry_ptr = create_entry(user_context, block, index);
183 for (
size_t i = blocks.
size(); i--;) {
184 Block *block = lookup_block(user_context, i);
191 if ((entry_ptr >= base_ptr) && (entry_ptr < end_ptr)) {
194 destroy_entry(user_context, block, index);
198 halide_error(user_context,
"MemoryArena: Pointer address doesn't belong to this memory pool!\n");
201 typename MemoryArena::Block *MemoryArena::create_block(
void *user_context) {
204 if (!blocks.
empty()) {
205 const Block *last_block =
static_cast<Block *
>(blocks.
back());
206 new_capacity = (last_block->capacity * 3 / 2);
216 for (
uint32_t i = 0; i < new_capacity - 1; ++i) {
217 new_indices[i] = i + 1;
221 new_indices[new_capacity - 1] = invalid_entry;
224 const Block new_block = {new_entries, new_indices, new_status, new_capacity, 0};
225 blocks.
append(user_context, &new_block);
226 return static_cast<Block *
>(blocks.
back());
229 void MemoryArena::destroy_block(
void *user_context, Block *block) {
231 if (block->entries !=
nullptr) {
236 block->entries =
nullptr;
237 block->indices =
nullptr;
238 block->status =
nullptr;
242 bool MemoryArena::collect_block(
void *user_context, Block *block) {
244 if (block->entries !=
nullptr) {
245 bool can_collect =
true;
246 for (
size_t i = block->capacity; i--;) {
253 destroy_block(user_context, block);
260 MemoryArena::Block *MemoryArena::lookup_block(
void *user_context,
uint32_t index) {
261 return static_cast<Block *
>(blocks[index]);
264 void *MemoryArena::lookup_entry(
void *user_context, Block *block,
uint32_t index) {
270 void *MemoryArena::create_entry(
void *user_context, Block *block,
uint32_t index) {
271 void *entry_ptr = lookup_entry(user_context, block, index);
272 block->free_index = block->indices[index];
274 #if DEBUG_RUNTIME_INTERNAL
280 void MemoryArena::destroy_entry(
void *user_context, Block *block,
uint32_t index) {
282 block->indices[index] = block->free_index;
283 block->free_index = index;
286 const typename MemoryArena::Config &
313 #endif // HALIDE_RUNTIME_MEMORY_ARENA_H