From d84babb6bddccff675e87ef43a597d6cd732385f Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Fri, 26 Sep 2014 23:50:01 +0200 Subject: [PATCH] Updates with latest tommyds library. --- cmdline/util.c | 22 ++++++++++++-- cmdline/util.h | 2 +- tommyds/tommy.c | 1 + tommyds/tommyarray.c | 40 +++++++++++++++----------- tommyds/tommyarray.h | 16 +++-------- tommyds/tommyarrayblk.c | 23 +++++++-------- tommyds/tommyarrayblk.h | 2 +- tommyds/tommyarrayblkof.c | 23 +++++++-------- tommyds/tommyarrayblkof.h | 2 +- tommyds/tommychain.h | 4 +-- tommyds/tommyhash.c | 38 ++++++++++++------------- tommyds/tommyhash.h | 4 +-- tommyds/tommyhashdyn.c | 60 ++++++++++++++++++++++++++++++--------- tommyds/tommyhashdyn.h | 27 ++++++++++++------ tommyds/tommylist.h | 8 ++++-- tommyds/tommytypes.h | 35 ++++++++++++++--------- 16 files changed, 189 insertions(+), 118 deletions(-) diff --git a/cmdline/util.c b/cmdline/util.c index 2acf96f7..482d849b 100644 --- a/cmdline/util.c +++ b/cmdline/util.c @@ -1505,9 +1505,27 @@ void* malloc_nofail(size_t size) return ptr; } -void* cmalloc_nofail(size_t count, size_t size) +void* calloc_nofail(size_t count, size_t size) { - return malloc_nofail(count * size); + void* ptr; + + size *= count; + + /* see the note in malloc_nofail() of why we don't use calloc() */ + ptr = malloc(size); + + if (!ptr) { + /* LCOV_EXCL_START */ + malloc_fail(size); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + memset(ptr, 0, size); + + mcounter += size; + + return ptr; } char* strdup_nofail(const char* str) diff --git a/cmdline/util.h b/cmdline/util.h index a67d02f7..2ec09640 100644 --- a/cmdline/util.h +++ b/cmdline/util.h @@ -468,7 +468,7 @@ void* malloc_nofail(size_t size); * Safe cmalloc. * If no memory is available, it aborts. */ -void* cmalloc_nofail(size_t count, size_t size); +void* calloc_nofail(size_t count, size_t size); /** * Safe aligned malloc. diff --git a/tommyds/tommy.c b/tommyds/tommy.c index 5da142ca..53ece8c2 100644 --- a/tommyds/tommy.c +++ b/tommyds/tommy.c @@ -30,6 +30,7 @@ /* redefine the malloc for tommy use */ #define tommy_malloc malloc_nofail +#define tommy_calloc calloc_nofail #define tommy_free free #include "tommyhash.c" diff --git a/tommyds/tommyarray.c b/tommyds/tommyarray.c index 6ba6e8d6..b46879c2 100644 --- a/tommyds/tommyarray.c +++ b/tommyds/tommyarray.c @@ -27,48 +27,54 @@ #include "tommyarray.h" -#include /* for memset */ - /******************************************************************************/ /* array */ void tommy_array_init(tommy_array* array) { + unsigned i; + /* fixed initial size */ array->bucket_bit = TOMMY_ARRAY_BIT; array->bucket_max = 1 << array->bucket_bit; - array->bucket[0] = tommy_cast(void**, tommy_malloc(array->bucket_max * sizeof(void*))); + array->bucket[0] = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*))); + for (i = 1; i < TOMMY_ARRAY_BIT; ++i) + array->bucket[i] = array->bucket[0]; - /* initializes it with zeros */ - memset(array->bucket[0], 0, array->bucket_max * sizeof(void*)); - - array->bucket_mac = 1; + array->bucket_mac = TOMMY_ARRAY_BIT; array->size = 0; } void tommy_array_done(tommy_array* array) { unsigned i; - for(i=0;ibucket_mac;++i) - tommy_free(array->bucket[i]); + + tommy_free(array->bucket[0]); + for (i = TOMMY_ARRAY_BIT; i < array->bucket_mac; ++i) { + void** segment = array->bucket[i]; + tommy_free(&segment[1 << i]); + } } void tommy_array_grow(tommy_array* array, unsigned size) { - while (size > array->bucket_max) { - /* allocate one more bucket */ - array->bucket[array->bucket_mac] = tommy_cast(void**, tommy_malloc(array->bucket_max * sizeof(void*))); + if (array->size >= size) + return; + array->size = size; - /* initializes it with zeros */ - memset(array->bucket[array->bucket_mac], 0, array->bucket_max * sizeof(void*)); + while (size > array->bucket_max) { + void** segment; + + /* allocate one more segment */ + segment = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*))); + + /* store it adjusting the offset */ + array->bucket[array->bucket_mac] = &segment[-array->bucket_max]; ++array->bucket_mac; ++array->bucket_bit; array->bucket_max = 1 << array->bucket_bit; } - - if (array->size < size) - array->size = size; } tommy_size_t tommy_array_memory_usage(tommy_array* array) diff --git a/tommyds/tommyarray.h b/tommyds/tommyarray.h index 5831cd09..86fd3a12 100644 --- a/tommyds/tommyarray.h +++ b/tommyds/tommyarray.h @@ -92,22 +92,14 @@ void tommy_array_grow(tommy_array* array, unsigned size); */ tommy_inline void** tommy_array_ref(tommy_array* array, unsigned pos) { - unsigned bsr; + unsigned bsr; assert(pos < array->size); - /* special case for the first bucket */ - if (pos < (1 << TOMMY_ARRAY_BIT)) { - return &array->bucket[0][pos]; - } + /* get the highest bit set, in case of all 0, return 0 */ + bsr = tommy_ilog2_u32(pos | 1); - /* get the highest bit set */ - bsr = tommy_ilog2_u32(pos); - - /* clear the highest bit */ - pos -= 1 << bsr; - - return &array->bucket[bsr - TOMMY_ARRAY_BIT + 1][pos]; + return &array->bucket[bsr][pos]; } /** diff --git a/tommyds/tommyarrayblk.c b/tommyds/tommyarrayblk.c index 68fff233..82d29751 100644 --- a/tommyds/tommyarrayblk.c +++ b/tommyds/tommyarrayblk.c @@ -27,8 +27,6 @@ #include "tommyarrayblk.h" -#include /* for memset */ - /******************************************************************************/ /* array */ @@ -43,7 +41,7 @@ void tommy_arrayblk_done(tommy_arrayblk* array) { unsigned i; - for(i=0;iblock);++i) + for (i = 0; i < tommy_array_size(&array->block); ++i) tommy_free(tommy_array_get(&array->block, i)); tommy_array_done(&array->block); @@ -51,8 +49,15 @@ void tommy_arrayblk_done(tommy_arrayblk* array) void tommy_arrayblk_grow(tommy_arrayblk* array, unsigned size) { - unsigned block_max = (size + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE; - unsigned block_mac = tommy_array_size(&array->block); + unsigned block_max; + unsigned block_mac; + + if (array->size >= size) + return; + array->size = size; + + block_max = (size + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE; + block_mac = tommy_array_size(&array->block); if (block_mac < block_max) { /* grow the block array */ @@ -60,10 +65,7 @@ void tommy_arrayblk_grow(tommy_arrayblk* array, unsigned size) /* allocate new blocks */ while (block_mac < block_max) { - void* ptr = tommy_malloc(TOMMY_ARRAYBLK_SIZE * sizeof(void*)); - - /* initializes it with zeros */ - memset(ptr, 0, TOMMY_ARRAYBLK_SIZE * sizeof(void*)); + void* ptr = tommy_calloc(TOMMY_ARRAYBLK_SIZE, sizeof(void*)); /* set the new block */ tommy_array_set(&array->block, block_mac, ptr); @@ -71,9 +73,6 @@ void tommy_arrayblk_grow(tommy_arrayblk* array, unsigned size) ++block_mac; } } - - if (array->size < size) - array->size = size; } tommy_size_t tommy_arrayblk_memory_usage(tommy_arrayblk* array) diff --git a/tommyds/tommyarrayblk.h b/tommyds/tommyarrayblk.h index c241875a..beba5b32 100644 --- a/tommyds/tommyarrayblk.h +++ b/tommyds/tommyarrayblk.h @@ -52,7 +52,7 @@ /** * Elements for each block. */ -#define TOMMY_ARRAYBLK_SIZE (64 * 1024) +#define TOMMY_ARRAYBLK_SIZE (4 * 1024) /** * Array. diff --git a/tommyds/tommyarrayblkof.c b/tommyds/tommyarrayblkof.c index 30669093..1a7e0ba6 100644 --- a/tommyds/tommyarrayblkof.c +++ b/tommyds/tommyarrayblkof.c @@ -27,8 +27,6 @@ #include "tommyarrayblkof.h" -#include /* for memset */ - /******************************************************************************/ /* array */ @@ -43,7 +41,7 @@ void tommy_arrayblkof_done(tommy_arrayblkof* array) { unsigned i; - for(i=0;iblock);++i) + for (i = 0; i < tommy_array_size(&array->block); ++i) tommy_free(tommy_array_get(&array->block, i)); tommy_array_done(&array->block); @@ -51,8 +49,15 @@ void tommy_arrayblkof_done(tommy_arrayblkof* array) void tommy_arrayblkof_grow(tommy_arrayblkof* array, unsigned size) { - unsigned block_max = (size + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE; - unsigned block_mac = tommy_array_size(&array->block); + unsigned block_max; + unsigned block_mac; + + if (array->size >= size) + return; + array->size = size; + + block_max = (size + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE; + block_mac = tommy_array_size(&array->block); if (block_mac < block_max) { /* grow the block array */ @@ -60,10 +65,7 @@ void tommy_arrayblkof_grow(tommy_arrayblkof* array, unsigned size) /* allocate new blocks */ while (block_mac < block_max) { - void* ptr = tommy_malloc(TOMMY_ARRAYBLK_SIZE * array->element_size); - - /* initializes it with zeros */ - memset(ptr, 0, TOMMY_ARRAYBLK_SIZE * array->element_size); + void* ptr = tommy_calloc(TOMMY_ARRAYBLK_SIZE, array->element_size); /* set the new block */ tommy_array_set(&array->block, block_mac, ptr); @@ -71,9 +73,6 @@ void tommy_arrayblkof_grow(tommy_arrayblkof* array, unsigned size) ++block_mac; } } - - if (array->size < size) - array->size = size; } tommy_size_t tommy_arrayblkof_memory_usage(tommy_arrayblkof* array) diff --git a/tommyds/tommyarrayblkof.h b/tommyds/tommyarrayblkof.h index ed90a8e5..922604c1 100644 --- a/tommyds/tommyarrayblkof.h +++ b/tommyds/tommyarrayblkof.h @@ -51,7 +51,7 @@ /** * Elements for each block. */ -#define TOMMY_ARRAYBLKOF_SIZE (64 * 1024) +#define TOMMY_ARRAYBLKOF_SIZE (4 * 1024) /** * Array. diff --git a/tommyds/tommychain.h b/tommyds/tommychain.h index 40556870..1a2dc796 100644 --- a/tommyds/tommychain.h +++ b/tommyds/tommychain.h @@ -211,9 +211,9 @@ tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* while (mask != 1) { mask >>= 1; if (mask & 1) { - tommy_chain_merge_degenerated(&bit[i+1], &bit[i], cmp); + tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp); } else { - bit[i+1] = bit[i]; + bit[i + 1] = bit[i]; } ++i; } diff --git a/tommyds/tommyhash.c b/tommyds/tommyhash.c index 9b0decc4..004c2ae2 100644 --- a/tommyds/tommyhash.c +++ b/tommyds/tommyhash.c @@ -42,33 +42,33 @@ tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) #endif } -#define tommy_rot(x,k) \ - (((x)<<(k)) | ((x)>>(32-(k)))) +#define tommy_rot(x, k) \ + (((x) << (k)) | ((x) >> (32 - (k)))) -#define tommy_mix(a,b,c) \ +#define tommy_mix(a, b, c) \ do { \ a -= c; a ^= tommy_rot(c, 4); c += b; \ b -= a; b ^= tommy_rot(a, 6); a += c; \ c -= b; c ^= tommy_rot(b, 8); b += a; \ - a -= c; a ^= tommy_rot(c,16); c += b; \ - b -= a; b ^= tommy_rot(a,19); a += c; \ + a -= c; a ^= tommy_rot(c, 16); c += b; \ + b -= a; b ^= tommy_rot(a, 19); a += c; \ c -= b; c ^= tommy_rot(b, 4); b += a; \ } while (0) -#define tommy_final(a,b,c) \ +#define tommy_final(a, b, c) \ do { \ - c ^= b; c -= tommy_rot(b,14); \ - a ^= c; a -= tommy_rot(c,11); \ - b ^= a; b -= tommy_rot(a,25); \ - c ^= b; c -= tommy_rot(b,16); \ - a ^= c; a -= tommy_rot(c,4); \ - b ^= a; b -= tommy_rot(a,14); \ - c ^= b; c -= tommy_rot(b,24); \ + c ^= b; c -= tommy_rot(b, 14); \ + a ^= c; a -= tommy_rot(c, 11); \ + b ^= a; b -= tommy_rot(a, 25); \ + c ^= b; c -= tommy_rot(b, 16); \ + a ^= c; a -= tommy_rot(c, 4); \ + b ^= a; b -= tommy_rot(a, 14); \ + c ^= b; c -= tommy_rot(b, 24); \ } while (0) tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) { - const unsigned char* key = tommy_cast(const unsigned char*,void_key); + const unsigned char* key = tommy_cast(const unsigned char*, void_key); tommy_uint32_t a, b, c; a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val; @@ -78,7 +78,7 @@ tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tom b += tommy_le_uint32_read(key + 4); c += tommy_le_uint32_read(key + 8); - tommy_mix(a,b,c); + tommy_mix(a, b, c); key_len -= 12; key += 12; @@ -110,14 +110,14 @@ tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tom case 1 : a += key[0]; } - tommy_final(a,b,c); + tommy_final(a, b, c); return c; } tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len) { - const unsigned char* key = tommy_cast(const unsigned char*,void_key); + const unsigned char* key = tommy_cast(const unsigned char*, void_key); tommy_uint32_t a, b, c; a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + (init_val & 0xffffffff); @@ -128,7 +128,7 @@ tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tom b += tommy_le_uint32_read(key + 4); c += tommy_le_uint32_read(key + 8); - tommy_mix(a,b,c); + tommy_mix(a, b, c); key_len -= 12; key += 12; @@ -160,7 +160,7 @@ tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tom case 1 : a += key[0]; } - tommy_final(a,b,c); + tommy_final(a, b, c); return c + ((tommy_uint64_t)b << 32); } diff --git a/tommyds/tommyhash.h b/tommyds/tommyhash.h index 2ed8dcf6..329ef9d1 100644 --- a/tommyds/tommyhash.h +++ b/tommyds/tommyhash.h @@ -24,7 +24,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - + /** \file * Hash functions for the use with ::tommy_hashtable, ::tommy_hashdyn and ::tommy_hashlin. */ @@ -65,7 +65,7 @@ tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tom * Using a different initialization value, you can generate a completely different set of hash values. * Use 0 if not relevalt. * \param void_key Pointer at the data to hash. - * \param key_len Size of the data to hash. + * \param key_len Size of the data to hash. * \note * This function is endianess independent. * \return The hash value of 64 bits. diff --git a/tommyds/tommyhashdyn.c b/tommyds/tommyhashdyn.c index 1c1478a7..5a3fc114 100644 --- a/tommyds/tommyhashdyn.c +++ b/tommyds/tommyhashdyn.c @@ -28,8 +28,6 @@ #include "tommyhashdyn.h" #include "tommylist.h" -#include /* for memset */ - /******************************************************************************/ /* hashdyn */ @@ -39,8 +37,7 @@ void tommy_hashdyn_init(tommy_hashdyn* hashdyn) hashdyn->bucket_bit = TOMMY_HASHDYN_BIT; hashdyn->bucket_max = 1 << hashdyn->bucket_bit; hashdyn->bucket_mask = hashdyn->bucket_max - 1; - hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_malloc(hashdyn->bucket_max * sizeof(tommy_hashdyn_node*))); - memset(hashdyn->bucket, 0, hashdyn->bucket_max * sizeof(tommy_hashdyn_node*)); + hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_calloc(hashdyn->bucket_max, sizeof(tommy_hashdyn_node*))); hashdyn->count = 0; } @@ -66,6 +63,9 @@ static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, unsigned new_bucket_bit new_bucket_max = 1 << new_bucket_bit; new_bucket_mask = new_bucket_max - 1; + + /* allocate the new vector using malloc() and not calloc() */ + /* because data is fully initialized in the update process */ new_bucket = tommy_cast(tommy_hashdyn_node**, tommy_malloc(new_bucket_max * sizeof(tommy_hashdyn_node*))); /* reinsert all the elements */ @@ -73,7 +73,7 @@ static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, unsigned new_bucket_bit unsigned i; /* grow */ - for(i=0;ibucket[i]; @@ -165,28 +165,62 @@ void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) { unsigned pos = hash % hashdyn->bucket_max; - tommy_hashdyn_node* i = hashdyn->bucket[pos]; + tommy_hashdyn_node* node = hashdyn->bucket[pos]; - while (i) { + while (node) { /* we first check if the hash matches, as in the same bucket we may have multiples hash values */ - if (i->key == hash && cmp(cmp_arg, i->data) == 0) { - tommy_list_remove_existing(&hashdyn->bucket[pos], i); + if (node->key == hash && cmp(cmp_arg, node->data) == 0) { + tommy_list_remove_existing(&hashdyn->bucket[pos], node); --hashdyn->count; hashdyn_shrink_step(hashdyn); - return i->data; + return node->data; } - i = i->next; + node = node->next; } return 0; } +void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func) +{ + unsigned bucket_max = hashdyn->bucket_max; + tommy_hashdyn_node** bucket = hashdyn->bucket; + unsigned pos; + + for (pos = 0; pos < bucket_max; ++pos) { + tommy_hashdyn_node* node = bucket[pos]; + + while (node) { + void* data = node->data; + node = node->next; + func(data); + } + } +} + +void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg) +{ + unsigned bucket_max = hashdyn->bucket_max; + tommy_hashdyn_node** bucket = hashdyn->bucket; + unsigned pos; + + for (pos = 0; pos < bucket_max; ++pos) { + tommy_hashdyn_node* node = bucket[pos]; + + while (node) { + void* data = node->data; + node = node->next; + func(arg, data); + } + } +} + tommy_size_t tommy_hashdyn_memory_usage(tommy_hashdyn* hashdyn) { return hashdyn->bucket_max * (tommy_size_t)sizeof(hashdyn->bucket[0]) - + tommy_hashdyn_count(hashdyn) * (tommy_size_t)sizeof(tommy_hashdyn_node); + + tommy_hashdyn_count(hashdyn) * (tommy_size_t)sizeof(tommy_hashdyn_node); } diff --git a/tommyds/tommyhashdyn.h b/tommyds/tommyhashdyn.h index 591fe138..b706df92 100644 --- a/tommyds/tommyhashdyn.h +++ b/tommyds/tommyhashdyn.h @@ -32,15 +32,15 @@ * the size then it reaches a load factor greater than 0.5 and it halves the size with a load * factor lower than 0.125. * - * All the elements are reallocated in a single resize operation done inside + * All the elements are reallocated in a single resize operation done inside * tommy_hashdyn_insert() or tommy_hashdyn_remove(). * - * Note that the resize operation takes approximatively 100 [ms] with 1 million of elements, + * Note that the resize operation takes approximatively 100 [ms] with 1 million of elements, * and 1 [second] with 10 millions. This could be a problem in real-time applications. * - * The resize also fragment the heap, as it involves allocating a double-sized table, copy elements, + * The resize also fragment the heap, as it involves allocating a double-sized table, copy elements, * and deallocating the older table. Leaving a big hole in the heap. - * + * * The ::tommy_hashlin hashtable fixes both problems. * * To initialize the hashtable you have to call tommy_hashdyn_init(). @@ -81,7 +81,7 @@ * return *(const int*)arg != ((const struct object*)obj)->value; * } * - * int value_to_find = 1; + * int value_to_find = 1; * struct object* obj = tommy_hashdyn_search(&hashdyn, compare, &value_to_find, tommy_inthash_u32(value_to_find)); * if (!obj) { * // not found @@ -96,7 +96,7 @@ * different keys. * * \code - * int value_to_find = 1; + * int value_to_find = 1; * tommy_node* i = tommy_hashdyn_bucket(&hashdyn, tommy_inthash_u32(value_to_find)); * while (i) { * struct object* obj = i->data; // gets the object pointer @@ -129,7 +129,7 @@ * * Note that you cannot iterates over all the elements in the hashtable using the * hashtable itself. You have to insert all the elements also in a ::tommy_list, - * and use the list to iterate. See the \ref multiindex example for more detail. + * and use the list to iterate. See the \ref multiindex example for more detail. */ #ifndef __TOMMYHASHDYN_H @@ -200,7 +200,7 @@ void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const * The bucket is guaranteed to contain ALL the elements with the specified hash, * but it can contain also others. * You can access elements in the bucket following the ::next pointer until 0. - * \param hash Hash of the element to find. + * \param hash Hash of the element to find. * \return The head of the bucket, or 0 if empty. */ tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash) @@ -221,6 +221,7 @@ tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, to tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) { tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash); + while (i) { /* we first check if the hash matches, as in the same bucket we may have multiples hash values */ if (i->key == hash && cmp(cmp_arg, i->data) == 0) @@ -237,6 +238,16 @@ tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_fun */ void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node); +/** + * Calls the specified function for each element in the hashtable. + */ +void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func); + +/** + * Calls the specified function with argument for each element in the hashtable. + */ +void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg); + /** * Gets the number of elements. */ diff --git a/tommyds/tommylist.h b/tommyds/tommylist.h index d4a3ee23..1725923b 100644 --- a/tommyds/tommylist.h +++ b/tommyds/tommylist.h @@ -96,7 +96,7 @@ * * i = i_next; // goes to the next element * } - * \endcode + * \endcode */ #ifndef __TOMMYLIST_H @@ -151,7 +151,7 @@ tommy_inline tommy_node* tommy_list_tail(tommy_list* list) */ tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node) { - /* one element "circular" prev list */ + /* one element "circular" prev list */ node->prev = node; /* one element "0 terminated" next list */ @@ -264,7 +264,7 @@ tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node tommy_node* head = tommy_list_head(list); /* remove from the "circular" prev list */ - if (node->next) { + if (node->next) { node->next->prev = node->prev; } else { head->prev = node->prev; /* the last */ @@ -313,6 +313,7 @@ tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list) tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func) { tommy_node* node = tommy_list_head(list); + while (node) { void* data = node->data; node = node->next; @@ -326,6 +327,7 @@ tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func) tommy_inline void tommy_list_foreach_arg(tommy_list* list, tommy_foreach_arg_func* func, void* arg) { tommy_node* node = tommy_list_head(list); + while (node) { void* data = node->data; node = node->next; diff --git a/tommyds/tommytypes.h b/tommyds/tommytypes.h index 27bf9fe4..fc58095c 100644 --- a/tommyds/tommytypes.h +++ b/tommyds/tommytypes.h @@ -64,16 +64,25 @@ typedef int tommy_bool_t; /**< Generic boolean type. */ /******************************************************************************/ /* heap */ -/* by default uses malloc/realloc/free */ +/* by default uses malloc/calloc/realloc/free */ /** - * Generic malloc(), realloc() and free() functions. - * Redefine them to what you need. By default they map to the C malloc(), realloc() and free(). + * Generic malloc(), calloc(), realloc() and free() functions. + * Redefine them to what you need. By default they map to the C malloc(), calloc(), realloc() and free(). */ -#if !defined(tommy_malloc) && !defined(tommy_realloc) && !defined(tommy_free) +#if !defined(tommy_malloc) || !defined(tommy_calloc) || !defined(tommy_realloc) || !defined(tommy_free) #include +#endif +#if !defined(tommy_malloc) #define tommy_malloc malloc +#endif +#if !defined(tommy_calloc) +#define tommy_calloc calloc +#endif +#if !defined(tommy_realloc) #define tommy_realloc realloc +#endif +#if !defined(tommy_free) #define tommy_free free #endif @@ -109,7 +118,7 @@ typedef int tommy_bool_t; /**< Generic boolean type. */ */ #if !defined(tommy_likely) #if defined(__GNUC__) -#define tommy_likely(x) __builtin_expect(!!(x),1) +#define tommy_likely(x) __builtin_expect(!!(x), 1) #else #define tommy_likely(x) (x) #endif @@ -120,7 +129,7 @@ typedef int tommy_bool_t; /**< Generic boolean type. */ */ #if !defined(tommy_unlikely) #if defined(__GNUC__) -#define tommy_unlikely(x) __builtin_expect(!!(x),0) +#define tommy_unlikely(x) __builtin_expect(!!(x), 0) #else #define tommy_unlikely(x) (x) #endif @@ -235,14 +244,14 @@ typedef int tommy_compare_func(const void* obj_a, const void* obj_b); * return *(const int*)arg != ((const struct object*)obj)->value; * } * - * int value_to_find = 1; + * int value_to_find = 1; * struct object* obj = tommy_hashtable_search(&hashtable, compare, &value_to_find, tommy_inthash_u32(value_to_find)); * if (!obj) { * // not found * } else { * // found * } - * \endcode + * \endcode * */ typedef int tommy_search_func(const void* arg, const void* obj); @@ -278,7 +287,7 @@ typedef void tommy_foreach_arg_func(void* arg, void* obj); * Integer log2 for constants. * You can use it only for exact power of 2 up to 256. */ -#define TOMMY_ILOG2(value) ((value) == 256 ? 8 : (value) == 128 ? 7 :(value) == 64 ? 6 : (value) == 32 ? 5 : (value) == 16 ? 4 : (value) == 8 ? 3 : (value) == 4 ? 2 : (value) == 2 ? 1 : 0) +#define TOMMY_ILOG2(value) ((value) == 256 ? 8 : (value) == 128 ? 7 : (value) == 64 ? 6 : (value) == 32 ? 5 : (value) == 16 ? 4 : (value) == 8 ? 3 : (value) == 4 ? 2 : (value) == 2 ? 1 : 0) /** * Bit scan reverse or integer log2. @@ -288,9 +297,9 @@ typedef void tommy_foreach_arg_func(void* arg, void* obj); * To force a return 0 in this case, you can use tommy_ilog2(value | 1). * * Other interesting ways for bitscan can be found at: - * - * Bit Twiddling Hacks - * http://graphics.stanford.edu/~seander/bithacks.html + * + * Bit Twiddling Hacks + * http://graphics.stanford.edu/~seander/bithacks.html * * Chess Programming BitScan * http://chessprogramming.wikispaces.com/BitScan @@ -356,7 +365,7 @@ tommy_inline unsigned tommy_ctz_u32(tommy_uint32_t value) 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 }; - return TOMMY_DE_BRUIJN_INDEX_CTZ[(tommy_uint32_t)(((value & -value) * 0x077CB531U)) >> 27]; + return TOMMY_DE_BRUIJN_INDEX_CTZ[(tommy_uint32_t)(((value & - value) * 0x077CB531U)) >> 27]; #endif }