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