annotate src/tools.c @ 118:c9c6810a96c1

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