]> git.ozlabs.org Git - ccan/blob - ccan/htable/htable.c
htable: handle v. unlikely case where entries look deleted/empty.
[ccan] / ccan / htable / htable.c
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 uintptr_t *actually_valid_pair(const struct htable *ht)
60 {
61         return ht->table + ((size_t)1 << ht->bits);
62 }
63
64 /* We have have two entries which look deleted, but we remember
65  * they are not! */
66 static inline bool entry_actually_valid(const struct htable *ht, size_t off)
67 {
68         const uintptr_t *valid = actually_valid_pair(ht);
69         /* Empty table looks like this! */
70         if (valid == &ht->common_bits + 1)
71                 return false;
72         return valid[0] == off || valid[1] == off;
73 }
74
75 /* Initialize the "actually valid" pair. */
76 static inline void init_actually_valid(struct htable *ht)
77 {
78         uintptr_t *valid = actually_valid_pair(ht);
79         valid[0] = valid[1] = ((size_t)1 << ht->bits);
80 }
81
82 /* Add to the "actually valid" pair: there can only ever be two! */
83 static COLD void add_actually_valid(struct htable *ht, size_t off)
84 {
85         uintptr_t *valid = actually_valid_pair(ht);
86         if (valid[0] == ((size_t)1 << ht->bits))
87                 valid[0] = off;
88         else {
89                 assert(valid[1] == ((size_t)1 << ht->bits));
90                 valid[1] = off;
91         }
92 }
93
94 static COLD void del_actually_valid(struct htable *ht, size_t off)
95 {
96         uintptr_t *validpair = actually_valid_pair(ht);
97         if (validpair[0] == off)
98                 validpair[0] = ((size_t)1 << ht->bits);
99         else {
100                 assert(validpair[1] == off);
101                 validpair[1] = ((size_t)1 << ht->bits);
102         }
103 }
104
105 /* If this entry looks invalid, check entry_actually_valid! */
106 static inline bool entry_looks_invalid(const struct htable *ht, size_t off)
107 {
108         return ht->table[off] <= HTABLE_DELETED;
109 }
110
111 static inline bool entry_is_valid(const struct htable *ht, size_t off)
112 {
113         if (!entry_looks_invalid(ht, off))
114                 return true;
115         return entry_actually_valid(ht, off);
116 }
117
118 static inline bool entry_is_deleted(const struct htable *ht, size_t off)
119 {
120         return ht->table[off] == HTABLE_DELETED && !entry_actually_valid(ht, off);
121 }
122
123 static inline uintptr_t ht_perfect_mask(const struct htable *ht)
124 {
125         return (uintptr_t)2 << ht->perfect_bitnum;
126 }
127
128 static inline uintptr_t get_hash_ptr_bits(const struct htable *ht,
129                                           size_t hash)
130 {
131         /* Shuffling the extra bits (as specified in mask) down the
132          * end is quite expensive.  But the lower bits are redundant, so
133          * we fold the value first. */
134         return (hash ^ (hash >> ht->bits))
135                 & ht->common_mask & ~ht_perfect_mask(ht);
136 }
137
138 void htable_init(struct htable *ht,
139                  size_t (*rehash)(const void *elem, void *priv), void *priv)
140 {
141         struct htable empty = HTABLE_INITIALIZER(empty, NULL, NULL);
142         *ht = empty;
143         ht->rehash = rehash;
144         ht->priv = priv;
145         ht->table = &ht->common_bits;
146 }
147
148 static inline size_t ht_max(const struct htable *ht)
149 {
150         return ((size_t)3 << ht->bits) / 4;
151 }
152
153 static inline size_t ht_max_with_deleted(const struct htable *ht)
154 {
155         return ((size_t)9 << ht->bits) / 10;
156 }
157
158 /* Includes the two trailing "not-deleted" entries */
159 static size_t htable_alloc_size(size_t bits)
160 {
161         return (sizeof(size_t) << bits) + 2 * sizeof(size_t);
162 }
163
164 bool htable_init_sized(struct htable *ht,
165                        size_t (*rehash)(const void *, void *),
166                        void *priv, size_t expect)
167 {
168         htable_init(ht, rehash, priv);
169
170         /* Don't go insane with sizing. */
171         for (ht->bits = 1; ((size_t)3 << ht->bits) / 4 < expect; ht->bits++) {
172                 if (ht->bits == 30)
173                         break;
174         }
175
176         ht->table = htable_alloc(ht, htable_alloc_size(ht->bits));
177         if (!ht->table) {
178                 ht->table = &ht->common_bits;
179                 return false;
180         }
181         init_actually_valid(ht);
182         (void)htable_debug(ht, HTABLE_LOC);
183         return true;
184 }
185         
186 void htable_clear(struct htable *ht)
187 {
188         if (ht->table != &ht->common_bits)
189                 htable_free(ht, (void *)ht->table);
190         htable_init(ht, ht->rehash, ht->priv);
191 }
192
193 bool htable_copy_(struct htable *dst, const struct htable *src)
194 {
195         uintptr_t *htable = htable_alloc(dst, htable_alloc_size(src->bits));
196
197         if (!htable)
198                 return false;
199
200         *dst = *src;
201         dst->table = htable;
202         memcpy(dst->table, src->table, htable_alloc_size(src->bits));
203         return true;
204 }
205
206 static size_t hash_bucket(const struct htable *ht, size_t h)
207 {
208         return h & ((1 << ht->bits)-1);
209 }
210
211 static void *htable_val(const struct htable *ht,
212                         struct htable_iter *i, size_t hash, uintptr_t perfect)
213 {
214         uintptr_t h2 = get_hash_ptr_bits(ht, hash) | perfect;
215
216         while (ht->table[i->off] || entry_actually_valid(ht, i->off)) {
217                 if (!entry_is_deleted(ht, i->off)) {
218                         if (get_extra_ptr_bits(ht, ht->table[i->off]) == h2)
219                                 return get_raw_ptr(ht, ht->table[i->off]);
220                 }
221                 i->off = (i->off + 1) & ((1 << ht->bits)-1);
222                 h2 &= ~perfect;
223         }
224         return NULL;
225 }
226
227 void *htable_firstval_(const struct htable *ht,
228                        struct htable_iter *i, size_t hash)
229 {
230         i->off = hash_bucket(ht, hash);
231         return htable_val(ht, i, hash, ht_perfect_mask(ht));
232 }
233
234 void *htable_nextval_(const struct htable *ht,
235                       struct htable_iter *i, size_t hash)
236 {
237         i->off = (i->off + 1) & ((1 << ht->bits)-1);
238         return htable_val(ht, i, hash, 0);
239 }
240
241 void *htable_first_(const struct htable *ht, struct htable_iter *i)
242 {
243         for (i->off = 0; i->off < (size_t)1 << ht->bits; i->off++) {
244                 if (entry_is_valid(ht, i->off))
245                         return get_raw_ptr(ht, ht->table[i->off]);
246         }
247         return NULL;
248 }
249
250 void *htable_next_(const struct htable *ht, struct htable_iter *i)
251 {
252         for (i->off++; i->off < (size_t)1 << ht->bits; i->off++) {
253                 if (entry_is_valid(ht, i->off))
254                         return get_raw_ptr(ht, ht->table[i->off]);
255         }
256         return NULL;
257 }
258
259 void *htable_prev_(const struct htable *ht, struct htable_iter *i)
260 {
261         for (;;) {
262                 if (!i->off)
263                         return NULL;
264                 i->off--;
265                 if (entry_is_valid(ht, i->off))
266                         return get_raw_ptr(ht, ht->table[i->off]);
267         }
268 }
269
270 /* This does not expand the hash table, that's up to caller. */
271 static void ht_add(struct htable *ht, const void *new, size_t h)
272 {
273         size_t i;
274         uintptr_t perfect = ht_perfect_mask(ht);
275
276         i = hash_bucket(ht, h);
277
278         while (entry_is_valid(ht, i)) {
279                 perfect = 0;
280                 i = (i + 1) & ((1 << ht->bits)-1);
281         }
282         ht->table[i] = make_hval(ht, new, get_hash_ptr_bits(ht, h)|perfect);
283
284         /* If it looks invalid, add it to exceptions */
285         if (ht->table[i] <= HTABLE_DELETED)
286                 add_actually_valid(ht, i);
287 }
288
289 static COLD bool double_table(struct htable *ht)
290 {
291         size_t i;
292         struct htable oldht = *ht;
293
294         ht->table = htable_alloc(ht, htable_alloc_size(ht->bits+1));
295         if (!ht->table) {
296                 ht->table = oldht.table;
297                 return false;
298         }
299         ht->bits++;
300         init_actually_valid(ht);
301
302         /* If we lost our "perfect bit", get it back now. */
303         if (ht->perfect_bitnum == NO_PERFECT_BIT && ht->common_mask) {
304                 for (i = 0; i < sizeof(ht->common_mask) * CHAR_BIT; i++) {
305                         if (ht->common_mask & ((size_t)2 << i)) {
306                                 ht->perfect_bitnum = i;
307                                 break;
308                         }
309                 }
310         }
311
312         if (oldht.table != &ht->common_bits) {
313                 for (i = 0; i < (size_t)1 << oldht.bits; i++) {
314                         if (entry_is_valid(&oldht, i)) {
315                                 void *p = get_raw_ptr(&oldht, oldht.table[i]);
316                                 ht_add(ht, p, ht->rehash(p, ht->priv));
317                         }
318                 }
319                 /* Pass ht here to callback: oldht is an internal figment */
320                 htable_free(ht, oldht.table);
321         }
322         ht->deleted = 0;
323
324         (void)htable_debug(ht, HTABLE_LOC);
325         return true;
326 }
327
328 static COLD void rehash_table(struct htable *ht)
329 {
330         size_t start, i;
331         uintptr_t e, perfect = ht_perfect_mask(ht);
332         uintptr_t *validpair = actually_valid_pair(ht);
333
334         /* Beware wrap cases: we need to start from first empty bucket. */
335         for (start = 0; ht->table[start]; start++);
336
337         for (i = 0; i < (size_t)1 << ht->bits; i++) {
338                 size_t h = (i + start) & ((1 << ht->bits)-1);
339                 uintptr_t *actually = NULL;
340                 e = ht->table[h];
341                 if (e <= HTABLE_DELETED) {
342                         /* If it's actually valid, remember in case we move it! */
343                         if (validpair[0] == h) {
344                                 actually = &validpair[0];
345                         } else if (validpair[1] == h) {
346                                 actually = &validpair[1];
347                         } else {
348                                 ht->table[h] = 0;
349                                 continue;
350                         }
351                 }
352
353                 if (!(e & perfect)) {
354                         void *p = get_raw_ptr(ht, e);
355                         ht->table[h] = 0;
356                         /* Clear actuallyvalid, let ht_add refill */
357                         if (actually)
358                                 *actually = ((size_t)1 << ht->bits);
359                         ht_add(ht, p, ht->rehash(p, ht->priv));
360                 }
361         }
362         ht->deleted = 0;
363         (void)htable_debug(ht, HTABLE_LOC);
364 }
365
366 /* We stole some bits, now we need to put them back... */
367 static COLD void update_common(struct htable *ht, const void *p)
368 {
369         unsigned int i;
370         uintptr_t maskdiff, bitsdiff;
371
372         if (ht->elems == 0) {
373                 ht->common_mask = -1;
374                 ht->common_bits = ((uintptr_t)p & ht->common_mask);
375                 ht->perfect_bitnum = 0;
376                 (void)htable_debug(ht, HTABLE_LOC);
377                 return;
378         }
379
380         /* Find bits which are unequal to old common set. */
381         maskdiff = ht->common_bits ^ ((uintptr_t)p & ht->common_mask);
382
383         /* These are the bits which go there in existing entries. */
384         bitsdiff = ht->common_bits & maskdiff;
385
386         for (i = 0; i < (size_t)1 << ht->bits; i++) {
387                 if (!entry_is_valid(ht, i))
388                         continue;
389                 /* Clear the bits no longer in the mask, set them as
390                  * expected. */
391                 ht->table[i] &= ~maskdiff;
392                 ht->table[i] |= bitsdiff;
393
394                 /* Make sure it's not newly falsely invalid */
395                 if (ht->table[i] <= HTABLE_DELETED && !entry_actually_valid(ht, i))
396                         add_actually_valid(ht, i);
397         }
398
399         /* Take away those bits from our mask, bits and perfect bit. */
400         ht->common_mask &= ~maskdiff;
401         ht->common_bits &= ~maskdiff;
402         if (ht_perfect_mask(ht) & maskdiff)
403                 ht->perfect_bitnum = NO_PERFECT_BIT;
404         (void)htable_debug(ht, HTABLE_LOC);
405 }
406
407 bool htable_add_(struct htable *ht, size_t hash, const void *p)
408 {
409         if (ht->elems+1 > ht_max(ht) && !double_table(ht))
410                 return false;
411         if (ht->elems+1 + ht->deleted > ht_max_with_deleted(ht))
412                 rehash_table(ht);
413         assert(p);
414         if (((uintptr_t)p & ht->common_mask) != ht->common_bits)
415                 update_common(ht, p);
416
417         ht_add(ht, p, hash);
418         ht->elems++;
419         return true;
420 }
421
422 bool htable_del_(struct htable *ht, size_t h, const void *p)
423 {
424         struct htable_iter i;
425         void *c;
426
427         for (c = htable_firstval(ht,&i,h); c; c = htable_nextval(ht,&i,h)) {
428                 if (c == p) {
429                         htable_delval(ht, &i);
430                         return true;
431                 }
432         }
433         return false;
434 }
435
436 void htable_delval_(struct htable *ht, struct htable_iter *i)
437 {
438         assert(i->off < (size_t)1 << ht->bits);
439
440         if (entry_looks_invalid(ht, i->off))
441                 del_actually_valid(ht, i->off);
442
443         ht->elems--;
444         ht->table[i->off] = HTABLE_DELETED;
445         ht->deleted++;
446 }
447
448 void *htable_pick_(const struct htable *ht, size_t seed, struct htable_iter *i)
449 {
450         void *e;
451         struct htable_iter unwanted;
452
453         if (!i)
454                 i = &unwanted;
455         i->off = seed % ((size_t)1 << ht->bits);
456         e = htable_next(ht, i);
457         if (!e)
458                 e = htable_first(ht, i);
459         return e;
460 }
461
462 struct htable *htable_check(const struct htable *ht, const char *abortstr)
463 {
464         void *p;
465         struct htable_iter i;
466         size_t n = 0;
467         const uintptr_t *validpair = actually_valid_pair(ht);
468
469         /* Use non-DEBUG versions here, to avoid infinite recursion with
470          * CCAN_HTABLE_DEBUG! */
471         for (p = htable_first_(ht, &i); p; p = htable_next_(ht, &i)) {
472                 struct htable_iter i2;
473                 void *c;
474                 size_t h = ht->rehash(p, ht->priv);
475                 bool found = false;
476
477                 n++;
478
479                 /* Open-code htable_get to avoid CCAN_HTABLE_DEBUG */
480                 for (c = htable_firstval_(ht, &i2, h);
481                      c;
482                      c = htable_nextval_(ht, &i2, h)) {
483                         if (c == p) {
484                                 found = true;
485                                 break;
486                         }
487                 }
488
489                 if (!found) {
490                         if (abortstr) {
491                                 fprintf(stderr,
492                                         "%s: element %p in position %zu"
493                                         " cannot find itself\n",
494                                         abortstr, p, i.off);
495                                 abort();
496                         }
497                         return NULL;
498                 }
499         }
500         if (n != ht->elems) {
501                 if (abortstr) {
502                         fprintf(stderr,
503                                 "%s: found %zu elems, expected %zu\n",
504                                 abortstr, n, ht->elems);
505                         abort();
506                 }
507                 return NULL;
508         }
509
510         /* Check validpair does actually override invalid-looking entries! */
511         if (ht->table != &ht->common_bits) {
512                 size_t i;
513                 for (i = 0; i < 2; i++) {
514                         if (validpair[i] == ((size_t)1 << ht->bits))
515                                 continue;
516                         if (validpair[i] > ((size_t)1 << ht->bits)) {
517                                 if (abortstr) {
518                                         fprintf(stderr,
519                                                 "%s: validpair[%zu] points at %zu"
520                                                 " which is out of bounds\n",
521                                                 abortstr, i, validpair[i]);
522                                         abort();
523                                 }
524                                 return NULL;
525                         }
526                         if (entry_looks_invalid(ht, validpair[i]))
527                                 continue;
528
529                         if (abortstr) {
530                                 fprintf(stderr,
531                                         "%s: validpair[%zu] points at %zu"
532                                         " which seems valid\n",
533                                         abortstr, i, validpair[i]);
534                                 abort();
535                         }
536                         return NULL;
537                 }
538         }
539
540         return (struct htable *)ht;
541 }