ucx/cx/mempool.h

changeset 888
af685cc9d623
parent 854
1c8401ece69e
--- a/ucx/cx/mempool.h	Sun Aug 31 14:39:13 2025 +0200
+++ b/ucx/cx/mempool.h	Sat Nov 08 23:06:11 2025 +0100
@@ -43,31 +43,107 @@
 extern "C" {
 #endif
 
-/** Internal structure for pooled memory. */
-struct cx_mempool_memory_s;
+/** A memory block in a simple memory pool. */
+struct cx_mempool_memory_s {
+    /** The destructor. */
+    cx_destructor_func destructor;
+    /** The actual memory. */
+    char c[];
+};
+
+/** A memory block in an advanced memory pool. */
+struct cx_mempool_memory2_s {
+    /** The destructor. */
+    cx_destructor_func2 destructor;
+    /** Data for the destructor. */
+    void *data;
+    /** The actual memory. */
+    char c[];
+};
+
+/** Represents memory that is not allocated by, but registered with a pool. */
+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 used allocator, initialized with the cxDefaultAllocator. */
+    const CxAllocator * const base_allocator;
+
     /** The provided allocator. */
     const CxAllocator *allocator;
 
-    /**
-     * A destructor that shall be automatically registered for newly allocated memory.
-     * This destructor MUST NOT free the memory.
-     */
-    cx_destructor_func auto_destr;
-
     /** Array of pooled memory. */
-    struct cx_mempool_memory_s **data;
+    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;
 };
 
 /**
@@ -80,35 +156,74 @@
  *
  * @param pool the memory pool to free
  */
-cx_attr_export
-void cxMempoolFree(CxMempool *pool);
+CX_EXPORT void cxMempoolFree(CxMempool *pool);
 
 /**
- * Creates an array-based memory pool with a shared destructor function.
+ * Creates an array-based memory pool.
  *
- * This destructor MUST NOT free the memory.
+ * The type determines how much additional memory is allocated per block
+ * to register a destructor function.
  *
- * @param capacity the initial capacity of the pool
- * @param destr optional destructor function to use for allocated memory
+ * @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, cx_destructor_func destr);
+cx_attr_nodiscard cx_attr_malloc cx_attr_dealloc(cxMempoolFree, 1)
+CX_EXPORT CxMempool *cxMempoolCreate(size_t capacity, enum cx_mempool_type type);
+
+/**
+ * Creates a basic array-based memory pool.
+ *
+ * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_SIMPLE.
+ *
+ * @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)
 
 /**
  * Creates a basic array-based memory pool.
  *
+ * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_ADVANCED.
+ *
+ * @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 cxMempoolCreateAdvanced(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_ADVANCED)
+
+/**
+ * Creates a basic array-based memory pool.
+ *
+ * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_PURE.
+ *
  * @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, NULL)
+#define cxMempoolCreatePure(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_PURE)
+
+/**
+ * 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_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_EXPORT void cxMempoolGlobalDestructor2(CxMempool *pool, cx_destructor_func2 fnc, void *data);
 
 /**
  * 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.
  *
@@ -116,31 +231,52 @@
  * @param fnc the destructor function
  */
 cx_attr_nonnull
-cx_attr_export
-void cxMempoolSetDestructor(
-        void *memory,
-        cx_destructor_func fnc
-);
+CX_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_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.
- * The destructor MUST NOT free the memory.
  *
  * @param memory the object allocated in the pool
  */
 cx_attr_nonnull
-cx_attr_export
-void cxMempoolRemoveDestructor(void *memory);
+CX_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_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.
  *
- * A small portion of memory will be allocated to register the information in the pool.
- * If that allocation fails, this function will return non-zero.
+ * 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)
@@ -149,12 +285,65 @@
  * @retval non-zero failure
  */
 cx_attr_nonnull
-cx_attr_export
-int cxMempoolRegister(
-        CxMempool *pool,
-        void *memory,
-        cx_destructor_func destr
-);
+CX_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_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_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_EXPORT int cxMempoolTransferObject(CxMempool *source, CxMempool *dest, const void *obj);
 
 #ifdef __cplusplus
 } // extern "C"

mercurial