37 ) { |
37 ) { |
38 if (needed_capacity <= pool->capacity) return 0; |
38 if (needed_capacity <= pool->capacity) return 0; |
39 size_t newcap = pool->capacity >= 1000 ? |
39 size_t newcap = pool->capacity >= 1000 ? |
40 pool->capacity + 1000 : pool->capacity * 2; |
40 pool->capacity + 1000 : pool->capacity * 2; |
41 size_t newmsize; |
41 size_t newmsize; |
|
42 // LCOV_EXCL_START |
42 if (pool->capacity > newcap |
43 if (pool->capacity > newcap |
43 || cx_szmul(newcap, sizeof(void*), &newmsize)) { |
44 || cx_szmul(newcap, sizeof(void*), &newmsize)) { |
44 errno = EOVERFLOW; |
45 errno = EOVERFLOW; |
45 return 1; |
46 return 1; |
46 } |
47 } // LCOV_EXCL_STOP |
47 void **newdata = cxReallocDefault(pool->data, newmsize); |
48 void **newdata = cxReallocDefault(pool->data, newmsize); |
48 if (newdata == NULL) return 1; |
49 if (newdata == NULL) return 1; |
49 pool->data = newdata; |
50 pool->data = newdata; |
50 pool->capacity = newcap; |
51 pool->capacity = newcap; |
51 return 0; |
52 return 0; |
57 ) { |
58 ) { |
58 if (needed_capacity <= pool->registered_capacity) return 0; |
59 if (needed_capacity <= pool->registered_capacity) return 0; |
59 // we do not expect so many registrations |
60 // we do not expect so many registrations |
60 size_t newcap = pool->registered_capacity + 8; |
61 size_t newcap = pool->registered_capacity + 8; |
61 size_t newmsize; |
62 size_t newmsize; |
|
63 // LCOV_EXCL_START |
62 if (pool->registered_capacity > newcap || cx_szmul(newcap, |
64 if (pool->registered_capacity > newcap || cx_szmul(newcap, |
63 sizeof(struct cx_mempool_foreign_memory_s), &newmsize)) { |
65 sizeof(struct cx_mempool_foreign_memory_s), &newmsize)) { |
64 errno = EOVERFLOW; |
66 errno = EOVERFLOW; |
65 return 1; |
67 return 1; |
66 } |
68 } // LCOV_EXCL_STOP |
67 void *newdata = cxReallocDefault(pool->registered, newmsize); |
69 void *newdata = cxReallocDefault(pool->registered, newmsize); |
68 if (newdata == NULL) return 1; |
70 if (newdata == NULL) return 1; |
69 pool->registered = newdata; |
71 pool->registered = newdata; |
70 pool->registered_capacity = newcap; |
72 pool->registered_capacity = newcap; |
71 return 0; |
73 return 0; |
76 size_t n |
78 size_t n |
77 ) { |
79 ) { |
78 struct cx_mempool_s *pool = p; |
80 struct cx_mempool_s *pool = p; |
79 |
81 |
80 if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { |
82 if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { |
81 return NULL; |
83 return NULL; // LCOV_EXCL_LINE |
82 } |
84 } |
83 |
85 |
84 struct cx_mempool_memory_s *mem = |
86 struct cx_mempool_memory_s *mem = |
85 cxMallocDefault(sizeof(struct cx_mempool_memory_s) + n); |
87 cxMallocDefault(sizeof(struct cx_mempool_memory_s) + n); |
86 if (mem == NULL) return NULL; |
88 if (mem == NULL) return NULL; |
105 if (ptr == NULL) return NULL; |
107 if (ptr == NULL) return NULL; |
106 memset(ptr, 0, nelem * elsize); |
108 memset(ptr, 0, nelem * elsize); |
107 return ptr; |
109 return ptr; |
108 } |
110 } |
109 |
111 |
|
112 static void cx_mempool_free_simple( |
|
113 void *p, |
|
114 void *ptr |
|
115 ) { |
|
116 if (!ptr) return; |
|
117 struct cx_mempool_s *pool = p; |
|
118 |
|
119 struct cx_mempool_memory_s *mem = |
|
120 (void*) ((char *) ptr - sizeof(struct cx_mempool_memory_s)); |
|
121 |
|
122 for (size_t i = 0; i < pool->size; i++) { |
|
123 if (mem == pool->data[i]) { |
|
124 if (mem->destructor) { |
|
125 mem->destructor(mem->c); |
|
126 } |
|
127 if (pool->destr) { |
|
128 pool->destr(mem->c); |
|
129 } |
|
130 if (pool->destr2) { |
|
131 pool->destr2(pool->destr2_data, mem->c); |
|
132 } |
|
133 cxFreeDefault(mem); |
|
134 size_t last_index = pool->size - 1; |
|
135 if (i != last_index) { |
|
136 pool->data[i] = pool->data[last_index]; |
|
137 pool->data[last_index] = NULL; |
|
138 } |
|
139 pool->size--; |
|
140 return; |
|
141 } |
|
142 } |
|
143 abort(); // LCOV_EXCL_LINE |
|
144 } |
|
145 |
110 static void *cx_mempool_realloc_simple( |
146 static void *cx_mempool_realloc_simple( |
111 void *p, |
147 void *p, |
112 void *ptr, |
148 void *ptr, |
113 size_t n |
149 size_t n |
114 ) { |
150 ) { |
|
151 if (ptr == NULL) { |
|
152 return cx_mempool_malloc_simple(p, n); |
|
153 } |
|
154 if (n == 0) { |
|
155 cx_mempool_free_simple(p, ptr); |
|
156 return NULL; |
|
157 } |
115 struct cx_mempool_s *pool = p; |
158 struct cx_mempool_s *pool = p; |
116 |
159 |
117 const unsigned overhead = sizeof(struct cx_mempool_memory_s); |
160 const unsigned overhead = sizeof(struct cx_mempool_memory_s); |
118 struct cx_mempool_memory_s *mem = |
161 struct cx_mempool_memory_s *mem = |
119 (void *) (((char *) ptr) - overhead); |
162 (void *) (((char *) ptr) - overhead); |
128 return ((char*)newm) + overhead; |
171 return ((char*)newm) + overhead; |
129 } |
172 } |
130 } |
173 } |
131 abort(); // LCOV_EXCL_LINE |
174 abort(); // LCOV_EXCL_LINE |
132 } else { |
175 } else { |
133 return ptr; |
176 // unfortunately glibc() realloc seems to always move |
134 } |
177 return ptr; // LCOV_EXCL_LINE |
135 } |
178 } |
136 |
|
137 static void cx_mempool_free_simple( |
|
138 void *p, |
|
139 void *ptr |
|
140 ) { |
|
141 if (!ptr) return; |
|
142 struct cx_mempool_s *pool = p; |
|
143 |
|
144 struct cx_mempool_memory_s *mem = |
|
145 (void*) ((char *) ptr - sizeof(struct cx_mempool_memory_s)); |
|
146 |
|
147 for (size_t i = 0; i < pool->size; i++) { |
|
148 if (mem == pool->data[i]) { |
|
149 if (mem->destructor) { |
|
150 mem->destructor(mem->c); |
|
151 } |
|
152 if (pool->destr) { |
|
153 pool->destr(mem->c); |
|
154 } |
|
155 if (pool->destr2) { |
|
156 pool->destr2(pool->destr2_data, mem->c); |
|
157 } |
|
158 cxFreeDefault(mem); |
|
159 size_t last_index = pool->size - 1; |
|
160 if (i != last_index) { |
|
161 pool->data[i] = pool->data[last_index]; |
|
162 pool->data[last_index] = NULL; |
|
163 } |
|
164 pool->size--; |
|
165 return; |
|
166 } |
|
167 } |
|
168 abort(); // LCOV_EXCL_LINE |
|
169 } |
179 } |
170 |
180 |
171 static void cx_mempool_free_all_simple(const struct cx_mempool_s *pool) { |
181 static void cx_mempool_free_all_simple(const struct cx_mempool_s *pool) { |
172 const bool has_destr = pool->destr; |
182 const bool has_destr = pool->destr; |
173 const bool has_destr2 = pool->destr2; |
183 const bool has_destr2 = pool->destr2; |
198 size_t n |
208 size_t n |
199 ) { |
209 ) { |
200 struct cx_mempool_s *pool = p; |
210 struct cx_mempool_s *pool = p; |
201 |
211 |
202 if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { |
212 if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { |
203 return NULL; |
213 return NULL; // LCOV_EXCL_LINE |
204 } |
214 } |
205 |
215 |
206 struct cx_mempool_memory2_s *mem = |
216 struct cx_mempool_memory2_s *mem = |
207 cxMallocDefault(sizeof(struct cx_mempool_memory_s) + n); |
217 cxMallocDefault(sizeof(struct cx_mempool_memory2_s) + n); |
208 if (mem == NULL) return NULL; |
218 if (mem == NULL) return NULL; |
209 mem->destructor = NULL; |
219 mem->destructor = NULL; |
210 mem->data = NULL; |
220 mem->data = NULL; |
211 pool->data[pool->size] = mem; |
221 pool->data[pool->size] = mem; |
212 pool->size++; |
222 pool->size++; |
228 if (ptr == NULL) return NULL; |
238 if (ptr == NULL) return NULL; |
229 memset(ptr, 0, nelem * elsize); |
239 memset(ptr, 0, nelem * elsize); |
230 return ptr; |
240 return ptr; |
231 } |
241 } |
232 |
242 |
|
243 static void cx_mempool_free_advanced( |
|
244 void *p, |
|
245 void *ptr |
|
246 ) { |
|
247 if (!ptr) return; |
|
248 struct cx_mempool_s *pool = p; |
|
249 |
|
250 struct cx_mempool_memory2_s *mem = |
|
251 (void*) ((char *) ptr - sizeof(struct cx_mempool_memory2_s)); |
|
252 |
|
253 for (size_t i = 0; i < pool->size; i++) { |
|
254 if (mem == pool->data[i]) { |
|
255 if (mem->destructor) { |
|
256 mem->destructor(mem->data, mem->c); |
|
257 } |
|
258 if (pool->destr) { |
|
259 pool->destr(mem->c); |
|
260 } |
|
261 if (pool->destr2) { |
|
262 pool->destr2(pool->destr2_data, mem->c); |
|
263 } |
|
264 cxFreeDefault(mem); |
|
265 size_t last_index = pool->size - 1; |
|
266 if (i != last_index) { |
|
267 pool->data[i] = pool->data[last_index]; |
|
268 pool->data[last_index] = NULL; |
|
269 } |
|
270 pool->size--; |
|
271 return; |
|
272 } |
|
273 } |
|
274 abort(); // LCOV_EXCL_LINE |
|
275 } |
|
276 |
233 static void *cx_mempool_realloc_advanced( |
277 static void *cx_mempool_realloc_advanced( |
234 void *p, |
278 void *p, |
235 void *ptr, |
279 void *ptr, |
236 size_t n |
280 size_t n |
237 ) { |
281 ) { |
|
282 if (ptr == NULL) { |
|
283 return cx_mempool_malloc_advanced(p, n); |
|
284 } |
|
285 if (n == 0) { |
|
286 cx_mempool_free_advanced(p, ptr); |
|
287 return NULL; |
|
288 } |
238 struct cx_mempool_s *pool = p; |
289 struct cx_mempool_s *pool = p; |
239 |
290 |
240 const unsigned overhead = sizeof(struct cx_mempool_memory2_s); |
291 const unsigned overhead = sizeof(struct cx_mempool_memory2_s); |
241 struct cx_mempool_memory2_s *mem = |
292 struct cx_mempool_memory2_s *mem = |
242 (void *) (((char *) ptr) - overhead); |
293 (void *) (((char *) ptr) - overhead); |
251 return ((char*)newm) + overhead; |
302 return ((char*)newm) + overhead; |
252 } |
303 } |
253 } |
304 } |
254 abort(); // LCOV_EXCL_LINE |
305 abort(); // LCOV_EXCL_LINE |
255 } else { |
306 } else { |
256 return ptr; |
307 // unfortunately glibc() realloc seems to always move |
257 } |
308 return ptr; // LCOV_EXCL_LINE |
258 } |
309 } |
259 |
|
260 static void cx_mempool_free_advanced( |
|
261 void *p, |
|
262 void *ptr |
|
263 ) { |
|
264 if (!ptr) return; |
|
265 struct cx_mempool_s *pool = p; |
|
266 |
|
267 struct cx_mempool_memory2_s *mem = |
|
268 (void*) ((char *) ptr - sizeof(struct cx_mempool_memory2_s)); |
|
269 |
|
270 for (size_t i = 0; i < pool->size; i++) { |
|
271 if (mem == pool->data[i]) { |
|
272 if (mem->destructor) { |
|
273 mem->destructor(mem->data, mem->c); |
|
274 } |
|
275 if (pool->destr) { |
|
276 pool->destr(mem->c); |
|
277 } |
|
278 if (pool->destr2) { |
|
279 pool->destr2(pool->destr2_data, mem->c); |
|
280 } |
|
281 cxFreeDefault(mem); |
|
282 size_t last_index = pool->size - 1; |
|
283 if (i != last_index) { |
|
284 pool->data[i] = pool->data[last_index]; |
|
285 pool->data[last_index] = NULL; |
|
286 } |
|
287 pool->size--; |
|
288 return; |
|
289 } |
|
290 } |
|
291 abort(); // LCOV_EXCL_LINE |
|
292 } |
310 } |
293 |
311 |
294 static void cx_mempool_free_all_advanced(const struct cx_mempool_s *pool) { |
312 static void cx_mempool_free_all_advanced(const struct cx_mempool_s *pool) { |
295 const bool has_destr = pool->destr; |
313 const bool has_destr = pool->destr; |
296 const bool has_destr2 = pool->destr2; |
314 const bool has_destr2 = pool->destr2; |
322 size_t n |
340 size_t n |
323 ) { |
341 ) { |
324 struct cx_mempool_s *pool = p; |
342 struct cx_mempool_s *pool = p; |
325 |
343 |
326 if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { |
344 if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { |
327 return NULL; |
345 return NULL; // LCOV_EXCL_LINE |
328 } |
346 } |
329 |
347 |
330 void *mem = cxMallocDefault(n); |
348 void *mem = cxMallocDefault(n); |
331 if (mem == NULL) return NULL; |
349 if (mem == NULL) return NULL; |
332 pool->data[pool->size] = mem; |
350 pool->data[pool->size] = mem; |
349 if (ptr == NULL) return NULL; |
367 if (ptr == NULL) return NULL; |
350 memset(ptr, 0, nelem * elsize); |
368 memset(ptr, 0, nelem * elsize); |
351 return ptr; |
369 return ptr; |
352 } |
370 } |
353 |
371 |
|
372 static void cx_mempool_free_pure( |
|
373 void *p, |
|
374 void *ptr |
|
375 ) { |
|
376 if (!ptr) return; |
|
377 struct cx_mempool_s *pool = p; |
|
378 |
|
379 for (size_t i = 0; i < pool->size; i++) { |
|
380 if (ptr == pool->data[i]) { |
|
381 if (pool->destr) { |
|
382 pool->destr(ptr); |
|
383 } |
|
384 if (pool->destr2) { |
|
385 pool->destr2(pool->destr2_data, ptr); |
|
386 } |
|
387 cxFreeDefault(ptr); |
|
388 size_t last_index = pool->size - 1; |
|
389 if (i != last_index) { |
|
390 pool->data[i] = pool->data[last_index]; |
|
391 pool->data[last_index] = NULL; |
|
392 } |
|
393 pool->size--; |
|
394 return; |
|
395 } |
|
396 } |
|
397 abort(); // LCOV_EXCL_LINE |
|
398 } |
|
399 |
354 static void *cx_mempool_realloc_pure( |
400 static void *cx_mempool_realloc_pure( |
355 void *p, |
401 void *p, |
356 void *ptr, |
402 void *ptr, |
357 size_t n |
403 size_t n |
358 ) { |
404 ) { |
|
405 if (ptr == NULL) { |
|
406 return cx_mempool_malloc_pure(p, n); |
|
407 } |
|
408 if (n == 0) { |
|
409 cx_mempool_free_pure(p, ptr); |
|
410 return NULL; |
|
411 } |
359 struct cx_mempool_s *pool = p; |
412 struct cx_mempool_s *pool = p; |
360 void *newm = cxReallocDefault(ptr, n); |
413 void *newm = cxReallocDefault(ptr, n); |
361 if (newm == NULL) return NULL; |
414 if (newm == NULL) return NULL; |
362 if (ptr != newm) { |
415 if (ptr != newm) { |
363 for (size_t i = 0; i < pool->size; i++) { |
416 for (size_t i = 0; i < pool->size; i++) { |
366 return newm; |
419 return newm; |
367 } |
420 } |
368 } |
421 } |
369 abort(); // LCOV_EXCL_LINE |
422 abort(); // LCOV_EXCL_LINE |
370 } else { |
423 } else { |
371 return ptr; |
424 // unfortunately glibc() realloc seems to always move |
372 } |
425 return ptr; // LCOV_EXCL_LINE |
373 } |
426 } |
374 |
|
375 static void cx_mempool_free_pure( |
|
376 void *p, |
|
377 void *ptr |
|
378 ) { |
|
379 if (!ptr) return; |
|
380 struct cx_mempool_s *pool = p; |
|
381 |
|
382 for (size_t i = 0; i < pool->size; i++) { |
|
383 if (ptr == pool->data[i]) { |
|
384 if (pool->destr) { |
|
385 pool->destr(ptr); |
|
386 } |
|
387 if (pool->destr2) { |
|
388 pool->destr2(pool->destr2_data, ptr); |
|
389 } |
|
390 cxFreeDefault(ptr); |
|
391 size_t last_index = pool->size - 1; |
|
392 if (i != last_index) { |
|
393 pool->data[i] = pool->data[last_index]; |
|
394 pool->data[last_index] = NULL; |
|
395 } |
|
396 pool->size--; |
|
397 return; |
|
398 } |
|
399 } |
|
400 abort(); // LCOV_EXCL_LINE |
|
401 } |
427 } |
402 |
428 |
403 static void cx_mempool_free_all_pure(const struct cx_mempool_s *pool) { |
429 static void cx_mempool_free_all_pure(const struct cx_mempool_s *pool) { |
404 const bool has_destr = pool->destr; |
430 const bool has_destr = pool->destr; |
405 const bool has_destr2 = pool->destr2; |
431 const bool has_destr2 = pool->destr2; |
524 enum cx_mempool_type type |
550 enum cx_mempool_type type |
525 ) { |
551 ) { |
526 if (capacity == 0) capacity = 16; |
552 if (capacity == 0) capacity = 16; |
527 size_t poolsize; |
553 size_t poolsize; |
528 if (cx_szmul(capacity, sizeof(void*), &poolsize)) { |
554 if (cx_szmul(capacity, sizeof(void*), &poolsize)) { |
|
555 // LCOV_EXCL_START |
529 errno = EOVERFLOW; |
556 errno = EOVERFLOW; |
530 return NULL; |
557 return NULL; |
531 } |
558 } // LCOV_EXCL_STOP |
532 |
559 |
533 CxAllocator *provided_allocator = cxMallocDefault(sizeof(CxAllocator)); |
560 CxAllocator *provided_allocator = cxMallocDefault(sizeof(CxAllocator)); |
534 if (provided_allocator == NULL) { // LCOV_EXCL_START |
561 if (provided_allocator == NULL) { // LCOV_EXCL_START |
535 return NULL; |
562 return NULL; |
536 } // LCOV_EXCL_STOP |
563 } // LCOV_EXCL_STOP |
537 |
564 |
538 CxMempool *pool = cxCallocDefault(1, sizeof(CxMempool)); |
565 CxMempool *pool = cxCallocDefault(1, sizeof(CxMempool)); |
539 if (pool == NULL) { |
566 if (pool == NULL) { // LCOV_EXCL_START |
540 cxFreeDefault(provided_allocator); |
567 cxFreeDefault(provided_allocator); |
541 return NULL; |
568 return NULL; |
542 } |
569 } // LCOV_EXCL_STOP |
543 |
570 |
544 provided_allocator->data = pool; |
571 provided_allocator->data = pool; |
545 pool->allocator = provided_allocator; |
572 pool->allocator = provided_allocator; |
546 if (type == CX_MEMPOOL_TYPE_SIMPLE) { |
573 if (type == CX_MEMPOOL_TYPE_SIMPLE) { |
547 provided_allocator->cl = &cx_mempool_simple_allocator_class; |
574 provided_allocator->cl = &cx_mempool_simple_allocator_class; |