开始设计
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
#include <c_Arena.h>
|
||||
#include <assert.h>
|
||||
#include <c_Alignment.h>
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
C_STATIC_FORCE_INLINE
|
||||
c_bool_t is_power_of_two(c_size_t x) {
|
||||
return (x & (x-1)) == 0;
|
||||
}
|
||||
|
||||
C_STATIC_FORCE_INLINE
|
||||
c_uintptr_t align_forward(c_uintptr_t ptr, c_size_t align) {
|
||||
c_uintptr_t p;
|
||||
c_uintptr_t a;
|
||||
c_uintptr_t modulo;
|
||||
|
||||
assert(is_power_of_two(align));
|
||||
|
||||
p = ptr;
|
||||
a = (uintptr_t)align;
|
||||
// Same as (p % a) but faster as 'a' is a power of two
|
||||
modulo = p & (a-1);
|
||||
|
||||
if (modulo != 0) {
|
||||
// If 'p' address is not aligned, push the address to the
|
||||
// next value which is aligned
|
||||
p += a - modulo;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
C_STATIC_FORCE_INLINE
|
||||
void *arena_alloc_align(c_Arena_t *a, c_size_t size, c_size_t align) {
|
||||
// Align 'curr_offset' forward to the specified alignment
|
||||
c_uintptr_t curr_ptr = (c_uintptr_t)a->buf + (c_uintptr_t)a->curr_offset;
|
||||
c_uintptr_t offset = align_forward(curr_ptr, align);
|
||||
offset -= (c_uintptr_t)a->buf; // Change to relative offset
|
||||
|
||||
// Check to see if the backing memory has space left
|
||||
if (offset+size <= a->buf_len) {
|
||||
void *ptr = &a->buf[offset];
|
||||
a->prev_offset = offset;
|
||||
a->curr_offset = offset+size;
|
||||
|
||||
// Zero new memory by default
|
||||
memset(ptr, 0, size);
|
||||
return ptr;
|
||||
}
|
||||
// Return NULL if the arena is out of memory (or handle differently)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
C_STATIC_FORCE_INLINE
|
||||
void *arena_resize_align(c_Arena_t *a, void *old_memory, c_size_t old_size, c_size_t new_size, c_size_t align) {
|
||||
uint8_t* old_mem = (uint8_t*)old_memory;
|
||||
|
||||
assert(is_power_of_two(align));
|
||||
|
||||
if (old_mem == NULL || old_size == 0) {
|
||||
return arena_alloc_align(a, new_size, align);
|
||||
} else if (a->buf <= old_mem && old_mem < (a->buf+ a->buf_len)) {
|
||||
if (a->buf+a->prev_offset == old_mem) {
|
||||
a->curr_offset = a->prev_offset + new_size;
|
||||
if (new_size > old_size) {
|
||||
// Zero the new memory by default
|
||||
memset(&a->buf[a->curr_offset], 0, new_size-old_size);
|
||||
}
|
||||
return old_memory;
|
||||
} else {
|
||||
void *new_memory = arena_alloc_align(a, new_size, align);
|
||||
c_size_t copy_size = old_size < new_size ? old_size : new_size;
|
||||
// Copy across old memory to the new memory
|
||||
memmove(new_memory, old_memory, copy_size);
|
||||
return new_memory;
|
||||
}
|
||||
|
||||
} else {
|
||||
assert(0 && "Memory is out of bounds of the buffer in this arena");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
void c_Arena_Init(c_Arena_t* a, void* buf, c_size_t buf_len) {
|
||||
a->buf = buf;
|
||||
a->buf_len = buf_len;
|
||||
a->prev_offset = 0;
|
||||
a->curr_offset = 0;
|
||||
}
|
||||
|
||||
void *c_Arena_Alloc(c_Arena_t *a, c_size_t size) {
|
||||
return arena_alloc_align(a, size, C_ALIGN_SIZE);
|
||||
}
|
||||
|
||||
void *c_Arena_Resize(c_Arena_t *a, void *old_memory, c_size_t old_size, c_size_t new_size) {
|
||||
return arena_resize_align(a, old_memory, old_size, new_size, C_ALIGN_SIZE);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user