annotate src/tools.c @ 1461:31189b5d832a

Add document
author Thinker K.F. Li <thinker@codemud.net>
date Sun, 17 Apr 2011 01:08:26 +0800
parents 586e50f82c1f
children
rev   line source
822
586e50f82c1f Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents: 186
diff changeset
1 // -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*-
586e50f82c1f Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents: 186
diff changeset
2 // vim: sw=4:ts=8:sts=4
12
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
3 #include <stdlib.h>
186
530bb7728546 Move header files to $(top_srcdir)/include/ and prefixed with 'mb_'.
Thinker K.F. Li <thinker@branda.to>
parents: 185
diff changeset
4 #include "mb_tools.h"
12
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
5
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 /*! \brief Small fixed size data elements management.
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
8 *
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
9 * 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
10 * 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
11 * 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
12 * utilization of memory.
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
13 *
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
14 * 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
15 * 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
16 * increase cache hit rate.
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
17 *
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
18 * 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
19 * 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
20 * 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
21 * 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
22 * code.
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
23 */
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
24 struct _elmpool {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
25 int elm_sz;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
26 int inc_num;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
27 void *frees;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
28 void *blks; /* list of allocated blocks. */
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
29 };
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 /*! \brief Create a new data elements pool.
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
32 *
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
33 * 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
34 * utilization of memory. It try to allocate bigger memory blocks
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
35 * for multiple elements.
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
36 *
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
37 * \param elm_sz size of elements.
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
38 * \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
39 * \return A elmpool or NULL for error.
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
40 */
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
41 elmpool_t *elmpool_new(int elm_sz, int inc_num) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
42 int _elm_sz;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
43 elmpool_t *pool;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
44
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
45 if(inc_num < 16)
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
46 return NULL;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
47
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
48 if(elm_sz >= sizeof(void *))
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
49 _elm_sz = elm_sz;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
50 else
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
51 _elm_sz = sizeof(void *);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
52
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
53 pool = (elmpool_t *)malloc(sizeof(elmpool_t));
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
54 if(pool == NULL)
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
55 return NULL;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
56
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
57 pool->elm_sz = _elm_sz;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
58 if(inc_num == 0)
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
59 inc_num = 256;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
60 pool->inc_num = inc_num;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
61 pool->frees = NULL;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
62 pool->blks = NULL;
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 return pool;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
65 }
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
66
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
67 void *elmpool_elm_alloc(elmpool_t *pool) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
68 void *blk, *elm;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
69 int elm_sz, inc_num;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
70 int i;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
71
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
72 if(pool->frees == NULL) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
73 inc_num = pool->inc_num;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
74 elm_sz = pool->elm_sz;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
75 blk = malloc(elm_sz * inc_num);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
76 if(blk == NULL)
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
77 return NULL;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
78
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
79 *(void **)blk = pool->blks;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
80 pool->blks = blk;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
81
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
82 blk = blk + elm_sz;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
83 pool->frees = blk;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
84 for(i = 2; i < inc_num; i++) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
85 *(void **)blk = blk + elm_sz;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
86 blk = *(void **)blk;
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 *(void **)blk = NULL;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
89 }
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
90
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
91 elm = pool->frees;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
92 pool->frees = *(void **)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 return elm;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
95 }
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
96
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
97 void elmpool_elm_free(elmpool_t *pool, void *elm) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
98 *(void **)elm = pool->frees;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
99 pool->frees = elm;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
100 }
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
101
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
102 void elmpool_free(elmpool_t *pool) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
103 void *blk, *next_blk;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
104
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
105 blk = pool->blks;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
106 while(blk) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
107 next_blk = *(void **)blk;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
108 free(blk);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
109 blk = next_blk;
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 }
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 #ifdef UNITTEST
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 #include <CUnit/Basic.h>
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
116
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
117 void test_elmpool(void) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
118 elmpool_t *pool;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
119 void *elm;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
120 int i;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
121
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
122 pool = elmpool_new(64, 16);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
123 for(i = 0; i < 15; i++) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
124 elm = elmpool_elm_alloc(pool);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
125 CU_ASSERT(elm != 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 CU_ASSERT(pool->frees == NULL);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
128
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
129 for(i = 0; i < 15; i++) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
130 elm = elmpool_elm_alloc(pool);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
131 CU_ASSERT(elm != 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 CU_ASSERT(pool->frees == NULL);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
134
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
135 elmpool_elm_free(pool, elm);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
136 CU_ASSERT(pool->frees == elm);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
137
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
138 elm = elmpool_elm_alloc(pool);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
139 CU_ASSERT(elm != NULL);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
140 CU_ASSERT(pool->frees == NULL);
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 elmpool_free(pool);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
143 }
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
144
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
145 CU_pSuite get_tools_suite(void) {
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
146 CU_pSuite suite;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
147
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
148 suite = CU_add_suite("Suite_tools", NULL, NULL);
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
149 CU_ADD_TEST(suite, test_elmpool);
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 return suite;
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
152 }
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
153
79e9edf4c00a Add redraw manager
Thinker K.F. Li <thinker@branda.to>
parents:
diff changeset
154 #endif /* UNITTEST */