12
|
1 #include <stdlib.h>
|
|
2 #include "tools.h"
|
|
3
|
|
4
|
|
5 /*! \brief Small fixed size data elements management.
|
|
6 *
|
|
7 * It is used to management a large number of data elements
|
|
8 * they with the same memory size, a fixed size. It allocate
|
|
9 * a large block for a lot of elements a time for more efficiency
|
|
10 * utilization of memory.
|
|
11 *
|
|
12 * Elements with the size and in a large number usually be accessed
|
|
13 * very close in time. Allocate a large block for elements also
|
|
14 * increase cache hit rate.
|
|
15 *
|
|
16 * Blocks are keep track as a linking list. They are freed when
|
|
17 * the elmpool_t is freed. It costs overhead of size of a element
|
|
18 * for each block. We use memory of first element of blocks to
|
|
19 * be next pointer of linking list. So, it can not be used by user
|
|
20 * code.
|
|
21 */
|
|
22 struct _elmpool {
|
|
23 int elm_sz;
|
|
24 int inc_num;
|
|
25 void *frees;
|
|
26 void *blks; /* list of allocated blocks. */
|
|
27 };
|
|
28
|
|
29 /*! \brief Create a new data elements pool.
|
|
30 *
|
|
31 * elmpool_t provide a pool of fixed size elements to gain better
|
|
32 * utilization of memory. It try to allocate bigger memory blocks
|
|
33 * for multiple elements.
|
|
34 *
|
|
35 * \param elm_sz size of elements.
|
|
36 * \param inc_num is number of elments to allocate every time. (>= 16)
|
|
37 * \return A elmpool or NULL for error.
|
|
38 */
|
|
39 elmpool_t *elmpool_new(int elm_sz, int inc_num) {
|
|
40 int _elm_sz;
|
|
41 elmpool_t *pool;
|
|
42
|
|
43 if(inc_num < 16)
|
|
44 return NULL;
|
|
45
|
|
46 if(elm_sz >= sizeof(void *))
|
|
47 _elm_sz = elm_sz;
|
|
48 else
|
|
49 _elm_sz = sizeof(void *);
|
|
50
|
|
51 pool = (elmpool_t *)malloc(sizeof(elmpool_t));
|
|
52 if(pool == NULL)
|
|
53 return NULL;
|
|
54
|
|
55 pool->elm_sz = _elm_sz;
|
|
56 if(inc_num == 0)
|
|
57 inc_num = 256;
|
|
58 pool->inc_num = inc_num;
|
|
59 pool->frees = NULL;
|
|
60 pool->blks = NULL;
|
|
61
|
|
62 return pool;
|
|
63 }
|
|
64
|
|
65 void *elmpool_elm_alloc(elmpool_t *pool) {
|
|
66 void *blk, *elm;
|
|
67 int elm_sz, inc_num;
|
|
68 int i;
|
|
69
|
|
70 if(pool->frees == NULL) {
|
|
71 inc_num = pool->inc_num;
|
|
72 elm_sz = pool->elm_sz;
|
|
73 blk = malloc(elm_sz * inc_num);
|
|
74 if(blk == NULL)
|
|
75 return NULL;
|
|
76
|
|
77 *(void **)blk = pool->blks;
|
|
78 pool->blks = blk;
|
|
79
|
|
80 blk = blk + elm_sz;
|
|
81 pool->frees = blk;
|
|
82 for(i = 2; i < inc_num; i++) {
|
|
83 *(void **)blk = blk + elm_sz;
|
|
84 blk = *(void **)blk;
|
|
85 }
|
|
86 *(void **)blk = NULL;
|
|
87 }
|
|
88
|
|
89 elm = pool->frees;
|
|
90 pool->frees = *(void **)elm;
|
|
91
|
|
92 return elm;
|
|
93 }
|
|
94
|
|
95 void elmpool_elm_free(elmpool_t *pool, void *elm) {
|
|
96 *(void **)elm = pool->frees;
|
|
97 pool->frees = elm;
|
|
98 }
|
|
99
|
|
100 void elmpool_free(elmpool_t *pool) {
|
|
101 void *blk, *next_blk;
|
|
102
|
|
103 blk = pool->blks;
|
|
104 while(blk) {
|
|
105 next_blk = *(void **)blk;
|
|
106 free(blk);
|
|
107 blk = next_blk;
|
|
108 }
|
|
109 }
|
|
110
|
|
111 #ifdef UNITTEST
|
|
112
|
|
113 #include <CUnit/Basic.h>
|
|
114
|
|
115 void test_elmpool(void) {
|
|
116 elmpool_t *pool;
|
|
117 void *elm;
|
|
118 int i;
|
|
119
|
|
120 pool = elmpool_new(64, 16);
|
|
121 for(i = 0; i < 15; i++) {
|
|
122 elm = elmpool_elm_alloc(pool);
|
|
123 CU_ASSERT(elm != NULL);
|
|
124 }
|
|
125 CU_ASSERT(pool->frees == NULL);
|
|
126
|
|
127 for(i = 0; i < 15; i++) {
|
|
128 elm = elmpool_elm_alloc(pool);
|
|
129 CU_ASSERT(elm != NULL);
|
|
130 }
|
|
131 CU_ASSERT(pool->frees == NULL);
|
|
132
|
|
133 elmpool_elm_free(pool, elm);
|
|
134 CU_ASSERT(pool->frees == elm);
|
|
135
|
|
136 elm = elmpool_elm_alloc(pool);
|
|
137 CU_ASSERT(elm != NULL);
|
|
138 CU_ASSERT(pool->frees == NULL);
|
|
139
|
|
140 elmpool_free(pool);
|
|
141 }
|
|
142
|
|
143 CU_pSuite get_tools_suite(void) {
|
|
144 CU_pSuite suite;
|
|
145
|
|
146 suite = CU_add_suite("Suite_tools", NULL, NULL);
|
|
147 CU_ADD_TEST(suite, test_elmpool);
|
|
148
|
|
149 return suite;
|
|
150 }
|
|
151
|
|
152 #endif /* UNITTEST */
|