Add hash and rbtree delete callback, cleanup the code and improve performance (hash as a new internal structure).

We still need a hash function for removing a node from the hash and destroying it at the same time.



SVN revision: 36222
This commit is contained in:
Cedric BAIL 2008-09-24 17:14:29 +00:00
parent 5ed8ea7e09
commit 550ebc9ab1
10 changed files with 286 additions and 178 deletions

View File

@ -64,9 +64,10 @@ EAPI int eina_hash_shutdown(void);
EAPI Eina_Hash * eina_hash_new(Eina_Key_Length key_length_cb,
Eina_Key_Cmp key_cmp_cb,
Eina_Key_Hash key_hash_cb);
EAPI Eina_Hash * eina_hash_string_djb2_new(void);
EAPI Eina_Hash * eina_hash_string_superfast_new(void);
Eina_Key_Hash key_hash_cb,
Eina_Free_Cb data_free_cb);
EAPI Eina_Hash * eina_hash_string_djb2_new(Eina_Free_Cb data_free_cb);
EAPI Eina_Hash * eina_hash_string_superfast_new(Eina_Free_Cb data_free_cb);
EAPI Eina_Bool eina_hash_add(Eina_Hash *hash, const void *key, const void *data);
EAPI Eina_Bool eina_hash_direct_add(Eina_Hash *hash, const void *key, const void *data);

View File

