diff --git a/include/arena.h b/include/arena.h index 7b41151..97d908a 100644 --- a/include/arena.h +++ b/include/arena.h @@ -6,12 +6,14 @@ typedef struct arena { void *begin, - *next; + *next, + *prev; size_t cap; } __attribute__((aligned(sizeof(void*)))) arena_t; arena_t* arena_new(); void arena_reset(arena_t* a); void* arena_alloc(arena_t* a, size_t len); +void* arena_realloc_tail(arena_t* a, size_t len); #endif diff --git a/src/arena.c b/src/arena.c index 375e185..6a11669 100644 --- a/src/arena.c +++ b/src/arena.c @@ -23,13 +23,13 @@ struct arena* arena_new() arena_t* a = (arena_t*)p; - *a = (arena_t) { - .begin = p + sizeof(struct arena), - .next = p + sizeof(struct arena), - .cap = size - sizeof(struct arena) - }; + void* beg = p + sizeof(struct arena); + a->begin = beg; + a->next = beg; + a->prev = beg; + a->cap = size - sizeof(struct arena); - return (arena_t*)a; + return a; } /* @@ -38,6 +38,7 @@ struct arena* arena_new() void arena_reset(struct arena* a) { a->next = a->begin; + a->prev = a->begin; } /* @@ -46,12 +47,31 @@ void arena_reset(struct arena* a) void* arena_alloc(struct arena* a, size_t len) { void* p = a->next; - a->next = (byte*)(a->next) + len; - if ((byte*)(a->next) > (byte*)(a->begin) + a->cap) { + if ((byte*)p + len > (byte*)(a->begin) + a->cap) { errno = ENOMEM; return NULL; } + a->next = (byte*)(a->next) + len; + a->prev = p; + return p; } + +/* + * Reallocate last block in arena + */ +void* arena_realloc_tail(struct arena* a, size_t len) +{ + void* p = a->prev; + + if ((byte*)p + len > (byte*)(a->begin) + a->cap) { + errno = ENOMEM; + return NULL; + } + + a->next = (byte*)p + len; + + return a->prev; +}