#include <ccan/compiler/compiler.h>
#include <stdint.h>
#include <stdlib.h>
+#include <limits.h>
#include <stdbool.h>
#include <assert.h>
ht->max *= 2;
ht->max_with_deleted *= 2;
- /* FIXME: If we lost our perfect bit, we could reclaim it here! */
+ /* If we lost our "perfect bit", get it back now. */
+ if (!ht->perfect_bit && ht->common_mask) {
+ for (i = 0; i < sizeof(ht->common_mask) * CHAR_BIT; i++) {
+ if (ht->common_mask & ((size_t)1 << i)) {
+ ht->perfect_bit = (size_t)1 << i;
+ break;
+ }
+ }
+ }
+
for (i = 0; i < oldnum; i++) {
if (entry_is_valid(e = oldtable[i])) {
void *p = get_raw_ptr(ht, e);
int main(int argc, char *argv[])
{
unsigned int i;
+ uintptr_t perfect_bit;
struct htable *ht;
uint64_t val[NUM_VALS];
uint64_t dne;
void *p;
struct htable_iter iter;
- plan_tests(19);
+ plan_tests(23);
for (i = 0; i < NUM_VALS; i++)
val[i] = i;
dne = i;
htable_add(ht, hash(&val[NUM_VALS-1], NULL), &val[NUM_VALS-1]);
ok1(ht->common_mask == 0);
ok1(ht->common_bits == 0);
+ /* Get rid of bogus pointer before we trip over it! */
+ htable_del(ht, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]);
/* Add the rest. */
add_vals(ht, val, NUM_VALS-1);
find_vals(ht, val, NUM_VALS);
ok1(!htable_get(ht, hash(&dne, NULL), objcmp, &dne));
+ htable_free(ht);
+
+ /* Corner cases: wipe out the perfect bit using bogus pointer. */
+ ht = htable_new(hash, NULL);
+ htable_add(ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1]));
+ ok1(ht->perfect_bit);
+ perfect_bit = ht->perfect_bit;
+ htable_add(ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1]
+ | perfect_bit));
+ ok1(ht->perfect_bit == 0);
+ htable_del(ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1] | perfect_bit));
+
+ /* Enlarging should restore it... */
+ add_vals(ht, val, NUM_VALS-1);
+
+ ok1(ht->perfect_bit != 0);
+ htable_free(ht);
+
return exit_status();
}