Mercurial > molko
changeset 438:25a56ca53ac2
core: update mlk-alloc module
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 17 Oct 2022 14:22:07 +0200 |
parents | e1eebc6bf25d |
children | f794dbbb18d2 |
files | GNUmakefile examples/example-drawable/example-drawable.c examples/example/spell-fire.c libmlk-core/mlk/core/alloc.c libmlk-core/mlk/core/alloc.h libmlk-core/mlk/core/buf.h libmlk-core/mlk/core/sys.c libmlk-rpg/mlk/rpg/battle-bar-default.c libmlk-rpg/mlk/rpg/battle-entity-state-attacking.c libmlk-rpg/mlk/rpg/battle-entity-state-blinking.c libmlk-rpg/mlk/rpg/battle-entity-state-moving.c libmlk-rpg/mlk/rpg/battle-state-ai.c libmlk-rpg/mlk/rpg/battle-state-attacking.c libmlk-rpg/mlk/rpg/battle-state-check.c libmlk-rpg/mlk/rpg/battle-state-closing.c libmlk-rpg/mlk/rpg/battle-state-item.c libmlk-rpg/mlk/rpg/map-file.c libmlk-rpg/mlk/rpg/map-file.h libmlk-rpg/mlk/rpg/tileset-file.c libmlk-rpg/mlk/rpg/tileset-file.h man/mlk-alloc.3 tests/test-alloc.c |
diffstat | 22 files changed, 417 insertions(+), 99 deletions(-) [+] |
line wrap: on
line diff
--- a/GNUmakefile Sun Oct 16 13:21:40 2022 +0200 +++ b/GNUmakefile Mon Oct 17 14:22:07 2022 +0200 @@ -53,7 +53,7 @@ $(OPENAL_INCS) \ $(SNDFILE_INCS) -OPTS := -Wall -Wextra -pipe +OPTS += -Wall -Wextra -pipe ifeq ($(OS),Darwin) OPTS += -Wno-deprecated-declarations @@ -415,7 +415,8 @@ # {{{ manual pages -MAN3 := man/mlk-err.3 +MAN3 := man/mlk-alloc.3 \ + man/mlk-err.3 # }}}
--- a/examples/example-drawable/example-drawable.c Sun Oct 16 13:21:40 2022 +0200 +++ b/examples/example-drawable/example-drawable.c Mon Oct 17 14:22:07 2022 +0200 @@ -111,7 +111,7 @@ static void spawn(int x, int y) { - struct explosion *ex = alloc_new0(sizeof (*ex)); + struct explosion *ex = mlk_alloc_new0(sizeof (*ex)); animation_init(&ex->anim, &explosion_sprite, 15);
--- a/examples/example/spell-fire.c Sun Oct 16 13:21:40 2022 +0200 +++ b/examples/example/spell-fire.c Mon Oct 17 14:22:07 2022 +0200 @@ -104,7 +104,7 @@ (void)owner; - self = alloc_new0(sizeof (*self)); + self = mlk_alloc_new0(sizeof (*self)); self->selection = slt->index_character; self->battle = bt; self->drawable.data = self;
--- a/libmlk-core/mlk/core/alloc.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-core/mlk/core/alloc.c Mon Oct 17 14:22:07 2022 +0200 @@ -28,13 +28,15 @@ #include "error.h" #include "panic.h" +#define OOM_MSG "out of memory" + static void * panic_alloc(size_t size) { void *mem; if (!(mem = malloc(size))) - panicf("%s", strerror(errno)); + panicf(OOM_MSG); return mem; } @@ -45,21 +47,19 @@ void *mem; if (!(mem = realloc(ptr, size)) && size != 0) - panicf("%s", strerror(errno)); + panicf(OOM_MSG); return mem; } -static const struct alloc_funcs default_alloc_funcs = { +static const struct mlk_alloc_funcs *funcs = &(const struct mlk_alloc_funcs) { .alloc = panic_alloc, .realloc = panic_realloc, .free = free }; -static const struct alloc_funcs *funcs = &default_alloc_funcs; - void -alloc_set(const struct alloc_funcs *newfuncs) +mlk_alloc_set(const struct mlk_alloc_funcs *newfuncs) { assert(funcs); assert(funcs->alloc); @@ -69,11 +69,11 @@ funcs = newfuncs; /* Change SDL allocators as well. */ - SDL_SetMemoryFunctions(alloc_new, alloc_array0, alloc_renew, free); + SDL_SetMemoryFunctions(mlk_alloc_new, mlk_alloc_array0, mlk_alloc_renew, free); } void * -alloc_new(size_t size) +mlk_alloc_new(size_t size) { assert(size != 0); @@ -81,7 +81,7 @@ } void * -alloc_new0(size_t size) +mlk_alloc_new0(size_t size) { assert(size != 0); @@ -89,7 +89,7 @@ } void * -alloc_array(size_t len, size_t elemsize) +mlk_alloc_array(size_t len, size_t elemsize) { assert(len != 0); assert(elemsize != 0); @@ -98,22 +98,22 @@ } void * -alloc_array0(size_t len, size_t elemsize) +mlk_alloc_array0(size_t len, size_t elemsize) { assert(len != 0); assert(elemsize != 0); - return alloc_new0(len * elemsize); + return mlk_alloc_new0(len * elemsize); } void * -alloc_renew(void *ptr, size_t size) +mlk_alloc_renew(void *ptr, size_t size) { return funcs->realloc(ptr, size); } void * -alloc_rearray(void *ptr, size_t len, size_t elemsize) +mlk_alloc_rearray(void *ptr, size_t len, size_t elemsize) { assert(elemsize != 0); @@ -121,7 +121,7 @@ } void * -alloc_rearray0(void *ptr, size_t oldlen, size_t newlen, size_t elemsize) +mlk_alloc_rearray0(void *ptr, size_t oldlen, size_t newlen, size_t elemsize) { ptr = funcs->realloc(ptr, newlen * elemsize); @@ -132,7 +132,7 @@ } void * -alloc_dup(const void *ptr, size_t size) +mlk_alloc_dup(const void *ptr, size_t size) { assert(ptr); assert(size != 0); @@ -141,7 +141,7 @@ } char * -alloc_sdup(const char *src) +mlk_alloc_sdup(const char *src) { assert(src); @@ -151,7 +151,7 @@ } char * -alloc_sdupf(const char *fmt, ...) +mlk_alloc_sdupf(const char *fmt, ...) { struct buf buf = {0}; va_list ap; @@ -164,39 +164,39 @@ } void -alloc_free(void *ptr) +mlk_alloc_free(void *ptr) { funcs->free(ptr); } void -alloc_pool_init(struct alloc_pool *pool, size_t elemsize, void (*finalizer)(void *)) +mlk_alloc_pool_init(struct mlk_alloc_pool *pool, size_t elemsize, void (*finalizer)(void *)) { assert(pool); assert(elemsize != 0); - pool->data = alloc_array(ALLOC_POOL_INIT_DEFAULT, elemsize); + pool->data = mlk_alloc_array(MLK_ALLOC_POOL_INIT_DEFAULT, elemsize); pool->elemsize = elemsize; pool->size = 0; - pool->capacity = ALLOC_POOL_INIT_DEFAULT; + pool->capacity = MLK_ALLOC_POOL_INIT_DEFAULT; pool->finalizer = finalizer; } void * -alloc_pool_new(struct alloc_pool *pool) +mlk_alloc_pool_new(struct mlk_alloc_pool *pool) { assert(pool); if (pool->size >= pool->capacity) { pool->capacity *= 2; - pool->data = alloc_rearray(pool->data, pool->capacity, pool->elemsize); + pool->data = mlk_alloc_rearray(pool->data, pool->capacity, pool->elemsize); } return ((unsigned char *)pool->data) + pool->size++ * pool->elemsize; } void * -alloc_pool_get(const struct alloc_pool *pool, size_t index) +mlk_alloc_pool_get(const struct mlk_alloc_pool *pool, size_t index) { assert(pool); assert(index < pool->size); @@ -205,20 +205,20 @@ } void * -alloc_pool_shrink(struct alloc_pool *pool) +mlk_alloc_pool_shrink(struct mlk_alloc_pool *pool) { assert(pool); void *ptr; - ptr = alloc_rearray(pool->data, pool->size, pool->elemsize); + ptr = mlk_alloc_rearray(pool->data, pool->size, pool->elemsize); memset(pool, 0, sizeof (*pool)); return ptr; } void -alloc_pool_finish(struct alloc_pool *pool) +mlk_alloc_pool_finish(struct mlk_alloc_pool *pool) { unsigned char *tab;
--- a/libmlk-core/mlk/core/alloc.h Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-core/mlk/core/alloc.h Mon Oct 17 14:22:07 2022 +0200 @@ -24,17 +24,17 @@ #include "core.h" /* Must be power of 2. */ -#define ALLOC_POOL_INIT_DEFAULT (32) +#define MLK_ALLOC_POOL_INIT_DEFAULT (32) /* Custom allocator. */ -struct alloc_funcs { +struct mlk_alloc_funcs { void *(*alloc)(size_t); void *(*realloc)(void *, size_t); void (*free)(void *); }; /* Minimalist growable array for loading data. */ -struct alloc_pool { +struct mlk_alloc_pool { void *data; size_t elemsize; size_t size; @@ -46,56 +46,56 @@ /* allocator functions. */ void -alloc_set(const struct alloc_funcs *); +mlk_alloc_set(const struct mlk_alloc_funcs *); void * -alloc_new(size_t); +mlk_alloc_new(size_t); void * -alloc_new0(size_t); +mlk_alloc_new0(size_t); void * -alloc_array(size_t, size_t); +mlk_alloc_array(size_t, size_t); void * -alloc_array0(size_t, size_t); +mlk_alloc_array0(size_t, size_t); void * -alloc_renew(void *, size_t); +mlk_alloc_renew(void *, size_t); void * -alloc_rearray(void *, size_t, size_t); +mlk_alloc_rearray(void *, size_t, size_t); void * -alloc_rearray0(void *, size_t, size_t, size_t); +mlk_alloc_rearray0(void *, size_t, size_t, size_t); void * -alloc_dup(const void *, size_t); +mlk_alloc_dup(const void *, size_t); char * -alloc_sdup(const char *); +mlk_alloc_sdup(const char *); char * -alloc_sdupf(const char *, ...); +mlk_alloc_sdupf(const char *, ...); void -alloc_free(void *); +mlk_alloc_free(void *); /* alloc_pool functions. */ void -alloc_pool_init(struct alloc_pool *, size_t , void (*)(void *)); +mlk_alloc_pool_init(struct mlk_alloc_pool *, size_t , void (*)(void *)); void * -alloc_pool_new(struct alloc_pool *); +mlk_alloc_pool_new(struct mlk_alloc_pool *); void * -alloc_pool_get(const struct alloc_pool *, size_t); +mlk_alloc_pool_get(const struct mlk_alloc_pool *, size_t); void * -alloc_pool_shrink(struct alloc_pool *); +mlk_alloc_pool_shrink(struct mlk_alloc_pool *); void -alloc_pool_finish(struct alloc_pool *); +mlk_alloc_pool_finish(struct mlk_alloc_pool *); CORE_END_DECLS
--- a/libmlk-core/mlk/core/buf.h Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-core/mlk/core/buf.h Mon Oct 17 14:22:07 2022 +0200 @@ -25,15 +25,15 @@ #include "alloc.h" #if !defined(BUF_MALLOC) -# define BUF_MALLOC alloc_new +# define BUF_MALLOC mlk_alloc_new #endif #if !defined(BUF_REALLOC) -# define BUF_REALLOC alloc_renew +# define BUF_REALLOC mlk_alloc_renew #endif #if !defined(BUF_FREE) -# define BUF_FREE alloc_free +# define BUF_FREE mlk_alloc_free #endif #if defined(__cplusplus)
--- a/libmlk-core/mlk/core/sys.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-core/mlk/core/sys.c Mon Oct 17 14:22:07 2022 +0200 @@ -272,10 +272,10 @@ struct audiostream *stream; int ret = 0; - stream = alloc_new(sizeof (*stream)); + stream = mlk_alloc_new(sizeof (*stream)); stream->samplerate = info->samplerate; stream->samplesz = info->frames * info->channels; - stream->samples = alloc_array(stream->samplesz, sizeof (*stream->samples)); + stream->samples = mlk_alloc_array(stream->samplesz, sizeof (*stream->samples)); stream->format = info->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; sf_command(file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
--- a/libmlk-rpg/mlk/rpg/battle-bar-default.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/battle-bar-default.c Mon Oct 17 14:22:07 2022 +0200 @@ -556,7 +556,7 @@ (void)bt; - bar->items = alloc_rearray0(bar->items, bar->itemsz, + bar->items = mlk_alloc_rearray0(bar->items, bar->itemsz, CHARACTER_SPELL_MAX, sizeof (*bar->items)); bar->itemsz = CHARACTER_SPELL_MAX; bar->state = BATTLE_BAR_DEFAULT_STATE_GRID;
--- a/libmlk-rpg/mlk/rpg/battle-entity-state-attacking.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/battle-entity-state-attacking.c Mon Oct 17 14:22:07 2022 +0200 @@ -90,7 +90,7 @@ struct self *self; - self = alloc_new0(sizeof (*self)); + self = mlk_alloc_new0(sizeof (*self)); self->state.data = self; self->state.update = update; self->state.draw = draw;
--- a/libmlk-rpg/mlk/rpg/battle-entity-state-blinking.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/battle-entity-state-blinking.c Mon Oct 17 14:22:07 2022 +0200 @@ -87,7 +87,7 @@ struct self *self; - self = alloc_new0(sizeof (*self)); + self = mlk_alloc_new0(sizeof (*self)); self->state.data = self; self->state.update = update; self->state.finish = finish;
--- a/libmlk-rpg/mlk/rpg/battle-entity-state-moving.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/battle-entity-state-moving.c Mon Oct 17 14:22:07 2022 +0200 @@ -118,7 +118,7 @@ struct self *self; - self = alloc_new0(sizeof (*self)); + self = mlk_alloc_new0(sizeof (*self)); self->state.data = self; self->state.update = update; self->state.draw = draw;
--- a/libmlk-rpg/mlk/rpg/battle-state-ai.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/battle-state-ai.c Mon Oct 17 14:22:07 2022 +0200 @@ -82,7 +82,7 @@ struct battle_state *self; - self = alloc_new0(sizeof (*self)); + self = mlk_alloc_new0(sizeof (*self)); self->data = bt; self->update = update; self->draw = draw;
--- a/libmlk-rpg/mlk/rpg/battle-state-attacking.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/battle-state-attacking.c Mon Oct 17 14:22:07 2022 +0200 @@ -165,7 +165,7 @@ struct self *self; - self = alloc_new0(sizeof (*self)); + self = mlk_alloc_new0(sizeof (*self)); self->state.data = self; self->state.update = update; self->state.draw = draw;
--- a/libmlk-rpg/mlk/rpg/battle-state-check.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/battle-state-check.c Mon Oct 17 14:22:07 2022 +0200 @@ -88,7 +88,7 @@ return; } - fade = alloc_new0(sizeof (*fade)); + fade = mlk_alloc_new0(sizeof (*fade)); fade->ch = et->ch; fade->x = et->x; fade->y = et->y; @@ -99,7 +99,7 @@ fade->dw.finish = fadeout_finish; if (drawable_stack_add(bt->effects, &fade->dw) < 0) - free(fade); + mlk_alloc_free(fade); } static int @@ -197,7 +197,7 @@ struct battle_state *self; - self = alloc_new0(sizeof (*self)); + self = mlk_alloc_new0(sizeof (*self)); self->data = bt; self->update = update; self->draw = draw;
--- a/libmlk-rpg/mlk/rpg/battle-state-closing.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/battle-state-closing.c Mon Oct 17 14:22:07 2022 +0200 @@ -129,7 +129,7 @@ struct self *self; - self = alloc_new0(sizeof (*self)); + self = mlk_alloc_new0(sizeof (*self)); self->state.data = self; self->state.update = update; self->state.draw = draw;
--- a/libmlk-rpg/mlk/rpg/battle-state-item.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/battle-state-item.c Mon Oct 17 14:22:07 2022 +0200 @@ -136,7 +136,7 @@ struct self *self; - self = alloc_new0(sizeof (*self)); + self = mlk_alloc_new0(sizeof (*self)); self->state.data = self; self->state.update = update; self->state.draw = draw;
--- a/libmlk-rpg/mlk/rpg/map-file.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/map-file.c Mon Oct 17 14:22:07 2022 +0200 @@ -66,7 +66,7 @@ * The next line after a layer declaration is a list of plain integer * that fill the layer tiles. */ - if (!(ctx->mf->layers[layer_type].tiles = alloc_array0(amount, sizeof (unsigned short)))) + if (!(ctx->mf->layers[layer_type].tiles = mlk_alloc_array0(amount, sizeof (unsigned short)))) return -1; for (int tile; fscanf(ctx->fp, "%d\n", &tile) && current < amount; ++current) @@ -102,7 +102,7 @@ * directive has one. */ if (block) { - if (!(reg = alloc_pool_new(&ctx->mf->blocks))) + if (!(reg = mlk_alloc_pool_new(&ctx->mf->blocks))) return -1; reg->x = x; @@ -275,7 +275,7 @@ int ret = 0; memset(map, 0, sizeof (*map)); - alloc_pool_init(&file->blocks, sizeof (*map->blocks), NULL); + mlk_alloc_pool_init(&file->blocks, sizeof (*map->blocks), NULL); if (!(ctx.fp = fopen(path, "r"))) goto fail; @@ -306,7 +306,7 @@ free(file->layers[2].tiles); tileset_file_finish(&file->tileset_file); - alloc_pool_finish(&file->blocks); + mlk_alloc_pool_finish(&file->blocks); memset(file, 0, sizeof (*file)); }
--- a/libmlk-rpg/mlk/rpg/map-file.h Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/map-file.h Mon Oct 17 14:22:07 2022 +0200 @@ -37,7 +37,7 @@ struct map_layer layers[MAP_LAYER_TYPE_NUM]; struct tileset_file tileset_file; struct tileset tileset; - struct alloc_pool blocks; + struct mlk_alloc_pool blocks; }; CORE_BEGIN_DECLS
--- a/libmlk-rpg/mlk/rpg/tileset-file.c Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/tileset-file.c Mon Oct 17 14:22:07 2022 +0200 @@ -152,10 +152,10 @@ unsigned short id, w, h; struct tileset_tiledef *td; - alloc_pool_init(&ctx->tf->tiledefs, sizeof (*td), NULL); + mlk_alloc_pool_init(&ctx->tf->tiledefs, sizeof (*td), NULL); while (fscanf(ctx->fp, "%hu|%hd|%hd|%hu|%hu\n", &id, &x, &y, &w, &h) == 5) { - td = alloc_pool_new(&ctx->tf->tiledefs); + td = mlk_alloc_pool_new(&ctx->tf->tiledefs); td->id = id; td->x = x; td->y = y; @@ -181,15 +181,15 @@ char filename[FILENAME_MAX + 1]; struct tileset_animation_block *anim; - alloc_pool_init(&ctx->tf->anims[0], sizeof (struct tileset_animation_block), tileset_animation_block_finish); - alloc_pool_init(&ctx->tf->anims[1], sizeof (struct tileset_animation), NULL); + mlk_alloc_pool_init(&ctx->tf->anims[0], sizeof (struct tileset_animation_block), tileset_animation_block_finish); + mlk_alloc_pool_init(&ctx->tf->anims[1], sizeof (struct tileset_animation), NULL); /* * 1. Create the first array of animation, sprite and texture that are * owned by the tileset_file structure. */ while (fscanf(ctx->fp, "%hu|" MAX_F(FILENAME_MAX) "|%u", &id, filename, &delay) == 3) { - anim = alloc_pool_new(&ctx->tf->anims[0]); + anim = mlk_alloc_pool_new(&ctx->tf->anims[0]); if (image_open(&anim->texture, util_pathf("%s/%s", ctx->basedir, filename)) < 0) return -1; @@ -203,10 +203,10 @@ * animations referencing the first array. */ for (size_t i = 0; i < ctx->tf->anims[0].size; ++i) { - struct tileset_animation_block *anim = alloc_pool_get(&ctx->tf->anims[0], i); + struct tileset_animation_block *anim = mlk_alloc_pool_get(&ctx->tf->anims[0], i); struct tileset_animation *ta; - if (!(ta = alloc_pool_new(&ctx->tf->anims[1]))) + if (!(ta = mlk_alloc_pool_new(&ctx->tf->anims[1]))) return -1; ta->id = id; @@ -324,9 +324,9 @@ { assert(tf); - alloc_pool_finish(&tf->tiledefs); - alloc_pool_finish(&tf->anims[0]); - alloc_pool_finish(&tf->anims[1]); + mlk_alloc_pool_finish(&tf->tiledefs); + mlk_alloc_pool_finish(&tf->anims[0]); + mlk_alloc_pool_finish(&tf->anims[1]); texture_finish(&tf->image);
--- a/libmlk-rpg/mlk/rpg/tileset-file.h Sun Oct 16 13:21:40 2022 +0200 +++ b/libmlk-rpg/mlk/rpg/tileset-file.h Mon Oct 17 14:22:07 2022 +0200 @@ -30,8 +30,8 @@ struct tileset_tiledef; struct tileset_file { - struct alloc_pool tiledefs; - struct alloc_pool anims[2]; + struct mlk_alloc_pool tiledefs; + struct mlk_alloc_pool anims[2]; struct texture image; struct sprite sprite; };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/man/mlk-alloc.3 Mon Oct 17 14:22:07 2022 +0200 @@ -0,0 +1,317 @@ +.Dd $Mdocdate$ +.Dt MLK-ALLOC 3 +.Os +.Sh NAME +.Nm mlk-alloc +.Nd allocation routines +.Sh LIBRARY +.Lb libmlk-core +.Sh SYNOPSIS +.In mlk/core/alloc.h +.Ft void +.Fn mlk_alloc_set "const struct mlk_alloc_funcs *funcs" +.Ft void * +.Fn mlk_alloc_new "size_t size" +.Ft void * +.Fn mlk_alloc_new0 "size_t size" +.Ft void * +.Fn mlk_alloc_array "size_t len" "size_t elemsize" +.Ft void * +.Fn mlk_alloc_array0 "size_t len" "size_t elemsize" +.Ft void * +.Fn mlk_alloc_renew "void *ptr" "size_t size" +.Ft void * +.Fn mlk_alloc_rearray "void *ptr" "size_t newlen" "size_t elemsize" +.Ft void * +.Fn mlk_alloc_rearray0 "void *ptr" "size_t oldlen" "size_t newlen" "size_t elemsize" +.Ft void * +.Fn mlk_alloc_dup "const void *ptr" "size_t size" +.Ft char * +.Fn mlk_alloc_sdup "const char *src" +.Ft char * +.Fn mlk_alloc_sdupf "const char *fmt" ... +.Ft void +.Fn mlk_alloc_free "void *ptr" +.Ft void +.Fn mlk_alloc_pool_init "struct mlk_alloc_pool *pool" "size_t elemsize" "void (*finalizer)(void *)" +.Ft void * +.Fn mlk_alloc_pool_new "struct mlk_alloc_pool *pool" +.Ft void * +.Fn mlk_alloc_pool_get "const struct mlk_alloc_pool *pool, size_t index" +.Ft void * +.Fn mlk_alloc_pool_shrink "struct mlk_alloc_pool *pool" +.Ft void +.Fn mlk_alloc_pool_finish "struct mlk_alloc_pool *pool" +.Sh DESCRIPTION +The allocation strategy in the mlk framework is to call +.Xr mlk-panic 3 +in case of memory exhaustion. It is designed in mind that recovering of lack of +memory in a game is usually impossible. However, the user can still change the +allocation functions to perform custom actions but it should be noted that mlk +framework don't except any of the function to return NULL in case of memory +exhaustion. +.Pp +The user should use its own functions when memory exhaustion has to be tested. +.Pp +The +.Vt "struct mlk_alloc_funcs" +type is defined as: +.Bd -literal +struct mlk_alloc_funcs { + void *(*alloc)(size_t size); + void *(*realloc)(void *ptr, size_t newsize); + void (*free)(void *ptr); +}; +.Pp +.Ed +Its fields are defined as following: +.Bl -tag +.It Va alloc +This function is called to allocate new memory, it takes the memory +.Fa size +as argument and must return a non-NULL value. +.It Va realloc +This function must reallocate the memory region pointed by +.Fa ptr +with its new size given by +.Fa newsize . +The original +.Fa ptr +may be NULL. The function must not return a non-NULL value. +.It Va free +This function must free the pointer specified by +.Fa ptr . +.El +.Pp +The +.Vt "struct mlk_alloc_pool" +type is defined as: +.Bd -literal +struct mlk_alloc_pool { + void *data; + size_t elemsize; + size_t size; + size_t capacity; + void (*finalizer)(void *); +}; +.Ed +.Pp +Its fields are defined as following: +.Bl -tag +.It Va data +Pointer to the memory region. +.It Va elemsize +Size of individual element. +.It Va size +Number of items in array. +.It Va capacity +Current capacity which may be greater or equal to +.Va size . +.It Va finalizer +Optional finalizer function that should finalize the object pointed by +.Va data +for every element. This function is only called when the +.Fn mlk_alloc_pool_finish +function is used. +.El +.Pp +The +.Fn mlk_alloc_set +function changes allocator functions to +.Fa funcs +allocator routines. It must be kept valid until the program is no longer used. +.Pp +The +.Fn mlk_alloc_new +and +.Fn mlk_alloc_new0 +function allocates memory data of the given +.Fa size . +The +.Fn mlk_alloc_new0 +variant ensure the data is being zero-initialized. +.Pp +The +.Fn mlk_alloc_array +and +.Fn mlk_alloc_array0 +functions allocate an array of +.Fa len +elements of +.Fa elemsize +individually. +The +.Fn mlk_alloc_array0 +variant ensure the data is being zero-initialized. +.Pp +The +.Fn mlk_alloc_renew +function reallocates the pointer +.Fa ptr +(which may be NULL) to the new +.Fa size +which can be 0. +.Pp +The +.Fn mlk_alloc_rearray +function reallocates the pointer +.Fa ptr +(which may be NULL) as an array of +.Fa newlen +elements of +.Fa elemsize +individually. +.Pp +The +.Fn mlk_alloc_rearray0 +function is similar to +.Fn mlk_alloc_rearray +but zero-initialize the memory. It needs the previous length given in +.Fa oldlen +argument because the function would not know which memory region to zero +initialize when increasing the memory. +.Pp +The +.Fn mlk_alloc_dup +function duplicates the pointer +.Fa ptr +with the given +.Fa size . +.Pp +The +.Fn mlk_alloc_sdup +function duplicates the string +.Fa src +and return it. +.Pp +The +.Fn mlk_alloc_sdupf +function creates a dynamically allocated string using printf(3) format like. +.Pp +the +.Fn mlk_alloc_free +function releases memory previously allocated. It must always be used instead of +C standard +.Xr free 3 +function if any function of this module was used to allocates the +.Fa ptr +memory region. +.Pp +The following functions can be used to increase a dynamically allocated array +automatically. It allocates twice as the current storage when size exceeds +capacity. +.Pp +It uses realloc mechanism to upgrade the new storage space so pointers returned +in +.Fn mlk_alloc_pool_new +may get invalided when this function is called. +.Pp +It is designed in mind to help allocating an array of elements when they can't +be determined at runtime (e.g. while reading a file) without the performance +cost of using +.Fn mlk_alloc_rearray +for every elements. +.Pp +The initial capacity is controlled by the +.Dv MLK_ALLOC_POOL_INIT_DEFAULT +macro and +.Em must +be a power of two. +.Pp +A custom finalizer function can be set to finalize each individual object if +necessary. +.Pp +The +.Fn mlk_alloc_pool_init +function initializes the +.Fa pool +as an array where elements have +.Fa elemsize +size. Optional +.Fa finalizer +argument can be passed to finalize every element when clearing the pool. This +will effectively create a initial storage according to +.Dv MLK_ALLOC_POOL_INIT_DEFAULT +value. +.Pp +The +.Fn mlk_alloc_pool_new +function requests a new slot from the +.Fa pool +and return it. If the current size has reached the capacity, it will be doubled +in that case it is possible that all previous pointer may be invalidated. +.Pp +The +.Fn mlk_alloc_pool_get +function returns the value at the given +.Fa index +from the +.Fa pool . +.Pp +The +.Fn mlk_alloc_pool_shrink +function shrink the +.Fa pool +data to the exact number of elements in the array and return the memory region +which user takes full ownership. Once returned data is no longer needed, it must +be released with +.Fn mlk_alloc_free . +.Pp +The pool is emptied and must be reinitialized using +.Fn mlk_alloc_pool_init +before reusing it. It is not necessary to call +.Fn mlk_alloc_pool_finish +but doing so is just no-op. +.Pp +The +.Fn mlk_alloc_pool_finish +function finalizes the +.Fa pool +and all individual elements if a finalizer was set. You must call +.Fn mlk_alloc_pool_init +again before reusing it. +.Sh EXAMPLES +.Ss Use a mlk_alloc_pool to increase an array while reading a file. +.Bd -literal +/* A structure defined line by line inside a file in the form "x|y" */ +struct point { + int x; + int y; +}; + +struct mlk_alloc_pool pool; +struct point *point, *points; +size_t pointsz; +int x, y; + +mlk_alloc_pool_init(&pool, sizeof (*point), NULL); + +/* Assume fp is a FILE pointer allocated by the user. */ +while (fscanf(fp, "%d|%d\\n", &x, &y) == 2) { + /* + * Returned pointer can be used to fill the region but must not be + * permanently referenced as it can get invalidated in the next + * iteration. + */ + point = mlk_alloc_pool_new(&pool); + point->x = x; + point->y = y; +} + +/* + * Shrink the data into the appropriate array length. The pool can be safely + * discarded. + */ +pointsz = pool.size; +points = mlk_alloc_pool_shrink(&pool); + +for (size_t i = 0; i < pointsz; ++i) + point_draw(&points[i]); +.Ed +.Sh SEE ALSO +.Xr mlk-panic 3 +.Sh AUTHORS +The +.Nm +library was written by +.An David Demelier Aq Mt markand@malikania.fr .
--- a/tests/test-alloc.c Sun Oct 16 13:21:40 2022 +0200 +++ b/tests/test-alloc.c Mon Oct 17 14:22:07 2022 +0200 @@ -58,7 +58,7 @@ my_stats.free_count += 1; } -static const struct alloc_funcs my_funcs = { +static const struct mlk_alloc_funcs my_funcs = { .alloc = my_alloc, .realloc = my_realloc, .free = my_free @@ -69,7 +69,7 @@ { struct point *points; - DT_ASSERT((points = alloc_array0(2, sizeof (*points)))); + DT_ASSERT((points = mlk_alloc_array0(2, sizeof (*points)))); DT_EQ_INT(points[0].x, 0); DT_EQ_INT(points[0].y, 0); DT_EQ_INT(points[1].x, 0); @@ -80,7 +80,7 @@ points[1].x = 30; points[1].y = 40; - DT_ASSERT((points = alloc_rearray0(points, 2, 4, sizeof (*points)))); + DT_ASSERT((points = mlk_alloc_rearray0(points, 2, 4, sizeof (*points)))); DT_EQ_INT(points[0].x, 10); DT_EQ_INT(points[0].y, 20); DT_EQ_INT(points[1].x, 30); @@ -94,19 +94,19 @@ static void test_basics_pool_simple(void) { - struct alloc_pool pool; + struct mlk_alloc_pool pool; struct point *p, *data; size_t total = 0; - alloc_pool_init(&pool, sizeof (*p), NULL); + mlk_alloc_pool_init(&pool, sizeof (*p), NULL); DT_EQ_UINT(pool.elemsize, sizeof (*p)); DT_EQ_UINT(pool.size, 0); - DT_EQ_UINT(pool.capacity, ALLOC_POOL_INIT_DEFAULT); + DT_EQ_UINT(pool.capacity, MLK_ALLOC_POOL_INIT_DEFAULT); /* Create until we reach the capacity. */ for (size_t i = 0; i < pool.capacity; ++i) { - p = alloc_pool_new(&pool); + p = mlk_alloc_pool_new(&pool); p->x = (int)i + 1; p->y = (int)i + 1; total++; @@ -123,14 +123,14 @@ } /* Now it should reallocate. */ - p = alloc_pool_new(&pool); + p = mlk_alloc_pool_new(&pool); p->x = 9999; p->y = 9999; DT_ASSERT(pool.capacity > pool.size); /* Shrink it! */ - data = alloc_pool_shrink(&pool); + data = mlk_alloc_pool_shrink(&pool); /* Verify values are correct again. */ for (size_t i = 0; i < total; ++i) { @@ -147,7 +147,7 @@ static void test_basics_sdupf(void) { - char *str = alloc_sdupf("Hello %s", "David"); + char *str = mlk_alloc_sdupf("Hello %s", "David"); DT_EQ_STR(str, "Hello David"); free(str); @@ -156,10 +156,10 @@ static void test_custom_count(void) { - alloc_set(&my_funcs); - alloc_free(alloc_new(10)); - alloc_free(alloc_new0(20)); - alloc_free(alloc_sdup("malikania")); + mlk_alloc_set(&my_funcs); + mlk_alloc_free(mlk_alloc_new(10)); + mlk_alloc_free(mlk_alloc_new0(20)); + mlk_alloc_free(mlk_alloc_sdup("malikania")); DT_EQ_UINT(my_stats.total, 40U); DT_EQ_UINT(my_stats.alloc_count, 3U);