mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
Updates with latest tommyds library.
This commit is contained in:
parent
eeea58b42a
commit
d84babb6bd
16 changed files with 189 additions and 118 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -27,48 +27,54 @@
|
|||
|
||||
#include "tommyarray.h"
|
||||
|
||||
#include <string.h> /* 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;i<array->bucket_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)
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
#include "tommyarrayblk.h"
|
||||
|
||||
#include <string.h> /* for memset */
|
||||
|
||||
/******************************************************************************/
|
||||
/* array */
|
||||
|
||||
|
|
@ -43,7 +41,7 @@ void tommy_arrayblk_done(tommy_arrayblk* array)
|
|||
{
|
||||
unsigned i;
|
||||
|
||||
for(i=0;i<tommy_array_size(&array->block);++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)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
/**
|
||||
* Elements for each block.
|
||||
*/
|
||||
#define TOMMY_ARRAYBLK_SIZE (64 * 1024)
|
||||
#define TOMMY_ARRAYBLK_SIZE (4 * 1024)
|
||||
|
||||
/**
|
||||
* Array.
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
#include "tommyarrayblkof.h"
|
||||
|
||||
#include <string.h> /* for memset */
|
||||
|
||||
/******************************************************************************/
|
||||
/* array */
|
||||
|
||||
|
|
@ -43,7 +41,7 @@ void tommy_arrayblkof_done(tommy_arrayblkof* array)
|
|||
{
|
||||
unsigned i;
|
||||
|
||||
for(i=0;i<tommy_array_size(&array->block);++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)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
/**
|
||||
* Elements for each block.
|
||||
*/
|
||||
#define TOMMY_ARRAYBLKOF_SIZE (64 * 1024)
|
||||
#define TOMMY_ARRAYBLKOF_SIZE (4 * 1024)
|
||||
|
||||
/**
|
||||
* Array.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@
|
|||
#include "tommyhashdyn.h"
|
||||
#include "tommylist.h"
|
||||
|
||||
#include <string.h> /* 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;i<bucket_max;++i) {
|
||||
for (i = 0; i < bucket_max; ++i) {
|
||||
tommy_hashdyn_node* j;
|
||||
|
||||
/* setup the new two buckets */
|
||||
|
|
@ -96,7 +96,7 @@ static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, unsigned new_bucket_bit
|
|||
unsigned i;
|
||||
|
||||
/* shrink */
|
||||
for(i=0;i<new_bucket_max;++i) {
|
||||
for (i = 0; i < new_bucket_max; ++i) {
|
||||
/* setup the new bucket with the lower bucket*/
|
||||
new_bucket[i] = hashdyn->bucket[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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 <stdlib.h>
|
||||
#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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue