Reimplement the arena
This commit is contained in:
@ -9,13 +9,13 @@ typedef struct {
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
Arena *arena = arena_make(sizeof(int));
|
Arena arena = gebs_arena_get(4*1024);
|
||||||
defer { arena_destroy(arena); }
|
defer { arena_destroy(&arena); }
|
||||||
|
|
||||||
Ints ints = {0};
|
Ints ints = {0};
|
||||||
defer { list_free_alloc(arena, &ints); }
|
for (size_t i = 0; i < 100; i++) {
|
||||||
for (size_t i = 0; i < 1000; i++) {
|
list_append_alloc(&arena, &ints, i);
|
||||||
list_append_alloc(arena, &ints, i);
|
gebs_arena_reset(&arena);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < ints.count; i++) {
|
for (size_t i = 0; i < ints.count; i++) {
|
||||||
printf("%zu\n", i);
|
printf("%zu\n", i);
|
||||||
|
137
gebs.h
137
gebs.h
@ -33,6 +33,7 @@
|
|||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <sys/wait.h>
|
# include <sys/wait.h>
|
||||||
|
# include <sys/mman.h>
|
||||||
#else
|
#else
|
||||||
# error "Unknown GEBS_PLATFORM"
|
# error "Unknown GEBS_PLATFORM"
|
||||||
#endif
|
#endif
|
||||||
@ -96,31 +97,32 @@ void gebs_default_allocator_free(void *self, void *memory);
|
|||||||
void *gebs_default_allocator_realloc(void *self, void *memory,
|
void *gebs_default_allocator_realloc(void *self, void *memory,
|
||||||
size_t prev_size, size_t new_size);
|
size_t prev_size, size_t new_size);
|
||||||
|
|
||||||
typedef struct Gebs_Arena_Allocation {
|
|
||||||
size_t index;
|
|
||||||
size_t size;
|
|
||||||
char *ptr;
|
|
||||||
struct Gebs_Arena_Allocation *next;
|
|
||||||
} Gebs_Arena_Allocation;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *(*malloc)(void *self, size_t size);
|
void *(*malloc)(void *self, size_t size);
|
||||||
void (*free)(void *self, void *memory);
|
void (*free)(void *self, void *memory);
|
||||||
void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size);
|
void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size);
|
||||||
|
|
||||||
char *region;
|
void *buffer;
|
||||||
size_t index;
|
void *end;
|
||||||
size_t size;
|
size_t capacity;
|
||||||
} Gebs_Arena;
|
} Gebs_Arena;
|
||||||
|
|
||||||
void gebs_arena_reset(Gebs_Arena *a);
|
void gebs_arena_reset(Gebs_Arena *a);
|
||||||
void gebs_arena_destroy(Gebs_Arena *a);
|
void gebs_arena_destroy(Gebs_Arena *a);
|
||||||
Gebs_Arena *gebs_arena_make(size_t size);
|
|
||||||
Gebs_Arena *gebs_arena_expand(Gebs_Arena *a, size_t new_size);
|
|
||||||
void *gebs_arena_malloc(void *self, size_t size);
|
void *gebs_arena_malloc(void *self, size_t size);
|
||||||
void gebs_arena_free(void *self, void *memory);
|
void gebs_arena_free(void *self, void *memory);
|
||||||
void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_size);
|
void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_size);
|
||||||
|
|
||||||
|
#define gebs_arena_get(cap) \
|
||||||
|
({ \
|
||||||
|
Gebs_Arena __arena = {0}; \
|
||||||
|
__arena.malloc = &gebs_arena_malloc; \
|
||||||
|
__arena.realloc = &gebs_arena_realloc; \
|
||||||
|
__arena.free = &gebs_arena_free; \
|
||||||
|
__arena.capacity = (cap); \
|
||||||
|
__arena; \
|
||||||
|
})
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Dynamic list
|
// Dynamic list
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -301,7 +303,7 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
|
|||||||
# define GEBS_SCRATCH_ARENA_SIZE 4096
|
# define GEBS_SCRATCH_ARENA_SIZE 4096
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern Gebs_Arena *gebs_scratch_arena;
|
extern Gebs_Arena gebs_scratch_arena;
|
||||||
|
|
||||||
char *gebs_fmt(const char *fmt, ...);
|
char *gebs_fmt(const char *fmt, ...);
|
||||||
void gebs_scratch_arena_reset(void);
|
void gebs_scratch_arena_reset(void);
|
||||||
@ -316,6 +318,7 @@ int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd)
|
|||||||
{
|
{
|
||||||
Gebs_String_Builder sb = {0};
|
Gebs_String_Builder sb = {0};
|
||||||
gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
|
gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
|
||||||
|
gebs_sb_finish_alloc(alloc, &sb);
|
||||||
GEBS_LOGI("cmd `%s`\n", sb.items);
|
GEBS_LOGI("cmd `%s`\n", sb.items);
|
||||||
|
|
||||||
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
|
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
|
||||||
@ -363,6 +366,7 @@ int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_S
|
|||||||
{
|
{
|
||||||
Gebs_String_Builder sb = {0};
|
Gebs_String_Builder sb = {0};
|
||||||
gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
|
gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
|
||||||
|
gebs_sb_finish_alloc(alloc, &sb);
|
||||||
GEBS_LOGI("cmd `%s`\n", sb.items);
|
GEBS_LOGI("cmd `%s`\n", sb.items);
|
||||||
|
|
||||||
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
|
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
|
||||||
@ -449,68 +453,23 @@ void *gebs_default_allocator_realloc(discard void *self, void *memory,
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
Gebs_Arena *gebs_arena_make(size_t size)
|
|
||||||
{
|
|
||||||
Gebs_Arena *a;
|
|
||||||
if (size == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = malloc(sizeof(*a));
|
|
||||||
if (a == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
a->malloc = &gebs_arena_malloc;
|
|
||||||
a->free = &gebs_arena_free;
|
|
||||||
a->realloc = &gebs_arena_realloc;
|
|
||||||
|
|
||||||
a->region = malloc(size);
|
|
||||||
if (a->region == NULL) {
|
|
||||||
free(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
a->index = 0;
|
|
||||||
a->size = size;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
Gebs_Arena *gebs_arena_expand(Gebs_Arena *a, size_t new_size)
|
|
||||||
{
|
|
||||||
if (a == NULL || new_size <= a->size) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
a->region = realloc(a->region, new_size);
|
|
||||||
if (a->region == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
a->size = new_size;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *gebs_arena_malloc(void *self, size_t size)
|
void *gebs_arena_malloc(void *self, size_t size)
|
||||||
{
|
{
|
||||||
Gebs_Arena *a = (Gebs_Arena *)self;
|
Gebs_Arena *a = (Gebs_Arena *)self;
|
||||||
unsigned int offset;
|
|
||||||
|
|
||||||
if (size == 0) {
|
if (a->buffer == NULL) {
|
||||||
return NULL;
|
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
|
||||||
|
int prot = PROT_READ | PROT_WRITE;
|
||||||
|
int vis = MAP_SHARED | MAP_ANONYMOUS;
|
||||||
|
a->buffer = mmap(0, a->capacity, prot, vis, -1, 0);
|
||||||
|
#else
|
||||||
|
# error "gebs_arena_malloc unknown platform"
|
||||||
|
#endif
|
||||||
|
a->end = a->buffer;
|
||||||
}
|
}
|
||||||
|
void *p = a->end;
|
||||||
if (a == NULL || a->region == NULL) {
|
a->end = (void *)((uintptr_t)a->end + size);
|
||||||
return NULL;
|
return p;
|
||||||
}
|
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
if (a->size - (a->index + offset) < size) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
a->index += size;
|
|
||||||
return a->region + (a->index - size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gebs_arena_free(discard void *self, discard void *memory)
|
void gebs_arena_free(discard void *self, discard void *memory)
|
||||||
@ -518,53 +477,45 @@ void gebs_arena_free(discard void *self, discard void *memory)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *gebs_arena_realloc(void *self, void *memory,
|
void *gebs_arena_realloc(void *self, void *memory,
|
||||||
discard size_t prev_size, size_t new_size)
|
size_t prev_size, size_t new_size)
|
||||||
{
|
{
|
||||||
Gebs_Arena *a = (Gebs_Arena *)self;
|
Gebs_Arena *a = (Gebs_Arena *)self;
|
||||||
|
|
||||||
uintptr_t offset = (char *)memory - a->region;
|
void *new = gebs_arena_malloc(a, new_size);
|
||||||
gebs_arena_expand(a, a->size + new_size);
|
memcpy(new, memory, prev_size);
|
||||||
return a->region + offset;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gebs_arena_reset(Gebs_Arena *a)
|
void gebs_arena_reset(Gebs_Arena *a)
|
||||||
{
|
{
|
||||||
if (a == NULL) {
|
a->end = a->buffer;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
a->index = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gebs_arena_destroy(Gebs_Arena *a)
|
void gebs_arena_destroy(Gebs_Arena *a)
|
||||||
{
|
{
|
||||||
if (a == NULL) {
|
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
|
||||||
return;
|
munmap(a->buffer, a->capacity);
|
||||||
}
|
#else
|
||||||
|
# error "gebs_arena_destroy unknown platform"
|
||||||
if (a->region != NULL) {
|
#endif
|
||||||
free(a->region);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Scratch arena
|
// Scratch arena
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
Gebs_Arena *gebs_scratch_arena;
|
Gebs_Arena gebs_scratch_arena;
|
||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
void gebs_scratch_areana_init(void)
|
void gebs_scratch_areana_init(void)
|
||||||
{
|
{
|
||||||
gebs_scratch_arena = gebs_arena_make(GEBS_SCRATCH_ARENA_SIZE);
|
gebs_scratch_arena = gebs_arena_get(4*1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((destructor))
|
__attribute__((destructor))
|
||||||
void gebs_scratch_areana_free(void)
|
void gebs_scratch_areana_free(void)
|
||||||
{
|
{
|
||||||
gebs_arena_destroy(gebs_scratch_arena);
|
gebs_arena_destroy(&gebs_scratch_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *gebs_fmt(const char *fmt, ...)
|
char *gebs_fmt(const char *fmt, ...)
|
||||||
@ -577,7 +528,7 @@ char *gebs_fmt(const char *fmt, ...)
|
|||||||
size_t size = vsnprintf(NULL, 0, fmt, list_copy);
|
size_t size = vsnprintf(NULL, 0, fmt, list_copy);
|
||||||
va_end(list_copy);
|
va_end(list_copy);
|
||||||
|
|
||||||
char *buf = gebs_malloc(gebs_scratch_arena, size+1);
|
char *buf = gebs_malloc(&gebs_scratch_arena, size+1);
|
||||||
vsprintf(buf, fmt, list);
|
vsprintf(buf, fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
return buf;
|
return buf;
|
||||||
@ -585,7 +536,7 @@ char *gebs_fmt(const char *fmt, ...)
|
|||||||
|
|
||||||
void gebs_scratch_arena_reset(void)
|
void gebs_scratch_arena_reset(void)
|
||||||
{
|
{
|
||||||
gebs_arena_reset(gebs_scratch_arena);
|
gebs_arena_reset(&gebs_scratch_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user