| 41 | 41 | 
| 42 #ifdef __cplusplus | 42 #ifdef __cplusplus | 
| 43 extern "C" { | 43 extern "C" { | 
| 44 #endif | 44 #endif | 
| 45 | 45 | 
| 46 /** Internal structure for pooled memory. */ | 46 struct cx_mempool_memory_s { | 
| 47 struct cx_mempool_memory_s; | 47     /** The destructor. */ | 
|  | 48     cx_destructor_func destructor; | 
|  | 49     /** The actual memory. */ | 
|  | 50     char c[]; | 
|  | 51 }; | 
|  | 52 | 
|  | 53 struct cx_mempool_memory2_s { | 
|  | 54     /** The destructor. */ | 
|  | 55     cx_destructor_func2 destructor; | 
|  | 56     /** Data for the destructor. */ | 
|  | 57     void *data; | 
|  | 58     /** The actual memory. */ | 
|  | 59     char c[]; | 
|  | 60 }; | 
|  | 61 | 
|  | 62 struct cx_mempool_foreign_memory_s { | 
|  | 63     /** The foreign memory. */ | 
|  | 64     void* mem; | 
|  | 65     union { | 
|  | 66         /** Simple destructor. */ | 
|  | 67         cx_destructor_func destr; | 
|  | 68         /** Advanced destructor. */ | 
|  | 69         cx_destructor_func2 destr2; | 
|  | 70     }; | 
|  | 71     /** Data for the advanced destructor. */ | 
|  | 72     void *destr2_data; | 
|  | 73 }; | 
|  | 74 | 
|  | 75 /** Specifies how individual blocks are allocated. */ | 
|  | 76 enum cx_mempool_type { | 
|  | 77     /** | 
|  | 78      * Allows registration of cx_destructor_func for each memory block. | 
|  | 79      */ | 
|  | 80     CX_MEMPOOL_TYPE_SIMPLE, | 
|  | 81     /** | 
|  | 82      * Allows registration of cx_destructor_func2 for each memory block. | 
|  | 83      */ | 
|  | 84     CX_MEMPOOL_TYPE_ADVANCED, | 
|  | 85     /** | 
|  | 86      * No individual destructor registration allowed. | 
|  | 87      * | 
|  | 88      * In this mode, no additional memory per block is allocated. | 
|  | 89      */ | 
|  | 90     CX_MEMPOOL_TYPE_PURE, | 
|  | 91 }; | 
| 48 | 92 | 
| 49 /** | 93 /** | 
| 50  * The basic structure of a memory pool. | 94  * The basic structure of a memory pool. | 
| 51  * Should be the first member of an actual memory pool implementation. | 95  * Should be the first member of an actual memory pool implementation. | 
| 52  */ | 96  */ | 
| 53 struct cx_mempool_s { | 97 struct cx_mempool_s { | 
| 54     /** The provided allocator. */ | 98     /** The provided allocator. */ | 
| 55     const CxAllocator *allocator; | 99     const CxAllocator *allocator; | 
| 56 | 100 | 
| 57     /** |  | 
| 58      * A destructor that shall be automatically registered for newly allocated memory. |  | 
| 59      * This destructor MUST NOT free the memory. |  | 
| 60      */ |  | 
| 61     cx_destructor_func auto_destr; |  | 
| 62 |  | 
| 63     /** Array of pooled memory. */ | 101     /** Array of pooled memory. */ | 
| 64     struct cx_mempool_memory_s **data; | 102     void **data; | 
| 65 | 103 | 
| 66     /** Number of pooled memory items. */ | 104     /** Number of pooled memory items. */ | 
| 67     size_t size; | 105     size_t size; | 
| 68 | 106 | 
| 69     /** Memory pool capacity. */ | 107     /** Memory pool capacity. */ | 
| 70     size_t capacity; | 108     size_t capacity; | 
|  | 109 | 
|  | 110     /** Array of registered memory. */ | 
|  | 111     struct cx_mempool_foreign_memory_s *registered; | 
|  | 112 | 
|  | 113     /** Number of registered memory items. */ | 
|  | 114     size_t registered_size; | 
|  | 115 | 
|  | 116     /** Capacity for registered memory. */ | 
|  | 117     size_t registered_capacity; | 
|  | 118 | 
|  | 119     /** | 
|  | 120      * A destructor that shall be called before deallocating a memory block. | 
|  | 121      * This destructor MUST NOT free the memory itself. | 
|  | 122      * | 
|  | 123      * It is guaranteed that this destructor is called after the individual | 
|  | 124      * destructor of the memory block and before @c destr2. | 
|  | 125      */ | 
|  | 126     cx_destructor_func destr; | 
|  | 127 | 
|  | 128     /** | 
|  | 129      * A destructor that shall be called before deallocating a memory block. | 
|  | 130      * This destructor MUST NOT free the memory itself. | 
|  | 131      * | 
|  | 132     * It is guaranteed that this destructor is called after the individual | 
|  | 133      * destructor of the memory block and @c destr. | 
|  | 134      */ | 
|  | 135     cx_destructor_func2 destr2; | 
|  | 136 | 
|  | 137     /** | 
|  | 138      * Additional data for the @c destr2. | 
|  | 139      */ | 
|  | 140     void *destr2_data; | 
| 71 }; | 141 }; | 
| 72 | 142 | 
| 73 /** | 143 /** | 
| 74  * Common type for all memory pool implementations. | 144  * Common type for all memory pool implementations. | 
| 75  */ | 145  */ | 
| 82  */ | 152  */ | 
| 83 cx_attr_export | 153 cx_attr_export | 
| 84 void cxMempoolFree(CxMempool *pool); | 154 void cxMempoolFree(CxMempool *pool); | 
| 85 | 155 | 
| 86 /** | 156 /** | 
| 87  * Creates an array-based memory pool with a shared destructor function. | 157  * Creates an array-based memory pool. | 
| 88  * | 158  * | 
| 89  * This destructor MUST NOT free the memory. | 159  * The type determines how much additional memory is allocated per block | 
| 90  * | 160  * to register a destructor function. | 
| 91  * @param capacity the initial capacity of the pool | 161  * | 
| 92  * @param destr optional destructor function to use for allocated memory | 162  * @param capacity the initial capacity of the pool (an implementation default if zero) | 
|  | 163  * @param type the type of memory pool | 
| 93  * @return the created memory pool or @c NULL if allocation failed | 164  * @return the created memory pool or @c NULL if allocation failed | 
| 94  */ | 165  */ | 
| 95 cx_attr_nodiscard | 166 cx_attr_nodiscard | 
| 96 cx_attr_malloc | 167 cx_attr_malloc | 
| 97 cx_attr_dealloc(cxMempoolFree, 1) | 168 cx_attr_dealloc(cxMempoolFree, 1) | 
| 98 cx_attr_export | 169 cx_attr_export | 
| 99 CxMempool *cxMempoolCreate(size_t capacity, cx_destructor_func destr); | 170 CxMempool *cxMempoolCreate(size_t capacity, enum cx_mempool_type type); | 
|  | 171 | 
|  | 172 /** | 
|  | 173  * Sets the global destructor for all memory blocks within the specified pool. | 
|  | 174  * | 
|  | 175  * @param pool (@c CxMempool*) the memory pool | 
|  | 176  * @param fnc (@c cx_destructor_func) the destructor that shall be applied to all memory blocks | 
|  | 177  */ | 
|  | 178 #define cxMempoolGlobalDestructor(pool, fnc) \ | 
|  | 179     (pool)->destr = (cx_destructor_func)(fnc) | 
|  | 180 | 
|  | 181 /** | 
|  | 182  * Sets the global destructor for all memory blocks within the specified pool. | 
|  | 183  * | 
|  | 184  * @param pool (@c CxMempool*) the memory pool | 
|  | 185  * @param fnc (@c cx_destructor_func2) the destructor that shall be applied to all memory blocks | 
|  | 186  * @param data (@c void*) additional data for the destructor function | 
|  | 187  */ | 
|  | 188 #define cxMempoolGlobalDestructor2(pool, fnc, data) \ | 
|  | 189     (pool)->destr2 = (cx_destructor_func2)(fnc); (pool)->destr2_data = (data) | 
| 100 | 190 | 
| 101 /** | 191 /** | 
| 102  * Creates a basic array-based memory pool. | 192  * Creates a basic array-based memory pool. | 
| 103  * | 193  * | 
| 104  * @param capacity (@c size_t) the initial capacity of the pool | 194  * @param capacity (@c size_t) the initial capacity of the pool | 
| 105  * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed | 195  * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed | 
| 106  */ | 196  */ | 
| 107 #define cxMempoolCreateSimple(capacity) cxMempoolCreate(capacity, NULL) | 197 #define cxMempoolCreateSimple(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_SIMPLE) | 
| 108 | 198 | 
| 109 /** | 199 /** | 
| 110  * Sets the destructor function for a specific allocated memory object. | 200  * Sets the destructor function for a specific allocated memory object. | 
| 111  * | 201  * | 
|  | 202  * If the type of memory pool is not #CX_MEMPOOL_TYPE_SIMPLE, the behavior is undefined. | 
| 112  * If the memory is not managed by a UCX memory pool, the behavior is undefined. | 203  * If the memory is not managed by a UCX memory pool, the behavior is undefined. | 
| 113  * The destructor MUST NOT free the memory. | 204  * The destructor MUST NOT free the memory. | 
| 114  * | 205  * | 
| 115  * @param memory the object allocated in the pool | 206  * @param memory the object allocated in the pool | 
| 116  * @param fnc the destructor function | 207  * @param fnc the destructor function | 
| 121         void *memory, | 212         void *memory, | 
| 122         cx_destructor_func fnc | 213         cx_destructor_func fnc | 
| 123 ); | 214 ); | 
| 124 | 215 | 
| 125 /** | 216 /** | 
| 126  * Removes the destructor function for a specific allocated memory object. | 217  * Sets the destructor function for a specific allocated memory object. | 
| 127  * | 218  * | 
|  | 219  * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined. | 
| 128  * If the memory is not managed by a UCX memory pool, the behavior is undefined. | 220  * If the memory is not managed by a UCX memory pool, the behavior is undefined. | 
| 129  * The destructor MUST NOT free the memory. | 221  * The destructor MUST NOT free the memory. | 
| 130  * | 222  * | 
| 131  * @param memory the object allocated in the pool | 223  * @param memory the object allocated in the pool | 
|  | 224  * @param fnc the destructor function | 
|  | 225  * @param data additional data for the destructor function | 
|  | 226  */ | 
|  | 227 cx_attr_nonnull | 
|  | 228 cx_attr_export | 
|  | 229 void cxMempoolSetDestructor2( | 
|  | 230         void *memory, | 
|  | 231         cx_destructor_func2 fnc, | 
|  | 232         void *data | 
|  | 233 ); | 
|  | 234 | 
|  | 235 /** | 
|  | 236  * Removes the destructor function for a specific allocated memory object. | 
|  | 237  * | 
|  | 238  * If the type of memory pool is not #CX_MEMPOOL_TYPE_SIMPLE, the behavior is undefined. | 
|  | 239  * If the memory is not managed by a UCX memory pool, the behavior is undefined. | 
|  | 240  * | 
|  | 241  * @param memory the object allocated in the pool | 
| 132  */ | 242  */ | 
| 133 cx_attr_nonnull | 243 cx_attr_nonnull | 
| 134 cx_attr_export | 244 cx_attr_export | 
| 135 void cxMempoolRemoveDestructor(void *memory); | 245 void cxMempoolRemoveDestructor(void *memory); | 
| 136 | 246 | 
| 137 /** | 247 /** | 
|  | 248  * Removes the destructor function for a specific allocated memory object. | 
|  | 249  * | 
|  | 250  * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined. | 
|  | 251  * If the memory is not managed by a UCX memory pool, the behavior is undefined. | 
|  | 252  * | 
|  | 253  * @param memory the object allocated in the pool | 
|  | 254  */ | 
|  | 255 cx_attr_nonnull | 
|  | 256 cx_attr_export | 
|  | 257 void cxMempoolRemoveDestructor2(void *memory); | 
|  | 258 | 
|  | 259 /** | 
| 138  * Registers foreign memory with this pool. | 260  * Registers foreign memory with this pool. | 
| 139  * | 261  * | 
| 140  * The destructor, in contrast to memory allocated by the pool, MUST free the memory. | 262  * The destructor, in contrast to memory allocated by the pool, MUST free the memory. | 
| 141  * | 263  * This function can be used with any pool of any type, since destructors for registered memory | 
| 142  * A small portion of memory will be allocated to register the information in the pool. | 264  * are entirely independent of the pool's memory management. | 
| 143  * If that allocation fails, this function will return non-zero. | 265  * | 
|  | 266  * The destructor for the registered memory will be called after all pooled items have been freed. | 
| 144  * | 267  * | 
| 145  * @param pool the pool | 268  * @param pool the pool | 
| 146  * @param memory the object to register (MUST NOT be already allocated in the pool) | 269  * @param memory the object to register (MUST NOT be already allocated in the pool) | 
| 147  * @param destr the destructor function | 270  * @param destr the destructor function | 
| 148  * @retval zero success | 271  * @retval zero success | 
| 154         CxMempool *pool, | 277         CxMempool *pool, | 
| 155         void *memory, | 278         void *memory, | 
| 156         cx_destructor_func destr | 279         cx_destructor_func destr | 
| 157 ); | 280 ); | 
| 158 | 281 | 
|  | 282 | 
|  | 283 /** | 
|  | 284  * Registers foreign memory with this pool. | 
|  | 285  * | 
|  | 286  * The destructor, in contrast to memory allocated by the pool, MUST free the memory. | 
|  | 287  * This function can be used with any pool of any type, since destructors for registered memory | 
|  | 288  * are entirely independent of the pool's memory management. | 
|  | 289  * | 
|  | 290  * The destructor for the registered memory will be called after all pooled items have been freed. | 
|  | 291  * | 
|  | 292  * @attention The data pointer MUST NOT be @c NULL. | 
|  | 293  * If you wish to register a destructor without additional data, use cxMempoolRegister(). | 
|  | 294  * | 
|  | 295  * @param pool the pool | 
|  | 296  * @param memory the object to register (MUST NOT be already allocated in the pool) | 
|  | 297  * @param destr the destructor function | 
|  | 298  * @param data additional data for the destructor function | 
|  | 299  * @retval zero success | 
|  | 300  * @retval non-zero failure | 
|  | 301  */ | 
|  | 302 cx_attr_nonnull | 
|  | 303 cx_attr_export | 
|  | 304 int cxMempoolRegister2( | 
|  | 305         CxMempool *pool, | 
|  | 306         void *memory, | 
|  | 307         cx_destructor_func2 destr, | 
|  | 308         void *data | 
|  | 309 ); | 
|  | 310 | 
| 159 /** | 311 /** | 
| 160  * Transfers all the memory managed by one pool to another. | 312  * Transfers all the memory managed by one pool to another. | 
| 161  * | 313  * | 
| 162  * The allocator of the source pool will also be transferred and registered with the destination pool | 314  * The allocator of the source pool will also be transferred and registered with the destination pool | 
| 163  * and stays valid, as long as the destination pool is not destroyed. | 315  * and stays valid, as long as the destination pool is not destroyed. | 
| 164  * | 316  * | 
| 165  * The source pool will get a completely new allocator and can be reused or destroyed afterward. | 317  * The source pool will get a completely new allocator and can be reused or destroyed afterward. | 
|  | 318  * | 
|  | 319  * This function fails when the destination pool has a different type than the source pool. | 
| 166  * | 320  * | 
| 167  * @param source the pool to move the memory from | 321  * @param source the pool to move the memory from | 
| 168  * @param dest the pool where to transfer the memory to | 322  * @param dest the pool where to transfer the memory to | 
| 169  * @retval zero success | 323  * @retval zero success | 
| 170  * @retval non-zero failure | 324  * @retval non-zero allocation failure or incompatible pools | 
| 171  */ | 325  */ | 
| 172 cx_attr_nonnull | 326 cx_attr_nonnull | 
| 173 cx_attr_export | 327 cx_attr_export | 
| 174 int cxMempoolTransfer( | 328 int cxMempoolTransfer( | 
| 175         CxMempool *source, | 329         CxMempool *source, | 
| 177 ); | 331 ); | 
| 178 | 332 | 
| 179 /** | 333 /** | 
| 180  * Transfers an object from one pool to another. | 334  * Transfers an object from one pool to another. | 
| 181  * | 335  * | 
| 182  * You can only transfer objects that have been allocated by this pool. | 336  * This function fails when the destination pool has a different type than the source pool. | 
| 183  * Objects that have been registered with cxMempoolRegister() cannot be transferred this way. |  | 
| 184  * | 337  * | 
| 185  * @attention If the object maintains a reference to the pool's allocator, | 338  * @attention If the object maintains a reference to the pool's allocator, | 
| 186  * you must make sure to update that reference to the allocator of the destination pool. | 339  * you must make sure to update that reference to the allocator of the destination pool. | 
| 187  * | 340  * | 
| 188  * @param source the pool to move the memory from | 341  * @param source the pool to move the memory from | 
| 189  * @param dest the pool where to transfer the memory to | 342  * @param dest the pool where to transfer the memory to | 
| 190  * @param obj pointer to the object that shall be transferred | 343  * @param obj pointer to the object that shall be transferred | 
| 191  * @retval zero success | 344  * @retval zero success | 
| 192  * @retval non-zero failure or object was not found in the source pool | 345  * @retval non-zero failure, or the object was not found in the source pool, or the pools are incompatible | 
| 193  */ | 346  */ | 
| 194 cx_attr_nonnull | 347 cx_attr_nonnull | 
| 195 cx_attr_export | 348 cx_attr_export | 
| 196 int cxMempoolTransferObject( | 349 int cxMempoolTransferObject( | 
| 197         CxMempool *source, | 350         CxMempool *source, |