| 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 */ |
| 78 /** |
154 /** |
| 79 * Deallocates a memory pool and frees the managed memory. |
155 * Deallocates a memory pool and frees the managed memory. |
| 80 * |
156 * |
| 81 * @param pool the memory pool to free |
157 * @param pool the memory pool to free |
| 82 */ |
158 */ |
| 83 cx_attr_export |
159 CX_EXPORT void cxMempoolFree(CxMempool *pool); |
| 84 void cxMempoolFree(CxMempool *pool); |
160 |
| 85 |
161 /** |
| 86 /** |
162 * Creates an array-based memory pool. |
| 87 * Creates an array-based memory pool with a shared destructor function. |
163 * |
| 88 * |
164 * The type determines how much additional memory is allocated per block |
| 89 * This destructor MUST NOT free the memory. |
165 * to register a destructor function. |
| 90 * |
166 * |
| 91 * @param capacity the initial capacity of the pool |
167 * @param capacity the initial capacity of the pool (an implementation default if zero) |
| 92 * @param destr optional destructor function to use for allocated memory |
168 * @param type the type of memory pool |
| 93 * @return the created memory pool or @c NULL if allocation failed |
169 * @return the created memory pool or @c NULL if allocation failed |
| 94 */ |
170 */ |
| 95 cx_attr_nodiscard |
171 cx_attr_nodiscard cx_attr_malloc cx_attr_dealloc(cxMempoolFree, 1) |
| 96 cx_attr_malloc |
172 CX_EXPORT CxMempool *cxMempoolCreate(size_t capacity, enum cx_mempool_type type); |
| 97 cx_attr_dealloc(cxMempoolFree, 1) |
|
| 98 cx_attr_export |
|
| 99 CxMempool *cxMempoolCreate(size_t capacity, cx_destructor_func destr); |
|
| 100 |
173 |
| 101 /** |
174 /** |
| 102 * Creates a basic array-based memory pool. |
175 * Creates a basic array-based memory pool. |
| |
176 * |
| |
177 * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_SIMPLE. |
| 103 * |
178 * |
| 104 * @param capacity (@c size_t) the initial capacity of the pool |
179 * @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 |
180 * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed |
| 106 */ |
181 */ |
| 107 #define cxMempoolCreateSimple(capacity) cxMempoolCreate(capacity, NULL) |
182 #define cxMempoolCreateSimple(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_SIMPLE) |
| |
183 |
| |
184 /** |
| |
185 * Creates a basic array-based memory pool. |
| |
186 * |
| |
187 * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_ADVANCED. |
| |
188 * |
| |
189 * @param capacity (@c size_t) the initial capacity of the pool |
| |
190 * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed |
| |
191 */ |
| |
192 #define cxMempoolCreateAdvanced(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_ADVANCED) |
| |
193 |
| |
194 /** |
| |
195 * Creates a basic array-based memory pool. |
| |
196 * |
| |
197 * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_PURE. |
| |
198 * |
| |
199 * @param capacity (@c size_t) the initial capacity of the pool |
| |
200 * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed |
| |
201 */ |
| |
202 #define cxMempoolCreatePure(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_PURE) |
| |
203 |
| |
204 /** |
| |
205 * Sets the global destructor for all memory blocks within the specified pool. |
| |
206 * |
| |
207 * @param pool the memory pool |
| |
208 * @param fnc the destructor that shall be applied to all memory blocks |
| |
209 */ |
| |
210 cx_attr_nonnull_arg(1) |
| |
211 CX_EXPORT void cxMempoolGlobalDestructor(CxMempool *pool, cx_destructor_func fnc); |
| |
212 |
| |
213 /** |
| |
214 * Sets the global destructor for all memory blocks within the specified pool. |
| |
215 * |
| |
216 * @param pool the memory pool |
| |
217 * @param fnc the destructor that shall be applied to all memory blocks |
| |
218 * @param data additional data for the destructor function |
| |
219 */ |
| |
220 cx_attr_nonnull_arg(1) |
| |
221 CX_EXPORT void cxMempoolGlobalDestructor2(CxMempool *pool, cx_destructor_func2 fnc, void *data); |
| 108 |
222 |
| 109 /** |
223 /** |
| 110 * Sets the destructor function for a specific allocated memory object. |
224 * Sets the destructor function for a specific allocated memory object. |
| 111 * |
225 * |
| |
226 * 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. |
227 * If the memory is not managed by a UCX memory pool, the behavior is undefined. |
| 113 * The destructor MUST NOT free the memory. |
228 * The destructor MUST NOT free the memory. |
| 114 * |
229 * |
| 115 * @param memory the object allocated in the pool |
230 * @param memory the object allocated in the pool |
| 116 * @param fnc the destructor function |
231 * @param fnc the destructor function |
| 117 */ |
232 */ |
| 118 cx_attr_nonnull |
233 cx_attr_nonnull |
| 119 cx_attr_export |
234 CX_EXPORT void cxMempoolSetDestructor(void *memory, cx_destructor_func fnc); |
| 120 void cxMempoolSetDestructor( |
235 |
| 121 void *memory, |
236 /** |
| 122 cx_destructor_func fnc |
237 * Sets the destructor function for a specific allocated memory object. |
| 123 ); |
238 * |
| 124 |
239 * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined. |
| 125 /** |
|
| 126 * Removes the destructor function for a specific allocated memory object. |
|
| 127 * |
|
| 128 * If the memory is not managed by a UCX memory pool, the behavior is undefined. |
240 * If the memory is not managed by a UCX memory pool, the behavior is undefined. |
| 129 * The destructor MUST NOT free the memory. |
241 * The destructor MUST NOT free the memory. |
| 130 * |
242 * |
| 131 * @param memory the object allocated in the pool |
243 * @param memory the object allocated in the pool |
| 132 */ |
244 * @param fnc the destructor function |
| 133 cx_attr_nonnull |
245 * @param data additional data for the destructor function |
| 134 cx_attr_export |
246 */ |
| 135 void cxMempoolRemoveDestructor(void *memory); |
247 cx_attr_nonnull |
| |
248 CX_EXPORT void cxMempoolSetDestructor2(void *memory, cx_destructor_func2 fnc, void *data); |
| |
249 |
| |
250 /** |
| |
251 * Removes the destructor function for a specific allocated memory object. |
| |
252 * |
| |
253 * If the type of memory pool is not #CX_MEMPOOL_TYPE_SIMPLE, the behavior is undefined. |
| |
254 * If the memory is not managed by a UCX memory pool, the behavior is undefined. |
| |
255 * |
| |
256 * @param memory the object allocated in the pool |
| |
257 */ |
| |
258 cx_attr_nonnull |
| |
259 CX_EXPORT void cxMempoolRemoveDestructor(void *memory); |
| |
260 |
| |
261 /** |
| |
262 * Removes the destructor function for a specific allocated memory object. |
| |
263 * |
| |
264 * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined. |
| |
265 * If the memory is not managed by a UCX memory pool, the behavior is undefined. |
| |
266 * |
| |
267 * @param memory the object allocated in the pool |
| |
268 */ |
| |
269 cx_attr_nonnull |
| |
270 CX_EXPORT void cxMempoolRemoveDestructor2(void *memory); |
| 136 |
271 |
| 137 /** |
272 /** |
| 138 * Registers foreign memory with this pool. |
273 * Registers foreign memory with this pool. |
| 139 * |
274 * |
| 140 * The destructor, in contrast to memory allocated by the pool, MUST free the memory. |
275 * The destructor, in contrast to memory allocated by the pool, MUST free the memory. |
| 141 * |
276 * 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. |
277 * are entirely independent of the pool's memory management. |
| 143 * If that allocation fails, this function will return non-zero. |
278 * |
| |
279 * The destructor for the registered memory will be called after all pooled items have been freed. |
| 144 * |
280 * |
| 145 * @param pool the pool |
281 * @param pool the pool |
| 146 * @param memory the object to register (MUST NOT be already allocated in the pool) |
282 * @param memory the object to register (MUST NOT be already allocated in the pool) |
| 147 * @param destr the destructor function |
283 * @param destr the destructor function |
| 148 * @retval zero success |
284 * @retval zero success |
| 149 * @retval non-zero failure |
285 * @retval non-zero failure |
| 150 */ |
286 */ |
| 151 cx_attr_nonnull |
287 cx_attr_nonnull |
| 152 cx_attr_export |
288 CX_EXPORT int cxMempoolRegister(CxMempool *pool, void *memory, cx_destructor_func destr); |
| 153 int cxMempoolRegister( |
289 |
| 154 CxMempool *pool, |
290 |
| 155 void *memory, |
291 /** |
| 156 cx_destructor_func destr |
292 * Registers foreign memory with this pool. |
| 157 ); |
293 * |
| |
294 * The destructor, in contrast to memory allocated by the pool, MUST free the memory. |
| |
295 * This function can be used with any pool of any type, since destructors for registered memory |
| |
296 * are entirely independent of the pool's memory management. |
| |
297 * |
| |
298 * The destructor for the registered memory will be called after all pooled items have been freed. |
| |
299 * |
| |
300 * @attention The data pointer MUST NOT be @c NULL. |
| |
301 * If you wish to register a destructor without additional data, use cxMempoolRegister(). |
| |
302 * |
| |
303 * @param pool the pool |
| |
304 * @param memory the object to register (MUST NOT be already allocated in the pool) |
| |
305 * @param destr the destructor function |
| |
306 * @param data additional data for the destructor function |
| |
307 * @retval zero success |
| |
308 * @retval non-zero failure |
| |
309 */ |
| |
310 cx_attr_nonnull |
| |
311 CX_EXPORT int cxMempoolRegister2(CxMempool *pool, void *memory, cx_destructor_func2 destr, void *data); |
| |
312 |
| |
313 /** |
| |
314 * Transfers all the memory managed by one pool to another. |
| |
315 * |
| |
316 * The allocator of the source pool will also be transferred and registered with the destination pool |
| |
317 * and stays valid, as long as the destination pool is not destroyed. |
| |
318 * |
| |
319 * The source pool will get a completely new allocator and can be reused or destroyed afterward. |
| |
320 * |
| |
321 * This function fails when the destination pool has a different type than the source pool. |
| |
322 * |
| |
323 * @param source the pool to move the memory from |
| |
324 * @param dest the pool where to transfer the memory to |
| |
325 * @retval zero success |
| |
326 * @retval non-zero allocation failure or incompatible pools |
| |
327 */ |
| |
328 cx_attr_nonnull |
| |
329 CX_EXPORT int cxMempoolTransfer(CxMempool *source, CxMempool *dest); |
| |
330 |
| |
331 /** |
| |
332 * Transfers an object from one pool to another. |
| |
333 * |
| |
334 * This function fails when the destination pool has a different type than the source pool. |
| |
335 * |
| |
336 * @attention If the object maintains a reference to the pool's allocator, |
| |
337 * you must make sure to update that reference to the allocator of the destination pool. |
| |
338 * |
| |
339 * @param source the pool to move the memory from |
| |
340 * @param dest the pool where to transfer the memory to |
| |
341 * @param obj pointer to the object that shall be transferred |
| |
342 * @retval zero success |
| |
343 * @retval non-zero failure, or the object was not found in the source pool, or the pools are incompatible |
| |
344 */ |
| |
345 cx_attr_nonnull |
| |
346 CX_EXPORT int cxMempoolTransferObject(CxMempool *source, CxMempool *dest, const void *obj); |
| 158 |
347 |
| 159 #ifdef __cplusplus |
348 #ifdef __cplusplus |
| 160 } // extern "C" |
349 } // extern "C" |
| 161 #endif |
350 #endif |
| 162 |
351 |