Scratch arena, in-place temporary gebs_fmt() macro
This commit is contained in:
26
example/arena.c
Normal file
26
example/arena.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#define GEBS_IMPLEMENTATION
|
||||||
|
#include "../gebs.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int *items;
|
||||||
|
size_t count, capacity;
|
||||||
|
} Ints;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
Gebs_Arena *arena = gebs_arena_make(1024);
|
||||||
|
defer { gebs_arena_destroy(arena); }
|
||||||
|
|
||||||
|
Ints ints = {0};
|
||||||
|
defer { gebs_list_free_alloc(arena, &ints); }
|
||||||
|
for (size_t i = 0; i < 1000; i++) {
|
||||||
|
gebs_list_append_alloc(arena, &ints, i);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ints.count; i++) {
|
||||||
|
printf("%zu\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s\n", gebs_fmt("Hello formatting %d", 124));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
4
gebs.c
4
gebs.c
@ -9,7 +9,9 @@ int main(int argc, char ** argv)
|
|||||||
gebs_mkdir("build");
|
gebs_mkdir("build");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GEBS_CMD("gcc", "-o", "build/self_rebuild", "example/self_rebuild.c") != 0)
|
if (GEBS_CMD("gcc", "-ggdb", "-o", "build/self_rebuild", "example/self_rebuild.c") != 0)
|
||||||
|
return 1;
|
||||||
|
if (GEBS_CMD("gcc", "-ggdb", "-o", "build/arena", "example/arena.c") != 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
190
gebs.h
190
gebs.h
@ -62,22 +62,48 @@
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *(*malloc)(size_t size);
|
void *(*malloc)(void *self, size_t size);
|
||||||
void (*free)(void *memory);
|
void (*free)(void *self, void *memory);
|
||||||
void *(*realloc)(void *memory, size_t prev_size, size_t new_size);
|
void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size);
|
||||||
} Gebs_Allocator;
|
} Gebs_Allocator;
|
||||||
|
|
||||||
// Wrapper macros
|
// Wrapper macros
|
||||||
#define gebs_malloc(alloc, size) ((alloc)->malloc((size)))
|
#define gebs_malloc(alloc, size) ((alloc)->malloc((void *)(alloc), (size)))
|
||||||
#define gebs_free(alloc, memory) ((alloc)->free((memory)))
|
#define gebs_free(alloc, memory) ((alloc)->free((void *)(alloc), (memory)))
|
||||||
#define gebs_realloc(alloc, memory, prev_size, new_size) \
|
#define gebs_realloc(alloc, memory, prev_size, new_size) \
|
||||||
((alloc)->realloc((memory), (prev_size), (new_size)))
|
((alloc)->realloc((void *)(alloc), (memory), (prev_size), (new_size)))
|
||||||
|
|
||||||
extern Gebs_Allocator gebs_default_allocator;
|
extern Gebs_Allocator gebs_default_allocator;
|
||||||
|
|
||||||
void *gebs_default_allocator_malloc(size_t size);
|
void *gebs_default_allocator_malloc(void *self, size_t size);
|
||||||
void gebs_default_allocator_free(void *memory);
|
void gebs_default_allocator_free(void *self, void *memory);
|
||||||
void *gebs_default_allocator_realloc(void *memory, size_t prev_size, size_t new_size);
|
void *gebs_default_allocator_realloc(void *self, void *memory,
|
||||||
|
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 {
|
||||||
|
void *(*malloc)(void *self, size_t size);
|
||||||
|
void (*free)(void *self, void *memory);
|
||||||
|
void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size);
|
||||||
|
|
||||||
|
char *region;
|
||||||
|
size_t index;
|
||||||
|
size_t size;
|
||||||
|
} Gebs_Arena;
|
||||||
|
|
||||||
|
void gebs_arena_reset(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_free(void *self, void *memory);
|
||||||
|
void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_size);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Dynamic list
|
// Dynamic list
|
||||||
@ -210,6 +236,24 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
|
|||||||
sizeof(__argv)/sizeof(__argv[0]), (char**)__argv, __FILE__); \
|
sizeof(__argv)/sizeof(__argv[0]), (char**)__argv, __FILE__); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Scratch arena
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef GEBS_SCRATCH_ARENA_SIZE
|
||||||
|
# define GEBS_SCRATCH_ARENA_SIZE 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern Gebs_Arena *gebs_scratch_arena;
|
||||||
|
|
||||||
|
#define gebs_fmt(fmt, ...) \
|
||||||
|
({ \
|
||||||
|
size_t __size = snprintf(NULL, 0, (fmt), ##__VA_ARGS__); \
|
||||||
|
char *__buf = gebs_malloc(gebs_scratch_arena, __size+1); \
|
||||||
|
sprintf(__buf, (fmt), ##__VA_ARGS__); \
|
||||||
|
__buf; \
|
||||||
|
})
|
||||||
|
|
||||||
#ifdef GEBS_IMPLEMENTATION
|
#ifdef GEBS_IMPLEMENTATION
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -273,22 +317,144 @@ Gebs_Allocator gebs_default_allocator = {
|
|||||||
.realloc = &gebs_default_allocator_realloc,
|
.realloc = &gebs_default_allocator_realloc,
|
||||||
};
|
};
|
||||||
|
|
||||||
void *gebs_default_allocator_malloc(size_t size)
|
void *gebs_default_allocator_malloc(void *self, size_t size)
|
||||||
{
|
{
|
||||||
|
(void)self;
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gebs_default_allocator_free(void *memory)
|
void gebs_default_allocator_free(void *self, void *memory)
|
||||||
{
|
{
|
||||||
|
(void)self;
|
||||||
free(memory);
|
free(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *gebs_default_allocator_realloc(void *memory, size_t prev_size, size_t new_size)
|
void *gebs_default_allocator_realloc(void *self, void *memory,
|
||||||
|
size_t prev_size, size_t new_size)
|
||||||
{
|
{
|
||||||
|
(void)self;
|
||||||
void *p = realloc(memory, new_size);
|
void *p = realloc(memory, new_size);
|
||||||
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)
|
||||||
|
{
|
||||||
|
Gebs_Arena *a = (Gebs_Arena *)self;
|
||||||
|
unsigned int offset;
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == NULL || a->region == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
if (a->size - (a->index + offset) < size) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->index += size;
|
||||||
|
return a->region + (a->index - size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gebs_arena_free(void *self, void *memory)
|
||||||
|
{
|
||||||
|
(void)self;
|
||||||
|
(void)memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_size)
|
||||||
|
{
|
||||||
|
(void)prev_size;
|
||||||
|
(void)memory;
|
||||||
|
gebs_arena_expand((Gebs_Arena *)self, new_size);
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gebs_arena_reset(Gebs_Arena *a)
|
||||||
|
{
|
||||||
|
if (a == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gebs_arena_destroy(Gebs_Arena *a)
|
||||||
|
{
|
||||||
|
if (a == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->region != NULL) {
|
||||||
|
free(a->region);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Scratch arena
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Gebs_Arena *gebs_scratch_arena;
|
||||||
|
|
||||||
|
__attribute__((constructor))
|
||||||
|
void gebs_scratch_areana_init(void)
|
||||||
|
{
|
||||||
|
gebs_scratch_arena = gebs_arena_make(GEBS_SCRATCH_ARENA_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((destructor))
|
||||||
|
void gebs_scratch_areana_free(void)
|
||||||
|
{
|
||||||
|
gebs_arena_destroy(gebs_scratch_arena);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Filesystem operations
|
// Filesystem operations
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user