AA_API void aa_mem_region_pop( aa_mem_region_t *reg, void *ptr ) { uint8_t *ptr8 = (uint8_t*)ptr; if( aa_mem_region_pop_in_node( ptr8, reg->node ) ){ // fast path, in the top node aa_mem_region_align( reg, ptr8 ); } else { // ugly case, iterate through nodes ptrdiff_t n = reg->node->end - reg->node->d; struct aa_mem_region_node *p = aa_mem_region_node_free( reg->node ); // free old nodes while( p && !aa_mem_region_pop_in_node(ptr8, p) ) { n += (p->end - p->d); p = aa_mem_region_node_free( p ); } assert( !p || (ptr8 >= p->d && ptr8 <= p->end)); // now realloc a replacement node // how much of the last chunk is now unused ptrdiff_t popsize = p ? (p->end - ptr8) : 0; assert( ( !p || ptr8 > p->d ) ? // popped in middle of chunk, keep it (!p || popsize < p->end - p->d ) : // poppsed start of chunk, realloc it ( (ptr8 == p->d) && (popsize == p->end - p->d) ) ); reg->node = aa_mem_region_node_alloc( (size_t)(n+popsize), (p && aa_mem_region_alignptr(p->d) == ptr8) ? aa_mem_region_node_free(p) : p ); reg->head = aa_mem_region_alignptr(reg->node->d); } }
void aa_mem_region_release( aa_mem_region_t *region ) { if( region->node->next ) { // compress buffers struct aa_mem_region_node *p = region->node; size_t n = 0; while (p) { n+= (size_t)(p->end - p->d); p = aa_mem_region_node_free(p); } region->node = aa_mem_region_node_alloc( n, NULL); } region->head = region->node->d; }
static void aa_mem_region_grow( aa_mem_region_t *reg, size_t size ) { size_t nsize = AA_MAX(2*(size_t)(reg->node->end - reg->node->d), size + AA_MEMREG_ALIGN); // this growth strategy creates worst-case O(n) memory waste reg->node = aa_mem_region_node_alloc( nsize, /* free unused chunk */ (aa_mem_region_alignptr(reg->node->d) == reg->head) ? aa_mem_region_node_free(reg->node) : reg->node ); aa_mem_region_align(reg, reg->node->d); assert( aa_mem_region_freesize(reg) >= size ); assert( ! ((uintptr_t)reg->head%16) ); }
void aa_mem_region_init( aa_mem_region_t *region, size_t size ) { region->node = aa_mem_region_node_alloc(size, NULL); aa_mem_region_align( region, region->node->d ); }
void aa_mem_region_init( aa_mem_region_t *region, size_t size ) { region->node = aa_mem_region_node_alloc(size, NULL); aa_mem_region_align( region, region->node->d ); region->reserved = 0; region->free_on_destroy = 0; }