From: Mathieu Desnoyers Date: Wed, 6 Jul 2011 15:19:08 +0000 (-0400) Subject: rculfhash: add unique X-Git-Tag: v0.7.0~43^2~223 X-Git-Url: https://git.liburcu.org/?p=urcu.git;a=commitdiff_plain;h=3eca1b8cce5630bcbd865a8d30855c996bc021c3 rculfhash: add unique Signed-off-by: Mathieu Desnoyers --- diff --git a/rculfhash.c b/rculfhash.c index 534a2f8..a5e4d9f 100644 --- a/rculfhash.c +++ b/rculfhash.c @@ -205,12 +205,13 @@ unsigned long _uatomic_max(unsigned long *ptr, unsigned long v) } static -void _ht_add(struct rcu_ht *ht, struct rcu_table *t, struct rcu_ht_node *node) +int _ht_add(struct rcu_ht *ht, struct rcu_table *t, struct rcu_ht_node *node, + int unique) { struct rcu_ht_node *iter_prev, *iter, *iter_prev_next, *next; if (!t->size) - return; + return 0; for (;;) { uint32_t chain_len = 0; @@ -232,6 +233,12 @@ void _ht_add(struct rcu_ht *ht, struct rcu_table *t, struct rcu_ht_node *node) next = rcu_dereference(clear_flag(iter)->next); if (unlikely(is_removed(next))) continue; + if (unique + && !clear_flag(iter)->dummy + && !ht->compare_fct(node->key, node->key_len, + clear_flag(iter)->key, + clear_flag(iter)->key_len)) + return -EEXIST; if (clear_flag(iter)->reverse_hash > node->reverse_hash) break; /* Only account for identical reverse hash once */ @@ -250,6 +257,7 @@ void _ht_add(struct rcu_ht *ht, struct rcu_table *t, struct rcu_ht_node *node) else break; } + return 0; } static @@ -345,7 +353,7 @@ void init_table(struct rcu_ht *ht, struct rcu_table *t, t->tbl[i]->dummy = 1; t->tbl[i]->hash = i; t->tbl[i]->reverse_hash = bit_reverse_ulong(i); - _ht_add(ht, t, t->tbl[i]); + (void) _ht_add(ht, t, t->tbl[i], 0); } t->resize_target = t->size = end; t->resize_initiated = 0; @@ -412,7 +420,18 @@ void ht_add(struct rcu_ht *ht, struct rcu_ht_node *node) node->reverse_hash = bit_reverse_ulong((unsigned long) node->hash); t = rcu_dereference(ht->t); - _ht_add(ht, t, node); + (void) _ht_add(ht, t, node, 0); +} + +int ht_add_unique(struct rcu_ht *ht, struct rcu_ht_node *node) +{ + struct rcu_table *t; + + node->hash = ht->hash_fct(node->key, node->key_len, ht->hash_seed); + node->reverse_hash = bit_reverse_ulong((unsigned long) node->hash); + + t = rcu_dereference(ht->t); + return _ht_add(ht, t, node, 1); } int ht_remove(struct rcu_ht *ht, struct rcu_ht_node *node) diff --git a/tests/test_urcu_hash.c b/tests/test_urcu_hash.c index 5935656..44b9531 100644 --- a/tests/test_urcu_hash.c +++ b/tests/test_urcu_hash.c @@ -405,9 +405,12 @@ void *thr_writer(void *_count) (void *)(unsigned long)(rand_r(&rand_lookup) % RAND_POOL), sizeof(void *), (void *) 0x42); - ht_add(test_ht, node); + ret = ht_add_unique(test_ht, node); rcu_read_unlock(); - nr_add++; + if (ret) + nr_addexist++; + else + nr_add++; } else { /* May delete */ rcu_read_lock(); diff --git a/urcu/rculfhash.h b/urcu/rculfhash.h index 94206e3..ed75431 100644 --- a/urcu/rculfhash.h +++ b/urcu/rculfhash.h @@ -55,6 +55,9 @@ struct rcu_ht_node *ht_lookup(struct rcu_ht *ht, void *key, size_t key_len); /* Call with rcu_read_lock held. */ void ht_add(struct rcu_ht *ht, struct rcu_ht_node *node); +/* Call with rcu_read_lock held. */ +int ht_add_unique(struct rcu_ht *ht, struct rcu_ht_node *node); + /* Call with rcu_read_lock held. */ int ht_remove(struct rcu_ht *ht, struct rcu_ht_node *node);