* Every atomic operation is also an implicit full memory barrier. The upshot is that it simplifies
* the code a bit, but it won't be as fast as it could be on platforms that provide weaker
* operations like and unfenced CAS which would still do the job.
+ *
+ * 11FebO9 - Bug fix in ht_iter_next() from Rui Ueyama
*/
#include <stdio.h>
map_val_t ent_val = ent->val;
if (EXPECT_FALSE(IS_TAGGED(ent_val, TAG1))) {
if (ent_val != COPIED_VALUE && ent_val != TAG_VALUE(TOMBSTONE, TAG1)) {
- int did_copy = hti_copy_entry(hti, ent, key_hash, ((volatile hti_t *)hti)->next);
+ int did_copy = hti_copy_entry(hti, ent, key_hash, VOLATILE_DEREF(hti).next);
if (did_copy) {
(void)SYNC_ADD(&hti->num_entries_copied, 1);
}
// searching the table. In that case, if a copy is in progress the key
// might exist in the copy.
if (EXPECT_FALSE(ent == NULL)) {
- if (((volatile hti_t *)hti)->next != NULL)
+ if (VOLATILE_DEREF(hti).next != NULL)
return hti_get(hti->next, key, key_hash); // recursive tail-call
return DOES_NOT_EXIST;
}
map_val_t ent_val = ent->val;
if (EXPECT_FALSE(IS_TAGGED(ent_val, TAG1))) {
if (EXPECT_FALSE(ent_val != COPIED_VALUE && ent_val != TAG_VALUE(TOMBSTONE, TAG1))) {
- int did_copy = hti_copy_entry(hti, ent, key_hash, ((volatile hti_t *)hti)->next);
+ int did_copy = hti_copy_entry(hti, ent, key_hash, VOLATILE_DEREF(hti).next);
if (did_copy) {
(void)SYNC_ADD(&hti->num_entries_copied, 1);
}
}
- return hti_get(((volatile hti_t *)hti)->next, key, key_hash); // tail-call
+ return hti_get(VOLATILE_DEREF(hti).next, key, key_hash); // tail-call
}
return (ent_val == TOMBSTONE) ? DOES_NOT_EXIST : ent_val;
} while (key == DOES_NOT_EXIST || val == DOES_NOT_EXIST || val == TOMBSTONE);
- if (key_ptr) {
- *key_ptr = key;
- }
if (val == COPIED_VALUE) {
const datatype_t *key_type = iter->hti->ht->key_type;
#ifdef NBD32
uint32_t hash = (key_type == NULL) ? murmur32_8b((uint64_t)key) : key_type->hash((void *)key);
#endif
val = hti_get(iter->hti->next, (map_key_t)ent->key, hash);
+
+ // Go to the next entry if key is already deleted.
+ if (val == DOES_NOT_EXIST)
+ return ht_iter_next(iter, key_ptr); // recursive tail-call
}
+ if (key_ptr) {
+ *key_ptr = key;
+ }
return val;
}