@ -50,12 +50,12 @@ typedef Eina_Rbtree_Direction (*Eina_Rbtree_Cmp_Node_Cb)(const Eina_Rbtree *left
typedef int (*Eina_Rbtree_Cmp_Key_Cb)(const Eina_Rbtree *node, const void *key, int length, void *data);
#define EINA_RBTREE_CMP_KEY_CB(Function) ((Eina_Rbtree_Cmp_Key_Cb) Function)
typedef void (*Eina_Rbtree_Free_Cb)(Eina_Rbtree *node);
typedef void (*Eina_Rbtree_Free_Cb)(Eina_Rbtree *node, void *data);
#define EINA_RBTREE_FREE_CB(Function) ((Eina_Rbtree_Free_Cb) Function)
EAPI Eina_Rbtree *eina_rbtree_inline_insert(Eina_Rbtree *root, Eina_Rbtree *node, Eina_Rbtree_Cmp_Node_Cb cmp, const void *data);
EAPI Eina_Rbtree *eina_rbtree_inline_remove(Eina_Rbtree *root, Eina_Rbtree *node, Eina_Rbtree_Cmp_Node_Cb cmp, const void *data);
EAPI void eina_rbtree_delete(Eina_Rbtree *root, Eina_Rbtree_Free_Cb func);
EAPI void eina_rbtree_delete(Eina_Rbtree *root, Eina_Rbtree_Free_Cb func, void *data);
static inline Eina_Rbtree *eina_rbtree_inline_lookup(Eina_Rbtree *root, const void *key, int length, Eina_Rbtree_Cmp_Key_Cb cmp, const void *data);

View File

@ -79,5 +79,7 @@ typedef Eina_Bool (*Eina_Each)(const void *container,
void *fdata);
#define EINA_EACH(Function) ((Eina_Each)Function)
typedef void (*Eina_Free_Cb)(void *data);
#define EINA_FREE_CB(Function) ((Eina_Free_Cb)Function)
#endif /* EINA_TYPES_H_ */

View File

@ -38,6 +38,11 @@
* @cond LOCAL
*/
#define EINA_HASH_BUCKET_SIZE 256
#define EINA_HASH_BUCKET_MASK 0xFF
#define EINA_HASH_RBTREE_MASK 0xFFF
typedef struct _Eina_Hash_Head Eina_Hash_Head;
typedef struct _Eina_Hash_El Eina_Hash_El;
typedef struct _Eina_Hash_Foreach Eina_Hash_Foreach;
typedef struct _Eina_Iterator_Hash Eina_Iterator_Hash;
@ -48,15 +53,25 @@ struct _Eina_Hash
Eina_Key_Length key_length_cb;
Eina_Key_Cmp key_cmp_cb;
Eina_Key_Hash key_hash_cb;
Eina_Free_Cb data_free_cb;
Eina_Rbtree *buckets[256];
Eina_Rbtree *buckets[EINA_HASH_BUCKET_SIZE];
int population;
};
struct _Eina_Hash_Head
{
EINA_RBTREE;
int hash;
Eina_Rbtree *head;
};
struct _Eina_Hash_El
{
Eina_Rbtree _node_data;
EINA_RBTREE;
Eina_Hash_Tuple tuple;
Eina_Bool begin : 1;
};
struct _Eina_Hash_Foreach
@ -76,6 +91,8 @@ struct _Eina_Iterator_Hash
const Eina_Hash *hash;
Eina_Iterator *current;
Eina_Iterator *list;
Eina_Hash_Head *eh;
Eina_Hash_El *el;
int bucket;
@ -84,10 +101,13 @@ struct _Eina_Iterator_Hash
struct _Eina_Hash_Each
{
Eina_Hash_Head *eh;
const Eina_Hash_El *el;
const void *data;
};
static int _eina_hash_init_count = 0;
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
@ -100,49 +120,162 @@ struct _Eina_Hash_Each
#endif
static inline int
_eina_hash_rbtree_key(const Eina_Hash_El *el, const Eina_Hash_Tuple *tuple, __UNUSED__ int key_length, Eina_Key_Cmp cmp)
_eina_hash_hash_rbtree_cmp_hash(const Eina_Hash_Head *eh, const int *hash, __UNUSED__ int key_length, __UNUSED__ void *data)
{
int result;
result = cmp(el->tuple.key, el->tuple.key_length, tuple->key, tuple->key_length);
if (result == 0)
if (tuple->data && el->tuple.data != tuple->data)
return 1;
return result;
return eh->hash - *hash;
}
static Eina_Rbtree_Direction
_eina_hash_rbtree_node(const Eina_Hash_El *left, const Eina_Hash_El *right, Eina_Key_Cmp cmp)
_eina_hash_hash_rbtree_cmp_node(const Eina_Hash_Head *left, const Eina_Hash_Head *right, __UNUSED__ void *data)
{
if (cmp(left->tuple.key, left->tuple.key_length, right->tuple.key, right->tuple.key_length) < 0)
if (left->hash - right->hash < 0)
return EINA_RBTREE_LEFT;
return EINA_RBTREE_RIGHT;
}
static Eina_Bool
_eina_hash_rbtree_each(__UNUSED__ const Eina_Rbtree *container, const Eina_Hash_El *el, Eina_Hash_Each *data)
static inline int
_eina_hash_key_rbtree_cmp_key_data(const Eina_Hash_El *el, const Eina_Hash_Tuple *tuple, __UNUSED__ unsigned int key_length, Eina_Key_Cmp cmp)
{
if (el->tuple.data == data->data)
int result;
result = cmp(el->tuple.key, el->tuple.key_length, tuple->key, tuple->key_length);
if (result == 0 && tuple->data && tuple->data != el->tuple.data)
return 1;
return result;
}
static Eina_Rbtree_Direction
_eina_hash_key_rbtree_cmp_node(const Eina_Hash_El *left, const Eina_Hash_El *right, Eina_Key_Cmp cmp)
{
int result;
result = cmp(left->tuple.key, left->tuple.key_length,
right->tuple.key, right->tuple.key_length);
if (result < 0)
return EINA_RBTREE_LEFT;
return EINA_RBTREE_RIGHT;
}
static inline Eina_Bool
eina_hash_add_alloc_by_hash(Eina_Hash *hash,
const void *key, int key_length, int alloc_length,
int key_hash,
const void *data)
{
Eina_Hash_El *el = NULL;
Eina_Hash_Head *eh;
Eina_Error error = 0;
int hash_num;
if ((!hash) || (!key) || (!data)) goto on_error;
error = EINA_ERROR_OUT_OF_MEMORY;
/* Apply eina mask to hash. */
hash_num = key_hash & EINA_HASH_BUCKET_MASK;
key_hash &= EINA_HASH_RBTREE_MASK;
/* Look up for head node. */
eh = (Eina_Hash_Head*) eina_rbtree_inline_lookup(hash->buckets[hash_num],
&key_hash, 0,
EINA_RBTREE_CMP_KEY_CB(_eina_hash_hash_rbtree_cmp_hash), NULL);
if (!eh)
{
data->el = el;
return EINA_FALSE;
/* If not found allocate it and a element. */
eh = malloc(sizeof (Eina_Hash_Head) + sizeof (Eina_Hash_El) + alloc_length);
if (!eh) goto on_error;
eh->hash = key_hash;
eh->head = NULL;
hash->buckets[hash_num] = eina_rbtree_inline_insert(hash->buckets[hash_num], EINA_RBTREE_GET(eh),
EINA_RBTREE_CMP_NODE_CB(_eina_hash_hash_rbtree_cmp_node), NULL);
el = (Eina_Hash_El*) (eh + 1);
el->begin = EINA_TRUE;
}
if (!el)
{
/*
Alloc every needed things
(No more lookup as we expect to support more than one item for one key).
*/
el = malloc(sizeof (Eina_Hash_El) + alloc_length);
if (!el) goto on_error;
el->begin = EINA_FALSE;
}
/* Setup the element */
el->tuple.key_length = key_length;
el->tuple.data = (void *) data;
if (alloc_length > 0)
{
el->tuple.key = (char *) (el + 1);
memcpy((char *) el->tuple.key, key, alloc_length);
}
else
{
el->tuple.key = key;
}
/* add the new element to the hash. */
eh->head = eina_rbtree_inline_insert(eh->head, EINA_RBTREE_GET(el),
EINA_RBTREE_CMP_NODE_CB(_eina_hash_key_rbtree_cmp_node), hash->key_cmp_cb);
hash->population++;
return EINA_TRUE;
on_error:
eina_error_set(error);
return EINA_FALSE;
}
static Eina_Bool
_eina_hash_rbtree_each(__UNUSED__ const Eina_Rbtree *container, const Eina_Hash_Head *eh, Eina_Hash_Each *data)
{
Eina_Iterator *it;
Eina_Hash_El *el;
Eina_Bool found = EINA_TRUE;
it = eina_rbtree_iterator_prefix(eh->head);
while (eina_iterator_next(it, (void**) &el))
{
if (el->tuple.data == data->data)
{
data->el = el;
data->eh = (Eina_Hash_Head*) eh;
found = EINA_FALSE;
break ;
}
}
eina_iterator_free(it);
return found;
}
static inline Eina_Hash_El *
_eina_hash_find_by_hash(const Eina_Hash *hash, Eina_Hash_Tuple *tuple, int key_hash)
_eina_hash_find_by_hash(const Eina_Hash *hash, Eina_Hash_Tuple *tuple, int key_hash, Eina_Hash_Head **eh)
{
Eina_Hash_El *el;
int rb_hash = key_hash & EINA_HASH_RBTREE_MASK;
key_hash &= 0xFF;
key_hash &= EINA_HASH_BUCKET_MASK;
*eh = (Eina_Hash_Head*) eina_rbtree_inline_lookup(hash->buckets[key_hash],
&rb_hash, 0,
EINA_RBTREE_CMP_KEY_CB(_eina_hash_hash_rbtree_cmp_hash), NULL);
if (!*eh) return NULL;
el = (Eina_Hash_El*) eina_rbtree_inline_lookup((*eh)->head,
tuple, 0,
EINA_RBTREE_CMP_KEY_CB(_eina_hash_key_rbtree_cmp_key_data), hash->key_cmp_cb);
el = (Eina_Hash_El*) eina_rbtree_inline_lookup(hash->buckets[key_hash], tuple, sizeof (Eina_Hash_Tuple), EINA_RBTREE_CMP_KEY_CB(_eina_hash_rbtree_key), hash->key_cmp_cb);
return el;
}
static inline Eina_Hash_El *
_eina_hash_find_by_data(const Eina_Hash *hash, const void *data, int *key_hash)
_eina_hash_find_by_data(const Eina_Hash *hash, const void *data, int *key_hash, Eina_Hash_Head **eh)
{
Eina_Hash_Each each;
Eina_Iterator *it;
@ -151,7 +284,7 @@ _eina_hash_find_by_data(const Eina_Hash *hash, const void *data, int *key_hash)
each.el = NULL;
each.data = data;
for (hash_num = 0; hash_num < 256; hash_num++)
for (hash_num = 0; hash_num < EINA_HASH_BUCKET_SIZE; hash_num++)
{
it = eina_rbtree_iterator_prefix(hash->buckets[hash_num]);
eina_iterator_foreach(it, EINA_EACH(_eina_hash_rbtree_each), &each);
@ -160,6 +293,7 @@ _eina_hash_find_by_data(const Eina_Hash *hash, const void *data, int *key_hash)
if (each.el)
{
*key_hash = hash_num;
*eh = each.eh;
return (Eina_Hash_El*) each.el;
}
}
@ -167,6 +301,21 @@ _eina_hash_find_by_data(const Eina_Hash *hash, const void *data, int *key_hash)
return NULL;
}
static void
_eina_hash_el_free(Eina_Hash_El *el, Eina_Hash *hash)
{
if (el->begin == EINA_FALSE) free(el);
if (hash->data_free_cb)
hash->data_free_cb(el->tuple.data);
}
static void
_eina_hash_head_free(Eina_Hash_Head *eh, Eina_Hash *hash)
{
eina_rbtree_delete(eh->head, EINA_RBTREE_FREE_CB(_eina_hash_el_free), hash);
free(eh);
}
static unsigned int
_eina_string_key_length(const char *key)
{
@ -229,11 +378,23 @@ _eina_hash_iterator_next(Eina_Iterator_Hash *it, void **data)
}
else
{
ok = eina_iterator_next(it->current, (void**) &it->el);
ok = eina_iterator_next(it->list, (void**) &it->el);
if (!ok)
{
eina_iterator_free(it->current);
it->current = NULL;
eina_iterator_free(it->list);
it->list = NULL;
ok = eina_iterator_next(it->current, (void**) &it->eh);
if (!ok)
{
eina_iterator_free(it->current);
it->current = NULL;
}
else
{
it->list = eina_rbtree_iterator_prefix(it->eh->head);
ok = eina_iterator_next(it->list, (void**) &it->el);
}
}
bucket = it->bucket;
@ -241,18 +402,20 @@ _eina_hash_iterator_next(Eina_Iterator_Hash *it, void **data)
if (ok == EINA_FALSE)
{
while (bucket < 256)
while (bucket < EINA_HASH_BUCKET_SIZE)
{
if (it->hash->buckets[bucket] != NULL)
{
it->current = eina_rbtree_iterator_prefix(it->hash->buckets[bucket]);
ok = eina_iterator_next(it->current, (void**) &it->el);
ok = eina_iterator_next(it->current, (void**) &it->eh);
if (ok) break ;
eina_iterator_free(it->current);
it->current = NULL;
}
++bucket;
}
it->list = eina_rbtree_iterator_prefix(it->eh->head);
ok = eina_iterator_next(it->list, (void**) &it->el);
}
it->index++;
@ -339,7 +502,10 @@ _eina_hash_iterator_free(Eina_Iterator_Hash *it)
EAPI int
eina_hash_init(void)
{
return eina_error_init();
if (!_eina_hash_init_count)
eina_error_init();
return ++_eina_hash_init_count;
}
/**
@ -356,13 +522,16 @@ eina_hash_init(void)
EAPI int
eina_hash_shutdown(void)
{
return eina_error_shutdown();
if (_eina_hash_init_count == 1)
eina_error_shutdown();
return --_eina_hash_init_count;
}
EAPI Eina_Hash *
eina_hash_new(Eina_Key_Length key_length_cb,
Eina_Key_Cmp key_cmp_cb,
Eina_Key_Hash key_hash_cb)
Eina_Key_Hash key_hash_cb,
Eina_Free_Cb data_free_cb)
{
/* FIXME: Use mempool. */
Eina_Hash *new;
@ -370,12 +539,16 @@ eina_hash_new(Eina_Key_Length key_length_cb,
eina_error_set(0);
if (!key_length_cb || !key_cmp_cb) return NULL;
new = calloc(1, sizeof (Eina_Hash));
new = malloc(sizeof (Eina_Hash));
if (!new) goto on_error;
new->key_length_cb = key_length_cb;
new->key_cmp_cb = key_cmp_cb;
new->key_hash_cb = key_hash_cb;
new->data_free_cb = data_free_cb;
new->population = 0;
memset(new->buckets, 0, sizeof (new->buckets));
return new;
@ -385,19 +558,21 @@ eina_hash_new(Eina_Key_Length key_length_cb,
}
EAPI Eina_Hash *
eina_hash_string_djb2_new(void)
eina_hash_string_djb2_new(Eina_Free_Cb data_free_cb)
{
return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
EINA_KEY_CMP(_eina_string_key_cmp),
EINA_KEY_HASH(eina_hash_djb2));
EINA_KEY_HASH(eina_hash_djb2),
data_free_cb);
}
EAPI Eina_Hash *
eina_hash_string_superfast_new(void)
eina_hash_string_superfast_new(Eina_Free_Cb data_free_cb)
{
return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length),
EINA_KEY_CMP(_eina_string_key_cmp),
EINA_KEY_HASH(eina_hash_superfast));
EINA_KEY_HASH(eina_hash_superfast),
data_free_cb);
}
/**
@ -437,18 +612,8 @@ eina_hash_free(Eina_Hash *hash)
if (!hash) return;
/* FIXME: Should have used an iterator. */
for (i = 0; i < 256; i++)
{
while (hash->buckets[i])
{
Eina_Rbtree *el;
el = hash->buckets[i];
hash->buckets[i] = eina_rbtree_inline_remove(hash->buckets[i], el, EINA_RBTREE_CMP_NODE_CB(_eina_hash_rbtree_node), hash->key_cmp_cb);
free(el);
}
}
for (i = 0; i < EINA_HASH_BUCKET_SIZE; i++)
eina_rbtree_delete(hash->buckets[i], EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash);
free(hash);
}
@ -481,32 +646,7 @@ eina_hash_add_by_hash(Eina_Hash *hash,
const void *key, int key_length, int key_hash,
const void *data)
{
Eina_Hash_El *el;
eina_error_set(0);
if ((!hash) || (!key) || (!data)) return EINA_FALSE;
/* Alloc every needed thing.*/
el = malloc(sizeof (Eina_Hash_El) + key_length);
if (!el) goto on_error;
/* Setup the element */
el->tuple.key_length = key_length;
el->tuple.data = (void *) data;
el->tuple.key = (char *) (el + 1);
memcpy((char *) el->tuple.key, key, key_length);
/* eina hash have 256 buckets. */
key_hash &= 0xFF;
/* add the new element to the hash. */
hash->buckets[key_hash] = eina_rbtree_inline_insert(hash->buckets[key_hash], &el->_node_data, EINA_RBTREE_CMP_NODE_CB(_eina_hash_rbtree_node), hash->key_cmp_cb);
hash->population++;
return EINA_TRUE;
on_error:
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
return EINA_FALSE;
return eina_hash_add_alloc_by_hash(hash, key, key_length, key_length, key_hash, data);
}
/**
@ -539,31 +679,7 @@ eina_hash_direct_add_by_hash(Eina_Hash *hash,
const void *key, int key_length, int key_hash,
const void *data)
{
Eina_Hash_El *el;
eina_error_set(0);
if ((!hash) || (!key) || (!data)) return EINA_FALSE;
/* Alloc every needed thing.*/
el = malloc(sizeof (Eina_Hash_El));
if (!el) goto on_error;
/* Setup the element */
el->tuple.key_length = key_length;
el->tuple.data = (void *) data;
el->tuple.key = key;
/* eina hash have 256 buckets. */
key_hash &= 0xFF;
/* add the new element to the hash. */
hash->buckets[key_hash] = eina_rbtree_inline_insert(hash->buckets[key_hash], &el->_node_data, EINA_RBTREE_CMP_NODE_CB(_eina_hash_rbtree_node), hash->key_cmp_cb);
hash->population++;
return EINA_TRUE;
on_error:
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
return EINA_FALSE;
return eina_hash_add_alloc_by_hash(hash, key, key_length, 0, key_hash, data);
}
/**
@ -653,6 +769,7 @@ EAPI Eina_Bool
eina_hash_del_by_hash(Eina_Hash *hash, const void *key, int key_length, int key_hash, const void *data)
{
Eina_Hash_El *el = NULL;
Eina_Hash_Head *eh;
Eina_Hash_Tuple tuple;
tuple.key = (void *) key;
@ -660,16 +777,23 @@ eina_hash_del_by_hash(Eina_Hash *hash, const void *key, int key_length, int key_
tuple.data = (void *) data;
if (!hash) return EINA_FALSE;
if (!key) el = _eina_hash_find_by_data(hash, data, &key_hash);
else el = _eina_hash_find_by_hash(hash, &tuple, key_hash);
if (!key) el = _eina_hash_find_by_data(hash, data, &key_hash, &eh);
else el = _eina_hash_find_by_hash(hash, &tuple, key_hash, &eh);
if (!el) return EINA_FALSE;
if (data && el->tuple.data != data) return EINA_FALSE;
key_hash &= 0xFF;
eh->head = eina_rbtree_inline_remove(eh->head, EINA_RBTREE_GET(el), EINA_RBTREE_CMP_NODE_CB(_eina_hash_key_rbtree_cmp_node), hash->key_cmp_cb);
if (el->begin == EINA_FALSE) free(el);
if (!eh->head)
{
key_hash &= EINA_HASH_BUCKET_MASK;
hash->buckets[key_hash] = eina_rbtree_inline_remove(hash->buckets[key_hash], EINA_RBTREE_GET(eh), EINA_RBTREE_CMP_NODE_CB(_eina_hash_hash_rbtree_cmp_node), NULL);
free(eh);
}
hash->buckets[key_hash] = eina_rbtree_inline_remove(hash->buckets[key_hash], &el->_node_data, EINA_RBTREE_CMP_NODE_CB(_eina_hash_rbtree_node), hash->key_cmp_cb);
free(el);
hash->population--;
return EINA_TRUE;
@ -717,6 +841,7 @@ eina_hash_del(Eina_Hash *hash, const void *key, const void *data)
EAPI void *
eina_hash_find_by_hash(const Eina_Hash *hash, const void *key, int key_length, int key_hash)
{
Eina_Hash_Head *eh;
Eina_Hash_El *el;
Eina_Hash_Tuple tuple;
@ -726,7 +851,7 @@ eina_hash_find_by_hash(const Eina_Hash *hash, const void *key, int key_length, i
tuple.key_length = key_length;
tuple.data = NULL;
el = _eina_hash_find_by_hash(hash, &tuple, key_hash);
el = _eina_hash_find_by_hash(hash, &tuple, key_hash, &eh);
if (el) return el->tuple.data;
return NULL;
}
@ -766,6 +891,7 @@ eina_hash_find(const Eina_Hash *hash, const void *key)
EAPI void *
eina_hash_modify_by_hash(Eina_Hash *hash, const void *key, int key_length, int key_hash, const void *data)
{
Eina_Hash_Head *eh;
Eina_Hash_El *el;
void *old_data = NULL;
Eina_Hash_Tuple tuple;
@ -776,7 +902,7 @@ eina_hash_modify_by_hash(Eina_Hash *hash, const void *key, int key_length, int k
tuple.key_length = key_length;
tuple.data = NULL;
el = _eina_hash_find_by_hash(hash, &tuple, key_hash);
el = _eina_hash_find_by_hash(hash, &tuple, key_hash, &eh);
if (el)
{
old_data = el->tuple.data;

View File

@ -113,7 +113,7 @@ eina_mempool_init(void)
eina_module_init();
EINA_ERROR_NOT_MEMPOOL_MODULE = eina_error_msg_register("Not a memory pool module.");
_backends = eina_hash_string_superfast_new();
_backends = eina_hash_string_superfast_new(NULL);
/* dynamic backends */
_modules = eina_module_list_get(PACKAGE_LIB_DIR "/eina/mp/", 0, NULL, NULL);
eina_module_list_load(_modules);

