htable.c (11777B)
1 /* Licensed under LGPLv2+ - see LICENSE file for details */ 2 #include <ccan/htable/htable.h> 3 #include <ccan/compiler/compiler.h> 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <limits.h> 7 #include <stdbool.h> 8 #include <assert.h> 9 #include <string.h> 10 11 /* We use 0x1 as deleted marker. */ 12 #define HTABLE_DELETED (0x1) 13 14 /* perfect_bitnum 63 means there's no perfect bitnum */ 15 #define NO_PERFECT_BIT (sizeof(uintptr_t) * CHAR_BIT - 1) 16 17 static void *htable_default_alloc(struct htable *ht, size_t len) 18 { 19 return calloc(len, 1); 20 } 21 22 static void htable_default_free(struct htable *ht, void *p) 23 { 24 free(p); 25 } 26 27 static void *(*htable_alloc)(struct htable *, size_t) = htable_default_alloc; 28 static void (*htable_free)(struct htable *, void *) = htable_default_free; 29 30 void htable_set_allocator(void *(*alloc)(struct htable *, size_t len), 31 void (*free)(struct htable *, void *p)) 32 { 33 if (!alloc) 34 alloc = htable_default_alloc; 35 if (!free) 36 free = htable_default_free; 37 htable_alloc = alloc; 38 htable_free = free; 39 } 40 41 /* We clear out the bits which are always the same, and put metadata there. */ 42 static inline uintptr_t get_extra_ptr_bits(const struct htable *ht, 43 uintptr_t e) 44 { 45 return e & ht->common_mask; 46 } 47 48 static inline void *get_raw_ptr(const struct htable *ht, uintptr_t e) 49 { 50 return (void *)((e & ~ht->common_mask) | ht->common_bits); 51 } 52 53 static inline uintptr_t make_hval(const struct htable *ht, 54 const void *p, uintptr_t bits) 55 { 56 return ((uintptr_t)p & ~ht->common_mask) | bits; 57 } 58 59 static inline bool entry_is_valid(uintptr_t e) 60 { 61 return e > HTABLE_DELETED; 62 } 63 64 static inline uintptr_t ht_perfect_mask(const struct htable *ht) 65 { 66 return (uintptr_t)2 << ht->perfect_bitnum; 67 } 68 69 static inline uintptr_t get_hash_ptr_bits(const struct htable *ht, 70 size_t hash) 71 { 72 /* Shuffling the extra bits (as specified in mask) down the 73 * end is quite expensive. But the lower bits are redundant, so 74 * we fold the value first. */ 75 return (hash ^ (hash >> ht->bits)) 76 & ht->common_mask & ~ht_perfect_mask(ht); 77 } 78 79 void htable_init(struct htable *ht, 80 size_t (*rehash)(const void *elem, void *priv), void *priv) 81 { 82 struct htable empty = HTABLE_INITIALIZER(empty, NULL, NULL); 83 *ht = empty; 84 ht->rehash = rehash; 85 ht->priv = priv; 86 ht->table = &ht->common_bits; 87 } 88 89 /* Fill to 87.5% */ 90 static inline size_t ht_max(const struct htable *ht) 91 { 92 return ((size_t)7 << ht->bits) / 8; 93 } 94 95 /* Clean deleted if we're full, and more than 12.5% deleted */ 96 static inline size_t ht_max_deleted(const struct htable *ht) 97 { 98 return ((size_t)1 << ht->bits) / 8; 99 } 100 101 bool htable_init_sized(struct htable *ht, 102 size_t (*rehash)(const void *, void *), 103 void *priv, size_t expect) 104 { 105 htable_init(ht, rehash, priv); 106 107 /* Don't go insane with sizing. */ 108 for (ht->bits = 1; ht_max(ht) < expect; ht->bits++) { 109 if (ht->bits == 30) 110 break; 111 } 112 113 ht->table = htable_alloc(ht, sizeof(size_t) << ht->bits); 114 if (!ht->table) { 115 ht->table = &ht->common_bits; 116 return false; 117 } 118 (void)htable_debug(ht, HTABLE_LOC); 119 return true; 120 } 121 122 void htable_clear(struct htable *ht) 123 { 124 if (ht->table != &ht->common_bits) 125 htable_free(ht, (void *)ht->table); 126 htable_init(ht, ht->rehash, ht->priv); 127 } 128 129 bool htable_copy_(struct htable *dst, const struct htable *src) 130 { 131 uintptr_t *htable = htable_alloc(dst, sizeof(size_t) << src->bits); 132 133 if (!htable) 134 return false; 135 136 *dst = *src; 137 dst->table = htable; 138 memcpy(dst->table, src->table, sizeof(size_t) << src->bits); 139 return true; 140 } 141 142 static size_t hash_bucket(const struct htable *ht, size_t h) 143 { 144 return h & ((1 << ht->bits)-1); 145 } 146 147 static void *htable_val(const struct htable *ht, 148 struct htable_iter *i, size_t hash, uintptr_t perfect) 149 { 150 uintptr_t h2 = get_hash_ptr_bits(ht, hash) | perfect; 151 152 while (ht->table[i->off]) { 153 if (ht->table[i->off] != HTABLE_DELETED) { 154 if (get_extra_ptr_bits(ht, ht->table[i->off]) == h2) 155 return get_raw_ptr(ht, ht->table[i->off]); 156 } 157 i->off = (i->off + 1) & ((1 << ht->bits)-1); 158 h2 &= ~perfect; 159 } 160 return NULL; 161 } 162 163 void *htable_firstval_(const struct htable *ht, 164 struct htable_iter *i, size_t hash) 165 { 166 i->off = hash_bucket(ht, hash); 167 return htable_val(ht, i, hash, ht_perfect_mask(ht)); 168 } 169 170 void *htable_nextval_(const struct htable *ht, 171 struct htable_iter *i, size_t hash) 172 { 173 i->off = (i->off + 1) & ((1 << ht->bits)-1); 174 return htable_val(ht, i, hash, 0); 175 } 176 177 void *htable_first_(const struct htable *ht, struct htable_iter *i) 178 { 179 for (i->off = 0; i->off < (size_t)1 << ht->bits; i->off++) { 180 if (entry_is_valid(ht->table[i->off])) 181 return get_raw_ptr(ht, ht->table[i->off]); 182 } 183 return NULL; 184 } 185 186 void *htable_next_(const struct htable *ht, struct htable_iter *i) 187 { 188 for (i->off++; i->off < (size_t)1 << ht->bits; i->off++) { 189 if (entry_is_valid(ht->table[i->off])) 190 return get_raw_ptr(ht, ht->table[i->off]); 191 } 192 return NULL; 193 } 194 195 void *htable_prev_(const struct htable *ht, struct htable_iter *i) 196 { 197 for (;;) { 198 if (!i->off) 199 return NULL; 200 i->off--; 201 if (entry_is_valid(ht->table[i->off])) 202 return get_raw_ptr(ht, ht->table[i->off]); 203 } 204 } 205 206 /* Another bit currently in mask needs to be exposed, so that a bucket with p in 207 * it won't appear invalid */ 208 static COLD void unset_another_common_bit(struct htable *ht, 209 uintptr_t *maskdiff, 210 const void *p) 211 { 212 size_t i; 213 214 for (i = sizeof(uintptr_t) * CHAR_BIT - 1; i > 0; i--) { 215 if (((uintptr_t)p & ((uintptr_t)1 << i)) 216 && ht->common_mask & ~*maskdiff & ((uintptr_t)1 << i)) 217 break; 218 } 219 /* There must have been one, right? */ 220 assert(i > 0); 221 222 *maskdiff |= ((uintptr_t)1 << i); 223 } 224 225 /* We want to change the common mask: this fixes up the table */ 226 static COLD void fixup_table_common(struct htable *ht, uintptr_t maskdiff) 227 { 228 size_t i; 229 uintptr_t bitsdiff; 230 231 again: 232 bitsdiff = ht->common_bits & maskdiff; 233 234 for (i = 0; i < (size_t)1 << ht->bits; i++) { 235 uintptr_t e; 236 if (!entry_is_valid(e = ht->table[i])) 237 continue; 238 239 /* Clear the bits no longer in the mask, set them as 240 * expected. */ 241 e &= ~maskdiff; 242 e |= bitsdiff; 243 /* If this made it invalid, restart with more exposed */ 244 if (!entry_is_valid(e)) { 245 unset_another_common_bit(ht, &maskdiff, get_raw_ptr(ht, e)); 246 goto again; 247 } 248 ht->table[i] = e; 249 } 250 251 /* Take away those bits from our mask, bits and perfect bit. */ 252 ht->common_mask &= ~maskdiff; 253 ht->common_bits &= ~maskdiff; 254 if (ht_perfect_mask(ht) & maskdiff) 255 ht->perfect_bitnum = NO_PERFECT_BIT; 256 } 257 258 /* Limited recursion */ 259 static void ht_add(struct htable *ht, const void *new, size_t h); 260 261 /* We tried to add this entry, but it looked invalid! We need to 262 * let another pointer bit through mask */ 263 static COLD void update_common_fix_invalid(struct htable *ht, const void *p, size_t h) 264 { 265 uintptr_t maskdiff; 266 267 assert(ht->elems != 0); 268 269 maskdiff = 0; 270 unset_another_common_bit(ht, &maskdiff, p); 271 fixup_table_common(ht, maskdiff); 272 273 /* Now won't recurse */ 274 ht_add(ht, p, h); 275 } 276 277 /* This does not expand the hash table, that's up to caller. */ 278 static void ht_add(struct htable *ht, const void *new, size_t h) 279 { 280 size_t i; 281 uintptr_t perfect = ht_perfect_mask(ht); 282 283 i = hash_bucket(ht, h); 284 285 while (entry_is_valid(ht->table[i])) { 286 perfect = 0; 287 i = (i + 1) & ((1 << ht->bits)-1); 288 } 289 ht->table[i] = make_hval(ht, new, get_hash_ptr_bits(ht, h)|perfect); 290 if (!entry_is_valid(ht->table[i])) 291 update_common_fix_invalid(ht, new, h); 292 } 293 294 static COLD bool double_table(struct htable *ht) 295 { 296 unsigned int i; 297 size_t oldnum = (size_t)1 << ht->bits; 298 uintptr_t *oldtable, e; 299 300 oldtable = ht->table; 301 ht->table = htable_alloc(ht, sizeof(size_t) << (ht->bits+1)); 302 if (!ht->table) { 303 ht->table = oldtable; 304 return false; 305 } 306 ht->bits++; 307 308 /* If we lost our "perfect bit", get it back now. */ 309 if (ht->perfect_bitnum == NO_PERFECT_BIT && ht->common_mask) { 310 for (i = 0; i < sizeof(ht->common_mask) * CHAR_BIT; i++) { 311 if (ht->common_mask & ((size_t)2 << i)) { 312 ht->perfect_bitnum = i; 313 break; 314 } 315 } 316 } 317 318 if (oldtable != &ht->common_bits) { 319 for (i = 0; i < oldnum; i++) { 320 if (entry_is_valid(e = oldtable[i])) { 321 void *p = get_raw_ptr(ht, e); 322 ht_add(ht, p, ht->rehash(p, ht->priv)); 323 } 324 } 325 htable_free(ht, oldtable); 326 } 327 ht->deleted = 0; 328 329 (void)htable_debug(ht, HTABLE_LOC); 330 return true; 331 } 332 333 static COLD void rehash_table(struct htable *ht) 334 { 335 size_t start, i; 336 uintptr_t e, perfect = ht_perfect_mask(ht); 337 338 /* Beware wrap cases: we need to start from first empty bucket. */ 339 for (start = 0; ht->table[start]; start++); 340 341 for (i = 0; i < (size_t)1 << ht->bits; i++) { 342 size_t h = (i + start) & ((1 << ht->bits)-1); 343 e = ht->table[h]; 344 if (!e) 345 continue; 346 if (e == HTABLE_DELETED) 347 ht->table[h] = 0; 348 else if (!(e & perfect)) { 349 void *p = get_raw_ptr(ht, e); 350 ht->table[h] = 0; 351 ht_add(ht, p, ht->rehash(p, ht->priv)); 352 } 353 } 354 ht->deleted = 0; 355 (void)htable_debug(ht, HTABLE_LOC); 356 } 357 358 /* We stole some bits, now we need to put them back... */ 359 static COLD void update_common(struct htable *ht, const void *p) 360 { 361 uintptr_t maskdiff; 362 363 if (ht->elems == 0) { 364 ht->common_mask = -1; 365 ht->common_bits = ((uintptr_t)p & ht->common_mask); 366 ht->perfect_bitnum = 0; 367 (void)htable_debug(ht, HTABLE_LOC); 368 return; 369 } 370 371 /* Find bits which are unequal to old common set. */ 372 maskdiff = ht->common_bits ^ ((uintptr_t)p & ht->common_mask); 373 374 fixup_table_common(ht, maskdiff); 375 (void)htable_debug(ht, HTABLE_LOC); 376 } 377 378 bool htable_add_(struct htable *ht, size_t hash, const void *p) 379 { 380 /* Cannot insert NULL, or (void *)1. */ 381 assert(p); 382 assert(entry_is_valid((uintptr_t)p)); 383 384 /* Getting too full? */ 385 if (ht->elems+1 + ht->deleted > ht_max(ht)) { 386 /* If we're more than 1/8 deleted, clean those, 387 * otherwise double table size. */ 388 if (ht->deleted > ht_max_deleted(ht)) 389 rehash_table(ht); 390 else if (!double_table(ht)) 391 return false; 392 } 393 if (((uintptr_t)p & ht->common_mask) != ht->common_bits) 394 update_common(ht, p); 395 396 ht_add(ht, p, hash); 397 ht->elems++; 398 return true; 399 } 400 401 bool htable_del_(struct htable *ht, size_t h, const void *p) 402 { 403 struct htable_iter i; 404 void *c; 405 406 for (c = htable_firstval(ht,&i,h); c; c = htable_nextval(ht,&i,h)) { 407 if (c == p) { 408 htable_delval(ht, &i); 409 return true; 410 } 411 } 412 return false; 413 } 414 415 void htable_delval_(struct htable *ht, struct htable_iter *i) 416 { 417 assert(i->off < (size_t)1 << ht->bits); 418 assert(entry_is_valid(ht->table[i->off])); 419 420 ht->elems--; 421 /* Cheap test: if the next bucket is empty, don't need delete marker */ 422 if (ht->table[hash_bucket(ht, i->off+1)] != 0) { 423 ht->table[i->off] = HTABLE_DELETED; 424 ht->deleted++; 425 } else 426 ht->table[i->off] = 0; 427 } 428 429 void *htable_pick_(const struct htable *ht, size_t seed, struct htable_iter *i) 430 { 431 void *e; 432 struct htable_iter unwanted; 433 434 if (!i) 435 i = &unwanted; 436 i->off = seed % ((size_t)1 << ht->bits); 437 e = htable_next(ht, i); 438 if (!e) 439 e = htable_first(ht, i); 440 return e; 441 } 442 443 struct htable *htable_check(const struct htable *ht, const char *abortstr) 444 { 445 void *p; 446 struct htable_iter i; 447 size_t n = 0; 448 449 /* Use non-DEBUG versions here, to avoid infinite recursion with 450 * CCAN_HTABLE_DEBUG! */ 451 for (p = htable_first_(ht, &i); p; p = htable_next_(ht, &i)) { 452 struct htable_iter i2; 453 void *c; 454 size_t h = ht->rehash(p, ht->priv); 455 bool found = false; 456 457 n++; 458 459 /* Open-code htable_get to avoid CCAN_HTABLE_DEBUG */ 460 for (c = htable_firstval_(ht, &i2, h); 461 c; 462 c = htable_nextval_(ht, &i2, h)) { 463 if (c == p) { 464 found = true; 465 break; 466 } 467 } 468 469 if (!found) { 470 if (abortstr) { 471 fprintf(stderr, 472 "%s: element %p in position %zu" 473 " cannot find itself\n", 474 abortstr, p, i.off); 475 abort(); 476 } 477 return NULL; 478 } 479 } 480 if (n != ht->elems) { 481 if (abortstr) { 482 fprintf(stderr, 483 "%s: found %zu elems, expected %zu\n", 484 abortstr, n, ht->elems); 485 abort(); 486 } 487 return NULL; 488 } 489 490 return (struct htable *)ht; 491 }