Fri, 23 May 2025 12:44:24 +0200
make test-compile depend on both static and shared
the shared lib is not needed for the tests,
but when run with coverage, gcov will be confused
when outdated line information is available from
a previous shared build
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * @file mempool.h * @brief Interface for memory pool implementations. * @author Mike Becker * @author Olaf Wintermann * @copyright 2-Clause BSD License */ #ifndef UCX_MEMPOOL_H #define UCX_MEMPOOL_H #include "common.h" #include "allocator.h" #ifdef __cplusplus extern "C" { #endif struct cx_mempool_memory_s { /** The destructor. */ cx_destructor_func destructor; /** The actual memory. */ char c[]; }; struct cx_mempool_memory2_s { /** The destructor. */ cx_destructor_func2 destructor; /** Data for the destructor. */ void *data; /** The actual memory. */ char c[]; }; struct cx_mempool_foreign_memory_s { /** The foreign memory. */ void* mem; union { /** Simple destructor. */ cx_destructor_func destr; /** Advanced destructor. */ cx_destructor_func2 destr2; }; /** Data for the advanced destructor. */ void *destr2_data; }; /** Specifies how individual blocks are allocated. */ enum cx_mempool_type { /** * Allows registration of cx_destructor_func for each memory block. */ CX_MEMPOOL_TYPE_SIMPLE, /** * Allows registration of cx_destructor_func2 for each memory block. */ CX_MEMPOOL_TYPE_ADVANCED, /** * No individual destructor registration allowed. * * In this mode, no additional memory per block is allocated. */ CX_MEMPOOL_TYPE_PURE, }; /** * The basic structure of a memory pool. * Should be the first member of an actual memory pool implementation. */ struct cx_mempool_s { /** The provided allocator. */ const CxAllocator *allocator; /** Array of pooled memory. */ void **data; /** Number of pooled memory items. */ size_t size; /** Memory pool capacity. */ size_t capacity; /** Array of registered memory. */ struct cx_mempool_foreign_memory_s *registered; /** Number of registered memory items. */ size_t registered_size; /** Capacity for registered memory. */ size_t registered_capacity; /** * A destructor that shall be called before deallocating a memory block. * This destructor MUST NOT free the memory itself. * * It is guaranteed that this destructor is called after the individual * destructor of the memory block and before @c destr2. */ cx_destructor_func destr; /** * A destructor that shall be called before deallocating a memory block. * This destructor MUST NOT free the memory itself. * * It is guaranteed that this destructor is called after the individual * destructor of the memory block and @c destr. */ cx_destructor_func2 destr2; /** * Additional data for the @c destr2. */ void *destr2_data; }; /** * Common type for all memory pool implementations. */ typedef struct cx_mempool_s CxMempool; /** * Deallocates a memory pool and frees the managed memory. * * @param pool the memory pool to free */ cx_attr_export void cxMempoolFree(CxMempool *pool); /** * Creates an array-based memory pool. * * The type determines how much additional memory is allocated per block * to register a destructor function. * * @param capacity the initial capacity of the pool (an implementation default if zero) * @param type the type of memory pool * @return the created memory pool or @c NULL if allocation failed */ cx_attr_nodiscard cx_attr_malloc cx_attr_dealloc(cxMempoolFree, 1) cx_attr_export CxMempool *cxMempoolCreate(size_t capacity, enum cx_mempool_type type); /** * Sets the global destructor for all memory blocks within the specified pool. * * @param pool the memory pool * @param fnc the destructor that shall be applied to all memory blocks */ cx_attr_nonnull_arg(1) cx_attr_export void cxMempoolGlobalDestructor(CxMempool *pool, cx_destructor_func fnc); /** * Sets the global destructor for all memory blocks within the specified pool. * * @param pool the memory pool * @param fnc the destructor that shall be applied to all memory blocks * @param data additional data for the destructor function */ cx_attr_nonnull_arg(1) cx_attr_export void cxMempoolGlobalDestructor2(CxMempool *pool, cx_destructor_func2 fnc, void *data); /** * Creates a basic array-based memory pool. * * @param capacity (@c size_t) the initial capacity of the pool * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed */ #define cxMempoolCreateSimple(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_SIMPLE) /** * Sets the destructor function for a specific allocated memory object. * * If the type of memory pool is not #CX_MEMPOOL_TYPE_SIMPLE, the behavior is undefined. * If the memory is not managed by a UCX memory pool, the behavior is undefined. * The destructor MUST NOT free the memory. * * @param memory the object allocated in the pool * @param fnc the destructor function */ cx_attr_nonnull cx_attr_export void cxMempoolSetDestructor( void *memory, cx_destructor_func fnc ); /** * Sets the destructor function for a specific allocated memory object. * * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined. * If the memory is not managed by a UCX memory pool, the behavior is undefined. * The destructor MUST NOT free the memory. * * @param memory the object allocated in the pool * @param fnc the destructor function * @param data additional data for the destructor function */ cx_attr_nonnull cx_attr_export void cxMempoolSetDestructor2( void *memory, cx_destructor_func2 fnc, void *data ); /** * Removes the destructor function for a specific allocated memory object. * * If the type of memory pool is not #CX_MEMPOOL_TYPE_SIMPLE, the behavior is undefined. * If the memory is not managed by a UCX memory pool, the behavior is undefined. * * @param memory the object allocated in the pool */ cx_attr_nonnull cx_attr_export void cxMempoolRemoveDestructor(void *memory); /** * Removes the destructor function for a specific allocated memory object. * * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined. * If the memory is not managed by a UCX memory pool, the behavior is undefined. * * @param memory the object allocated in the pool */ cx_attr_nonnull cx_attr_export void cxMempoolRemoveDestructor2(void *memory); /** * Registers foreign memory with this pool. * * The destructor, in contrast to memory allocated by the pool, MUST free the memory. * This function can be used with any pool of any type, since destructors for registered memory * are entirely independent of the pool's memory management. * * The destructor for the registered memory will be called after all pooled items have been freed. * * @param pool the pool * @param memory the object to register (MUST NOT be already allocated in the pool) * @param destr the destructor function * @retval zero success * @retval non-zero failure */ cx_attr_nonnull cx_attr_export int cxMempoolRegister( CxMempool *pool, void *memory, cx_destructor_func destr ); /** * Registers foreign memory with this pool. * * The destructor, in contrast to memory allocated by the pool, MUST free the memory. * This function can be used with any pool of any type, since destructors for registered memory * are entirely independent of the pool's memory management. * * The destructor for the registered memory will be called after all pooled items have been freed. * * @attention The data pointer MUST NOT be @c NULL. * If you wish to register a destructor without additional data, use cxMempoolRegister(). * * @param pool the pool * @param memory the object to register (MUST NOT be already allocated in the pool) * @param destr the destructor function * @param data additional data for the destructor function * @retval zero success * @retval non-zero failure */ cx_attr_nonnull cx_attr_export int cxMempoolRegister2( CxMempool *pool, void *memory, cx_destructor_func2 destr, void *data ); /** * Transfers all the memory managed by one pool to another. * * The allocator of the source pool will also be transferred and registered with the destination pool * and stays valid, as long as the destination pool is not destroyed. * * The source pool will get a completely new allocator and can be reused or destroyed afterward. * * This function fails when the destination pool has a different type than the source pool. * * @param source the pool to move the memory from * @param dest the pool where to transfer the memory to * @retval zero success * @retval non-zero allocation failure or incompatible pools */ cx_attr_nonnull cx_attr_export int cxMempoolTransfer( CxMempool *source, CxMempool *dest ); /** * Transfers an object from one pool to another. * * This function fails when the destination pool has a different type than the source pool. * * @attention If the object maintains a reference to the pool's allocator, * you must make sure to update that reference to the allocator of the destination pool. * * @param source the pool to move the memory from * @param dest the pool where to transfer the memory to * @param obj pointer to the object that shall be transferred * @retval zero success * @retval non-zero failure, or the object was not found in the source pool, or the pools are incompatible */ cx_attr_nonnull cx_attr_export int cxMempoolTransferObject( CxMempool *source, CxMempool *dest, const void *obj ); #ifdef __cplusplus } // extern "C" #endif #endif // UCX_MEMPOOL_H