View File

@ -448,12 +448,12 @@ eina_rbtree_iterator_postfix(const Eina_Rbtree *root)
}
EAPI void
eina_rbtree_delete(Eina_Rbtree *root, Eina_Rbtree_Free_Cb func)
eina_rbtree_delete(Eina_Rbtree *root, Eina_Rbtree_Free_Cb func, void *data)
{
if (!root) return ;
eina_rbtree_delete(root->son[0], func);
eina_rbtree_delete(root->son[1], func);
func(root);
eina_rbtree_delete(root->son[0], func, data);
eina_rbtree_delete(root->son[1], func, data);
func(root, data);
}

View File

@ -129,7 +129,7 @@ _eina_stringshare_node(const Eina_Stringshare_Head *left, const Eina_Stringshare
}
static void
_eina_stringshare_head_free(Eina_Stringshare_Head *ed)
_eina_stringshare_head_free(Eina_Stringshare_Head *ed, __UNUSED__ void *data)
{
while (ed->head)
{
@ -234,7 +234,7 @@ eina_stringshare_shutdown()
/* remove any string still in the table */
for (i = 0; i < EINA_STRINGSHARE_BUCKETS; i++)
{
eina_rbtree_delete(EINA_RBTREE_GET(share->buckets[i]), EINA_RBTREE_FREE_CB(_eina_stringshare_head_free));
eina_rbtree_delete(EINA_RBTREE_GET(share->buckets[i]), EINA_RBTREE_FREE_CB(_eina_stringshare_head_free), NULL);
share->buckets[i] = NULL;
}
free(share);

View File

@ -66,6 +66,12 @@ _eina_bench_rbtree_key(const Eina_Bench_Rbtree *node, const char *key, int lengt
return strncmp(node->key, key, length);
}
static void
_eina_bench_rbtree_free(Eina_Rbtree *node, __UNUSED__ void *data)
{
free(node);
}
static void
eina_bench_lookup_rbtree(int request)
{
@ -97,26 +103,17 @@ eina_bench_lookup_rbtree(int request)
tmp = eina_rbtree_inline_lookup(root, tmp_key, 10, EINA_RBTREE_CMP_KEY_CB(_eina_bench_rbtree_key), NULL);
}
while (root)
{
tmp = root;
root = eina_rbtree_inline_remove(root, root, EINA_RBTREE_CMP_NODE_CB(_eina_bench_rbtree_cmp), NULL);
free(tmp);
}
eina_rbtree_delete(root, EINA_RBTREE_FREE_CB(_eina_bench_rbtree_free), NULL);
}
static void
eina_bench_lookup_superfast(int request)
{
Eina_Hash *hash = NULL;
Eina_Array *array = NULL;
int *tmp_val;
Eina_Array_Iterator it;
unsigned int i;
array = eina_array_new(1000);
hash = eina_hash_string_superfast_new();
hash = eina_hash_string_superfast_new(free);
for (i = 0; i < (unsigned int) request; ++i)
{
@ -130,8 +127,6 @@ eina_bench_lookup_superfast(int request)
*tmp_val = i;
eina_hash_add(hash, tmp_key, tmp_val);
eina_array_push(array, tmp_val);
}
srand(time(NULL));
@ -146,25 +141,16 @@ eina_bench_lookup_superfast(int request)
}
eina_hash_free(hash);
EINA_ARRAY_ITER_NEXT(array, i, tmp_val, it)
free(tmp_val);
eina_array_free(array);
}
static void
eina_bench_lookup_djb2(int request)
{
Eina_Hash *hash = NULL;
Eina_Array *array = NULL;
int *tmp_val;
Eina_Array_Iterator it;
unsigned int i;
array = eina_array_new(1000);
hash = eina_hash_string_djb2_new();
hash = eina_hash_string_djb2_new(free);
for (i = 0; i < (unsigned int) request; ++i)
{
@ -178,8 +164,6 @@ eina_bench_lookup_djb2(int request)
*tmp_val = i;
eina_hash_add(hash, tmp_key, tmp_val);
eina_array_push(array, tmp_val);
}
srand(time(NULL));
@ -194,41 +178,37 @@ eina_bench_lookup_djb2(int request)
}
eina_hash_free(hash);
EINA_ARRAY_ITER_NEXT(array, i, tmp_val, it)
free(tmp_val);
eina_array_free(array);
}
typedef struct _Eina_Bench_DJB2 Eina_Bench_DJB2;
struct _Eina_Bench_DJB2
{
char *key;
int value;
};
static void
eina_bench_lookup_djb2_inline(int request)
{
Eina_Hash *hash = NULL;
Eina_Array *array = NULL;
int *tmp_val;
Eina_Array_Iterator it;
Eina_Bench_DJB2 *elm;
unsigned int i;
array = eina_array_new(1000);
hash = eina_hash_string_djb2_new();
hash = eina_hash_string_djb2_new(free);
for (i = 0; i < (unsigned int) request; ++i)
{
char tmp_key[10];
int length;
tmp_val = malloc(sizeof (int));
elm = malloc(sizeof (Eina_Bench_DJB2) + 10);
if (!elm) continue ;
if (!tmp_key || !tmp_val) continue ;
elm->key = (char*) (elm + 1);
length = eina_convert_itoa(i, tmp_key) + 1;
*tmp_val = i;
length = eina_convert_itoa(i, elm->key) + 1;
elm->value = i;
eina_hash_add_by_hash(hash, tmp_key, length, eina_hash_djb2(tmp_key, length), tmp_val);
eina_array_push(array, tmp_val);
eina_hash_direct_add_by_hash(hash, elm->key, length, eina_hash_superfast(elm->key, length), elm);
}
srand(time(NULL));
@ -236,19 +216,14 @@ eina_bench_lookup_djb2_inline(int request)
for (i = 0; i < (unsigned int) request; ++i)
{
char tmp_key[10];
int length;
int length = 6;
length = eina_convert_itoa(rand() % request, tmp_key) + 1;
tmp_val = eina_hash_find_by_hash(hash, tmp_key, length, eina_hash_djb2(tmp_key, length));
elm = eina_hash_find_by_hash(hash, tmp_key, length, eina_hash_superfast(tmp_key, length));
}
eina_hash_free(hash);
EINA_ARRAY_ITER_NEXT(array, i, tmp_val, it)
free(tmp_val);
eina_array_free(array);
}
#ifdef EINA_BENCH_HAVE_GLIB
@ -401,8 +376,10 @@ void eina_bench_hash(Eina_Benchmark *bench)
eina_benchmark_register(bench, "ghash-lookup", EINA_BENCHMARK(eina_bench_lookup_ghash), 1000, 180000, 2500);
#endif
#ifdef EINA_BENCH_HAVE_EVAS
#if 0
eina_benchmark_register(bench, "evas-lookup", EINA_BENCHMARK(eina_bench_lookup_evas), 1000, 180000, 2500);
#endif
#endif
#ifdef EINA_BENCH_HAVE_ECORE
eina_benchmark_register(bench, "ecore-lookup", EINA_BENCHMARK(eina_bench_lookup_ecore), 1000, 180000, 2500);
#endif

