struct isc_hashmap_iter {
isc_hashmap_t *hashmap;
size_t i;
+ size_t size;
uint8_t hindex;
hashmap_node_t *cur;
};
return (ISC_R_SUCCESS);
}
-static void
+static bool
hashmap_delete_node(isc_hashmap_t *hashmap, hashmap_node_t *entry,
uint32_t hashval, uint32_t psl, const uint8_t idx) {
uint32_t pos;
uint32_t hash;
+ bool last = false;
hashmap->count--;
break;
}
+ if (pos == 0) {
+ last = true;
+ }
+
node->psl--;
*entry = *node;
entry = &hashmap->tables[idx].table[pos];
}
*entry = (hashmap_node_t){ 0 };
+ return (last);
}
static void
/* Move the first non-empty node from old table to new table */
node = oldtable[hashmap->hiter];
- hashmap_delete_node(hashmap, &oldtable[hashmap->hiter], node.hashval,
- node.psl, oldidx);
+ (void)hashmap_delete_node(hashmap, &oldtable[hashmap->hiter],
+ node.hashval, node.psl, oldidx);
isc_result_t result = hashmap_add(hashmap, node.hashval, NULL, node.key,
node.value, NULL, hashmap->hindex);
node = hashmap_find(hashmap, hashval, match, key, &psl, &idx);
if (node != NULL) {
INSIST(node->key != NULL);
- hashmap_delete_node(hashmap, node, hashval, psl, idx);
+ (void)hashmap_delete_node(hashmap, node, hashval, psl, idx);
result = ISC_R_SUCCESS;
}
isc__hashmap_iter_next(isc_hashmap_iter_t *iter) {
isc_hashmap_t *hashmap = iter->hashmap;
- while (iter->i < hashmap->tables[iter->hindex].size &&
+ while (iter->i < iter->size &&
hashmap->tables[iter->hindex].table[iter->i].key == NULL)
{
iter->i++;
}
- if (iter->i < hashmap->tables[iter->hindex].size) {
+ if (iter->i < iter->size) {
iter->cur = &hashmap->tables[iter->hindex].table[iter->i];
return (ISC_R_SUCCESS);
if (try_nexttable(hashmap, iter->hindex)) {
iter->hindex = hashmap_nexttable(iter->hindex);
iter->i = 0;
+ iter->size = hashmap->tables[iter->hindex].size;
return (isc__hashmap_iter_next(iter));
}
iter->hindex = iter->hashmap->hindex;
iter->i = 0;
+ iter->size = iter->hashmap->tables[iter->hashmap->hindex].size;
return (isc__hashmap_iter_next(iter));
}
hashmap_node_t *node =
&iter->hashmap->tables[iter->hindex].table[iter->i];
- hashmap_delete_node(iter->hashmap, node, node->hashval, node->psl,
- iter->hindex);
+ if (hashmap_delete_node(iter->hashmap, node, node->hashval, node->psl,
+ iter->hindex))
+ {
+ /*
+ * We have seen the new last element so reduce the size
+ * so we don't iterate over it twice.
+ */
+ INSIST(iter->size != 0);
+ iter->size--;
+ }
return (isc__hashmap_iter_next(iter));
}
isc_result_t result;
isc_hashmap_iter_t *iter = NULL;
size_t count = 7600;
- uint32_t walked;
test_node_t *nodes;
+ bool *seen;
nodes = isc_mem_cget(mctx, count, sizeof(nodes[0]));
+ seen = isc_mem_cget(mctx, count, sizeof(seen[0]));
isc_hashmap_create(mctx, HASHMAP_MIN_BITS, &hashmap);
assert_non_null(hashmap);
/* We want to iterate while rehashing is in progress */
assert_true(rehashing_in_progress(hashmap));
- walked = 0;
+ memset(seen, 0, count * sizeof(seen[0]));
isc_hashmap_iter_create(hashmap, &iter);
for (result = isc_hashmap_iter_first(iter); result == ISC_R_SUCCESS;
assert_memory_equal(key, tkey, 16);
- walked++;
+ assert_false(seen[i]);
+ seen[i] = true;
}
- assert_int_equal(walked, count);
assert_int_equal(result, ISC_R_NOMORE);
+ for (size_t i = 0; i < count; i++) {
+ assert_true(seen[i]);
+ }
/* erase odd */
- walked = 0;
+ memset(seen, 0, count * sizeof(seen[0]));
result = isc_hashmap_iter_first(iter);
while (result == ISC_R_SUCCESS) {
char key[16] = { 0 };
} else {
result = isc_hashmap_iter_next(iter);
}
- walked++;
+
+ assert_false(seen[i]);
+ seen[i] = true;
}
assert_int_equal(result, ISC_R_NOMORE);
- assert_int_equal(walked, count);
+ for (size_t i = 0; i < count; i++) {
+ assert_true(seen[i]);
+ }
/* erase even */
- walked = 0;
+ memset(seen, 0, count * sizeof(seen[0]));
result = isc_hashmap_iter_first(iter);
while (result == ISC_R_SUCCESS) {
char key[16] = { 0 };
} else {
result = isc_hashmap_iter_next(iter);
}
- walked++;
}
assert_int_equal(result, ISC_R_NOMORE);
- assert_int_equal(walked, count / 2);
- walked = 0;
for (result = isc_hashmap_iter_first(iter); result == ISC_R_SUCCESS;
result = isc_hashmap_iter_next(iter))
{
- walked++;
+ assert_true(false);
}
-
assert_int_equal(result, ISC_R_NOMORE);
- assert_int_equal(walked, 0);
/* Iterator doesn't progress rehashing */
assert_true(rehashing_in_progress(hashmap));
isc_hashmap_destroy(&hashmap);
assert_null(hashmap);
+ isc_mem_cput(mctx, seen, count, sizeof(seen[0]));
isc_mem_cput(mctx, nodes, count, sizeof(nodes[0]));
}