Sat, 08 Feb 2025 14:13:59 +0100
add documentation for allocator.h
relates to #451
# Allocator The allocator interface provides a mechanism to implement own custom allocators that can also be used in many other function in UCX. A default allocator implementation using the stdlib functions is available via the global symbol `cxDefaultAllocator` and UCX also provides a [memory pool](mempool.h.md) implementation. You are free to add additional own custom implementations. A general sketch that illustrates how to do this can be found [below](#custom-allocator). ## Overview ```C void *cxMalloc(const CxAllocator *allocator, size_t n); void *cxCalloc(const CxAllocator *allocator, size_t nmemb, size_t size); void *cxRealloc(const CxAllocator *allocator, void *mem, size_t n); void *cxReallocArray(const CxAllocator *allocator, void *mem, size_t nmemb, size_t size); int cxReallocate(const CxAllocator *allocator, void **mem, size_t n); int cxReallocateArray(const CxAllocator *allocator, void **mem, size_t nmemb, size_t size); void cxFree(const CxAllocator *allocator, void *mem); int cx_reallocate(void **mem, size_t size); int cx_reallocatearray(void **mem, size_t nmemb, size_t size); // predefined allocator that uses stdlib functions CxAllocator *cxDefaultAllocator; ``` > All UCX functions that are not _explicitly_ designed for taking an allocator argument > (recognizable by a `_a` suffix in the function's name) do support a `NULL` argument > in which case the `cxDefaultAllocator` will be used. ## Description The functions `cxMalloc()`, `cxCalloc()`, `cxRealloc()`, `cxReallocArray()`, and `cxFree()` invoke the memory management functions specified in the `allocator` and should behave like their respective stdlibc pendants. Implementations of the allocator interface are strongly encouraged to guarantee this behavior, most prominently that invocations of `cxFree()` with a `NULL`-pointer for `mem` are ignored instead of causing segfault error. Additionally, UCX provides the functions `cxReallocate()` and `cxReallocateArray()`, as well as their independent pendants `cx_reallocate()` and `cx_reallocatearray()`. All those functions solve the problem that a possible reallocation might fail, leading to a quite common programming mistake: ```C // common mistake - mem will be lost hen realloc() returns NULL mem = realloc(mem, capacity + 32); if (mem == NULL) // ... do error handling ``` The above code can be replaced with `cx_reallocate()` which keeps the pointer intact and returns an error code instead. ```C // when cx_reallocate() fails, mem will still point to the old memory if (cx_reallocate(&mem, capacity + 32)) // ... do error handling ``` > Please pay special attention to always use `cxFree()` and the `cxRealloc()`-family of functions > with the **same** allocator that was used to allocate the memory. {style="warning"} ## Custom Allocator If you want to define your own allocator, you need to initialize the `CxAllocator` structure with a pointer to an allocator class (containing function pointers for the memory management functions) and an optional pointer to custom data. An example is shown below: ```c struct my_allocator_state { // ... some internal state ... }; static cx_allocator_class my_allocator_class = { my_malloc_impl, my_realloc_impl, // all these functions are somewhere defined my_calloc_impl, my_free_impl }; CxAllocator create_my_allocator(void) { CxAllocator alloc; alloc.cl = &my_allocator_class; struct my_allocator_state *state = malloc(sizeof(*state)); // ... initialize state ... alloc.data = state; return alloc; } void destroy_my_allocator(CxAllocator *al) { struct my_allocator_state *state = al->state; // ... destroy state -- free(state); } ``` <seealso> <category ref="apidoc"> <a href="https://ucx.sourceforge.io/api/allocator_8h.html">allocator.h</a> </category> </seealso>