View File

@ -60,9 +60,10 @@ START_TEST(eina_hash_simple)
int *test;
int array[] = { 1, 42, 4, 5, 6 };
fail_if(eina_hash_init() <= 0);
/* As mempool is already initialized and it use hash, we should have 2 init. */
fail_if(eina_hash_init() != 2);
hash = eina_hash_string_superfast_new();
hash = eina_hash_string_superfast_new(NULL);
fail_if(hash == NULL);
fail_if(eina_hash_add(hash, "1", &array[0]) != EINA_TRUE);
@ -106,7 +107,8 @@ START_TEST(eina_hash_simple)
eina_hash_free(hash);
fail_if(eina_hash_shutdown() > 0);
/* Same comment as eina_hash_init */
fail_if(eina_hash_shutdown() != 1);
}
END_TEST
@ -115,9 +117,9 @@ START_TEST(eina_hash_extended)
Eina_Hash *hash = NULL;
int i;
fail_if(eina_hash_init() <= 0);
fail_if(eina_hash_init() != 2);
hash = eina_hash_string_djb2_new();
hash = eina_hash_string_djb2_new(NULL);
fail_if(hash == NULL);
fail_if(eina_hash_direct_add(hash, "42", "42") != EINA_TRUE);
@ -134,7 +136,7 @@ START_TEST(eina_hash_extended)
eina_hash_free(hash);
fail_if(eina_hash_shutdown() > 0);
fail_if(eina_hash_shutdown() != 1);
}
END_TEST
@ -144,9 +146,9 @@ START_TEST(eina_hash_double_item)
int i[] = { 7, 7 };
int *test;
fail_if(eina_hash_init() <= 0);
fail_if(eina_hash_init() != 2);
hash = eina_hash_string_superfast_new();
hash = eina_hash_string_superfast_new(NULL);
fail_if(hash == NULL);
fail_if(eina_hash_add(hash, "7", &i[0]) != EINA_TRUE);
@ -158,7 +160,7 @@ START_TEST(eina_hash_double_item)
eina_hash_free(hash);
fail_if(eina_hash_shutdown() > 0);
fail_if(eina_hash_shutdown() != 1);
}
END_TEST

View File

@ -112,7 +112,7 @@ START_TEST(eina_iterator_hash_simple)
eina_hash_init();
hash = eina_hash_string_superfast_new();
hash = eina_hash_string_superfast_new(NULL);
fail_if(hash == NULL);
fail_if(eina_hash_add(hash, "1", &array[0]) != EINA_TRUE);