Mercurial > MadButterfly
diff src/tools.c @ 12:79e9edf4c00a
Add redraw manager
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Mon, 28 Jul 2008 17:45:36 +0800 |
parents | |
children | e06a4a667ce2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools.c Mon Jul 28 17:45:36 2008 +0800 @@ -0,0 +1,152 @@ +#include <stdlib.h> +#include "tools.h" + + +/*! \brief Small fixed size data elements management. + * + * It is used to management a large number of data elements + * they with the same memory size, a fixed size. It allocate + * a large block for a lot of elements a time for more efficiency + * utilization of memory. + * + * Elements with the size and in a large number usually be accessed + * very close in time. Allocate a large block for elements also + * increase cache hit rate. + * + * Blocks are keep track as a linking list. They are freed when + * the elmpool_t is freed. It costs overhead of size of a element + * for each block. We use memory of first element of blocks to + * be next pointer of linking list. So, it can not be used by user + * code. + */ +struct _elmpool { + int elm_sz; + int inc_num; + void *frees; + void *blks; /* list of allocated blocks. */ +}; + +/*! \brief Create a new data elements pool. + * + * elmpool_t provide a pool of fixed size elements to gain better + * utilization of memory. It try to allocate bigger memory blocks + * for multiple elements. + * + * \param elm_sz size of elements. + * \param inc_num is number of elments to allocate every time. (>= 16) + * \return A elmpool or NULL for error. + */ +elmpool_t *elmpool_new(int elm_sz, int inc_num) { + int _elm_sz; + elmpool_t *pool; + + if(inc_num < 16) + return NULL; + + if(elm_sz >= sizeof(void *)) + _elm_sz = elm_sz; + else + _elm_sz = sizeof(void *); + + pool = (elmpool_t *)malloc(sizeof(elmpool_t)); + if(pool == NULL) + return NULL; + + pool->elm_sz = _elm_sz; + if(inc_num == 0) + inc_num = 256; + pool->inc_num = inc_num; + pool->frees = NULL; + pool->blks = NULL; + + return pool; +} + +void *elmpool_elm_alloc(elmpool_t *pool) { + void *blk, *elm; + int elm_sz, inc_num; + int i; + + if(pool->frees == NULL) { + inc_num = pool->inc_num; + elm_sz = pool->elm_sz; + blk = malloc(elm_sz * inc_num); + if(blk == NULL) + return NULL; + + *(void **)blk = pool->blks; + pool->blks = blk; + + blk = blk + elm_sz; + pool->frees = blk; + for(i = 2; i < inc_num; i++) { + *(void **)blk = blk + elm_sz; + blk = *(void **)blk; + } + *(void **)blk = NULL; + } + + elm = pool->frees; + pool->frees = *(void **)elm; + + return elm; +} + +void elmpool_elm_free(elmpool_t *pool, void *elm) { + *(void **)elm = pool->frees; + pool->frees = elm; +} + +void elmpool_free(elmpool_t *pool) { + void *blk, *next_blk; + + blk = pool->blks; + while(blk) { + next_blk = *(void **)blk; + free(blk); + blk = next_blk; + } +} + +#ifdef UNITTEST + +#include <CUnit/Basic.h> + +void test_elmpool(void) { + elmpool_t *pool; + void *elm; + int i; + + pool = elmpool_new(64, 16); + for(i = 0; i < 15; i++) { + elm = elmpool_elm_alloc(pool); + CU_ASSERT(elm != NULL); + } + CU_ASSERT(pool->frees == NULL); + + for(i = 0; i < 15; i++) { + elm = elmpool_elm_alloc(pool); + CU_ASSERT(elm != NULL); + } + CU_ASSERT(pool->frees == NULL); + + elmpool_elm_free(pool, elm); + CU_ASSERT(pool->frees == elm); + + elm = elmpool_elm_alloc(pool); + CU_ASSERT(elm != NULL); + CU_ASSERT(pool->frees == NULL); + + elmpool_free(pool); +} + +CU_pSuite get_tools_suite(void) { + CU_pSuite suite; + + suite = CU_add_suite("Suite_tools", NULL, NULL); + CU_ADD_TEST(suite, test_elmpool); + + return suite; +} + +#endif /* UNITTEST */