| 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, |