]> pd.if.org Git - nbds/blobdiff - map/hashtable.c
Bug fix in ht_iter_next() from Rui Ueyama
[nbds] / map / hashtable.c
index b8d8f6b3f3e5972837d13e746fed85b933955fb6..bff782f84afdf46867dcbc27275402f1e3ac18dd 100644 (file)
@@ -10,6 +10,8 @@
  * 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>
@@ -374,7 +376,7 @@ static map_val_t hti_cas (hti_t *hti, map_key_t key, uint32_t key_hash, map_val_
     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);
             }
@@ -429,7 +431,7 @@ static map_val_t hti_get (hti_t *hti, map_key_t key, uint32_t key_hash) {
     // 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;
     }
@@ -441,12 +443,12 @@ static map_val_t hti_get (hti_t *hti, map_key_t key, uint32_t key_hash) {
     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;
@@ -677,9 +679,6 @@ map_val_t ht_iter_next (ht_iter_t *iter, map_key_t *key_ptr) {
 
     } 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
@@ -688,8 +687,15 @@ map_val_t ht_iter_next (ht_iter_t *iter, map_key_t *key_ptr) {
         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;
 }