src/mempool.c

changeset 1328
2cf66dee40b8
parent 1325
20caf6efaf07
child 1329
343eac5ac824
equal deleted inserted replaced
1327:ed75dc1db503 1328:2cf66dee40b8
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;

mercurial