view man/mlk-alloc.3 @ 438:25a56ca53ac2

core: update mlk-alloc module
author David Demelier <markand@malikania.fr>
date Mon, 17 Oct 2022 14:22:07 +0200
parents
children 9c3b3935f0aa
line wrap: on
line source

.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 .