00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdlib.h>
00014 #include <string.h>
00015
00016 #include "memory_pool.h"
00017
00018 inline static size_t calc_node_size(size_t element_size)
00019 {
00020 return element_size + sizeof(memory_pool_node_hdr_t);
00021 }
00022
00023 inline static node_t *get_node_n(memory_pool_t *pool, node_t *head, u32 n)
00024 {
00025 return (node_t *)((u8 *)head + calc_node_size(pool->element_size) * n);
00026 }
00027
00062 memory_pool_t *memory_pool_new(u32 n_elements, size_t element_size)
00063 {
00064 memory_pool_t *new_pool = malloc(sizeof(memory_pool_t));
00065 if (!new_pool) {
00066 return NULL;
00067 }
00068
00069
00070 size_t node_size = calc_node_size(element_size);
00071 node_t *buff = (node_t *)malloc(node_size * n_elements);
00072 if (!buff) {
00073 free(new_pool);
00074 return NULL;
00075 }
00076
00077 memory_pool_init(new_pool, n_elements, element_size, buff);
00078
00079 return new_pool;
00080 }
00081
00103 s8 memory_pool_init(memory_pool_t *new_pool, u32 n_elements,
00104 size_t element_size, void *buff)
00105 {
00106 if (!new_pool) {
00107 return -1;
00108 }
00109
00110 new_pool->n_elements = n_elements;
00111 new_pool->element_size = element_size;
00112
00113
00114 new_pool->pool = (node_t *)buff;
00115 if (!new_pool->pool) {
00116 return -2;
00117 }
00118
00119
00120
00121 new_pool->free_nodes_head = new_pool->pool;
00122 node_t *current = NULL;
00123 node_t *next_free = NULL;
00124
00125
00126 for (s32 i=n_elements-1; i>=0; i--) {
00127 current = get_node_n(new_pool, new_pool->free_nodes_head, i);
00128 current->hdr.next = next_free;
00129 next_free = current;
00130 }
00131
00132
00133 new_pool->allocated_nodes_head = NULL;
00134
00135 return 0;
00136 }
00137
00144 void memory_pool_destroy(memory_pool_t *pool)
00145 {
00146 free(pool->pool);
00147 free(pool);
00148 }
00149
00157 s32 memory_pool_n_free(memory_pool_t *pool)
00158 {
00159 u32 count = 0;
00160
00161 node_t *p = pool->free_nodes_head;
00162 while (p && count <= pool->n_elements) {
00163 p = p->hdr.next;
00164 count++;
00165 }
00166
00167 if (count == pool->n_elements && p)
00168
00169
00170 return -1;
00171
00172 return count;
00173 }
00174
00181 s32 memory_pool_n_allocated(memory_pool_t *pool)
00182 {
00183 u32 count = 0;
00184
00185 node_t *p = pool->allocated_nodes_head;
00186 while (p && count <= pool->n_elements) {
00187 p = p->hdr.next;
00188 count++;
00189 }
00190
00191 if (count == pool->n_elements && p)
00192
00193
00194 return -1;
00195
00196 return count;
00197 }
00198
00205 u8 memory_pool_empty(memory_pool_t *pool)
00206 {
00207 return (pool->allocated_nodes_head == NULL);
00208 }
00209
00212 u32 memory_pool_n_elements(memory_pool_t *pool)
00213 {
00214 return pool->n_elements;
00215 }
00228 s32 memory_pool_to_array(memory_pool_t *pool, void *array)
00229 {
00230 u32 count = 0;
00231
00232 node_t *p = pool->allocated_nodes_head;
00233 while (p && count <= pool->n_elements) {
00234 memcpy((u8 *)array + count*pool->element_size, p->elem, pool->element_size);
00235 p = p->hdr.next;
00236 count++;
00237 }
00238
00239 if (count == pool->n_elements && p)
00240
00241
00242 return -1;
00243
00244 return count;
00245 }
00246
00254 element_t *memory_pool_add(memory_pool_t *pool)
00255 {
00256
00257
00258
00259 if (!pool->free_nodes_head) {
00260
00261 return NULL;
00262 }
00263
00264 node_t *new_node = pool->free_nodes_head;
00265 pool->free_nodes_head = new_node->hdr.next;
00266
00267 new_node->hdr.next = pool->allocated_nodes_head;
00268 pool->allocated_nodes_head = new_node;
00269
00270 return new_node->elem;
00271 }
00272
00279 s32 memory_pool_map(memory_pool_t *pool, void *arg, void (*f)(void *arg, element_t *elem))
00280 {
00281 u32 count = 0;
00282
00283 node_t *p = pool->allocated_nodes_head;
00284 while (p && count <= pool->n_elements) {
00285 (*f)(arg, p->elem);
00286 p = p->hdr.next;
00287 count++;
00288 }
00289
00290 if (count == pool->n_elements && p)
00291
00292
00293 return -1;
00294
00295 return count;
00296 }
00297
00308 s32 memory_pool_fold(memory_pool_t *pool, void *x0,
00309 void (*f)(void *x, element_t *elem))
00310 {
00311 u32 count = 0;
00312
00313 node_t *p = pool->allocated_nodes_head;
00314 while (p && count <= pool->n_elements) {
00315 (*f)(x0, p->elem);
00316 p = p->hdr.next;
00317 count++;
00318 }
00319
00320 if (count == pool->n_elements && p)
00321
00322
00323 return -1;
00324
00325 return count;
00326 }
00327
00338 double memory_pool_dfold(memory_pool_t *pool, double x0,
00339 double (*f)(double x, element_t *elem))
00340 {
00341 u32 count = 0;
00342 double x = x0;
00343
00344 node_t *p = pool->allocated_nodes_head;
00345 while (p && count <= pool->n_elements) {
00346 x = (*f)(x, p->elem);
00347 p = p->hdr.next;
00348 count++;
00349 }
00350
00351 return x;
00352 }
00353
00364 float memory_pool_ffold(memory_pool_t *pool, float x0,
00365 float (*f)(float x, element_t *elem))
00366 {
00367 u32 count = 0;
00368 float x = x0;
00369
00370 node_t *p = pool->allocated_nodes_head;
00371 while (p && count <= pool->n_elements) {
00372 x = (*f)(x, p->elem);
00373 p = p->hdr.next;
00374 count++;
00375 }
00376
00377 return x;
00378 }
00379
00390 s32 memory_pool_ifold(memory_pool_t *pool, s32 x0,
00391 s32 (*f)(s32 x, element_t *elem))
00392 {
00393 u32 count = 0;
00394 s32 x = x0;
00395
00396 node_t *p = pool->allocated_nodes_head;
00397 while (p && count <= pool->n_elements) {
00398 x = (*f)(x, p->elem);
00399 p = p->hdr.next;
00400 count++;
00401 }
00402
00403 return x;
00404 }
00405
00414 s32 memory_pool_filter(memory_pool_t *pool, void *arg, s8 (*f)(void *arg, element_t *elem))
00415 {
00416 u32 count = 0;
00417
00418
00419
00420 node_t fake_head_node_prev = {
00421 .hdr = {
00422 .next = pool->allocated_nodes_head,
00423 },
00424 };
00425
00426 node_t *p_prev = &fake_head_node_prev;
00427 node_t *p = pool->allocated_nodes_head;
00428
00429 while (p && count <= pool->n_elements) {
00430 if ((*f)(arg, p->elem)) {
00431
00432 p_prev = p;
00433 p = p->hdr.next;
00434 count++;
00435 } else {
00436
00437 p_prev->hdr.next = p->hdr.next;
00438
00439 p->hdr.next = pool->free_nodes_head;
00440 pool->free_nodes_head = p;
00441 p = p_prev->hdr.next;
00442 }
00443 }
00444
00445
00446 pool->allocated_nodes_head = fake_head_node_prev.hdr.next;
00447
00448 if (count == pool->n_elements && p)
00449
00450
00451 return -1;
00452
00453 return count;
00454 }
00455
00461 s32 memory_pool_clear(memory_pool_t *pool)
00462 {
00463 u32 count = 0;
00464 node_t *p = pool->allocated_nodes_head;
00465
00466 if (!p) {
00467
00468 return 0;
00469 }
00470
00471 while (p->hdr.next && count <= pool->n_elements) {
00472 p = p->hdr.next;
00473 count++;
00474 }
00475
00476 if (p->hdr.next) {
00477
00478 return -1;
00479 }
00480
00481
00482
00483 p->hdr.next = pool->free_nodes_head;
00484 pool->free_nodes_head = pool->allocated_nodes_head;
00485 pool->allocated_nodes_head = NULL;
00486
00487 return 0;
00488 }
00489
00535 void memory_pool_sort(memory_pool_t *pool, void *arg,
00536 s32 (*cmp)(void *arg, element_t *a, element_t *b))
00537 {
00538
00539 if (!pool->allocated_nodes_head)
00540 return;
00541
00542 u32 insize = 1;
00543
00544 while (1) {
00545 node_t *p = pool->allocated_nodes_head;
00546 pool->allocated_nodes_head = NULL;
00547 node_t *tail = NULL;
00548
00549 u32 nmerges = 0;
00550
00551 while (p) {
00552 nmerges++;
00553
00554 node_t *q = p;
00555 u32 psize = 0;
00556 for (u32 i = 0; i < insize; i++) {
00557 psize++;
00558 q = q->hdr.next;
00559 if (!q) break;
00560 }
00561
00562
00563 u32 qsize = insize;
00564
00565
00566 while (psize > 0 || (qsize > 0 && q)) {
00567
00568 node_t *e;
00569
00570
00571 if (psize == 0) {
00572
00573 e = q; q = q->hdr.next; qsize--;
00574 } else if (qsize == 0 || !q) {
00575
00576 e = p; p = p->hdr.next; psize--;
00577 } else if (cmp(arg, p->elem, q->elem) <= 0) {
00578
00579
00580 e = p; p = p->hdr.next; psize--;
00581 } else {
00582
00583 e = q; q = q->hdr.next; qsize--;
00584 }
00585
00586
00587 if (tail) {
00588 tail->hdr.next = e;
00589 } else {
00590 pool->allocated_nodes_head = e;
00591 }
00592 tail = e;
00593 }
00594
00595
00596 p = q;
00597 }
00598 tail->hdr.next = NULL;
00599
00600
00601 if (nmerges <= 1)
00602 return;
00603
00604
00605 insize *= 2;
00606 }
00607 }
00608
00644 void memory_pool_group_by(memory_pool_t *pool, void *arg,
00645 s32 (*cmp)(void *arg, element_t *a, element_t *b),
00646 void *x0, size_t x_size,
00647 void (*agg)(element_t *new, void *x, u32 n, element_t *elem))
00648 {
00649
00650 if (!pool->allocated_nodes_head)
00651 return;
00652
00653
00654 memory_pool_sort(pool, arg, cmp);
00655
00656
00657
00658 node_t *old_head = pool->allocated_nodes_head;
00659 pool->allocated_nodes_head = NULL;
00660
00661
00662 u8 x_work[x_size];
00663
00664 u32 count = 0;
00665
00666 node_t *p = old_head;
00667
00668 while (p && count <= pool->n_elements) {
00669 u32 group_count = 0;
00670
00671
00672 node_t *group_head = p;
00673
00674
00675 if (x_size)
00676 memcpy(x_work, x0, x_size);
00677
00678
00679 element_t *new_elem = memory_pool_add(pool);
00680
00681
00682 memcpy(new_elem, p->elem, pool->element_size);
00683
00684
00685 do {
00686 agg(new_elem, (void *)x_work, group_count, p->elem);
00687 group_count++;
00688
00689
00690 node_t *next_p = p->hdr.next;
00691
00692
00693 p->hdr.next = pool->free_nodes_head;
00694 pool->free_nodes_head = p;
00695
00696 p = next_p;
00697 } while(p && cmp(arg, group_head->elem, p->elem) == 0);
00698
00699 count++;
00700 }
00701 }
00702
00721 s32 memory_pool_product(memory_pool_t *pool, void *xs, u32 n_xs, size_t x_size,
00722 void (*prod)(element_t *new, void *x, u32 n_xs, u32 n, element_t *elem))
00723 {
00724
00725
00726 node_t *old_head = pool->allocated_nodes_head;
00727 pool->allocated_nodes_head = NULL;
00728
00729 u32 count = 0;
00730
00731 node_t *p = old_head;
00732 while (p && count <= pool->n_elements) {
00733
00734
00735 for (u32 i=0; i<n_xs; i++) {
00736 element_t *new = memory_pool_add(pool);
00737 if (!new) {
00738
00739 return -2;
00740 }
00741
00742 memcpy(new, p->elem, pool->element_size);
00743 prod(new, ((u8 *)xs + i*x_size), n_xs, i, p->elem);
00744 count++;
00745 }
00746
00747
00748 node_t *next_p = p->hdr.next;
00749
00750
00751 p->hdr.next = pool->free_nodes_head;
00752 pool->free_nodes_head = p;
00753
00754 p = next_p;
00755 }
00756
00757 if (count == pool->n_elements && p)
00758
00759
00760 return -1;
00761
00762 return count;
00763 }
00764
00765 s32 memory_pool_product_generator(memory_pool_t *pool, void *x0, u32 max_xs, size_t x_size,
00766 s8 (*next)(void *x, u32 n),
00767 void (*prod)(element_t *new, void *x, u32 n, element_t *elem))
00768 {
00769
00770
00771 node_t *old_head = pool->allocated_nodes_head;
00772 pool->allocated_nodes_head = NULL;
00773
00774 u32 count = 0;
00775
00776 node_t *p = old_head;
00777 while (p && count <= pool->n_elements) {
00778
00779
00780 u8 x_work[x_size];
00781 memcpy(x_work, x0, x_size);
00782 u32 x_count = 0;
00783 do {
00784 if (x_count > max_xs) {
00785
00786 return -3;
00787 }
00788 element_t *new = memory_pool_add(pool);
00789 if (!new) {
00790
00791 return -2;
00792 }
00793
00794 memcpy(new, p->elem, pool->element_size);
00795 prod(new, x_work, x_count, p->elem);
00796 x_count++;
00797 count++;
00798 } while (next(x_work, x_count));
00799
00800
00801 node_t *next_p = p->hdr.next;
00802
00803
00804 p->hdr.next = pool->free_nodes_head;
00805 pool->free_nodes_head = p;
00806
00807 p = next_p;
00808 }
00809
00810 if (count == pool->n_elements && p)
00811
00812
00813 return -1;
00814
00815 return count;
00816 }
00817