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