1 /* Licensed under LGPLv2+ - see LICENSE file for details */
2 #include <ccan/htable/htable.h>
3 #include <ccan/compiler/compiler.h>
10 /* This means a struct htable takes at least 512 bytes / 1k (32/64 bits). */
11 #define HTABLE_BASE_BITS 7
13 /* We use 0x1 as deleted marker. */
14 #define HTABLE_DELETED (0x1)
17 size_t (*rehash
)(const void *elem
, void *priv
);
20 size_t elems
, deleted
, max
, max_with_deleted
;
21 /* These are the bits which are the same in all pointers. */
22 uintptr_t common_mask
, common_bits
;
23 uintptr_t perfect_bit
;
27 /* We clear out the bits which are always the same, and put metadata there. */
28 static inline uintptr_t get_extra_ptr_bits(const struct htable
*ht
,
31 return e
& ht
->common_mask
;
34 static inline void *get_raw_ptr(const struct htable
*ht
, uintptr_t e
)
36 return (void *)((e
& ~ht
->common_mask
) | ht
->common_bits
);
39 static inline uintptr_t make_hval(const struct htable
*ht
,
40 const void *p
, uintptr_t bits
)
42 return ((uintptr_t)p
& ~ht
->common_mask
) | bits
;
45 static inline bool entry_is_valid(uintptr_t e
)
47 return e
> HTABLE_DELETED
;
50 static inline uintptr_t get_hash_ptr_bits(const struct htable
*ht
,
53 /* Shuffling the extra bits (as specified in mask) down the
54 * end is quite expensive. But the lower bits are redundant, so
55 * we fold the value first. */
56 return (hash
^ (hash
>> ht
->bits
))
57 & ht
->common_mask
& ~ht
->perfect_bit
;
60 struct htable
*htable_new(size_t (*rehash
)(const void *elem
, void *priv
),
63 struct htable
*ht
= malloc(sizeof(struct htable
));
65 ht
->bits
= HTABLE_BASE_BITS
;
70 ht
->max
= ((size_t)1 << ht
->bits
) * 3 / 4;
71 ht
->max_with_deleted
= ((size_t)1 << ht
->bits
) * 9 / 10;
72 /* This guarantees we enter update_common first add. */
76 ht
->table
= calloc(1 << ht
->bits
, sizeof(uintptr_t));
85 void htable_free(const struct htable
*ht
)
87 free((void *)ht
->table
);
91 static size_t hash_bucket(const struct htable
*ht
, size_t h
)
93 return h
& ((1 << ht
->bits
)-1);
96 static void *htable_val(const struct htable
*ht
,
97 struct htable_iter
*i
, size_t hash
, uintptr_t perfect
)
99 uintptr_t h2
= get_hash_ptr_bits(ht
, hash
) | perfect
;
101 while (ht
->table
[i
->off
]) {
102 if (ht
->table
[i
->off
] != HTABLE_DELETED
) {
103 if (get_extra_ptr_bits(ht
, ht
->table
[i
->off
]) == h2
)
104 return get_raw_ptr(ht
, ht
->table
[i
->off
]);
106 i
->off
= (i
->off
+ 1) & ((1 << ht
->bits
)-1);
112 void *htable_firstval(const struct htable
*ht
,
113 struct htable_iter
*i
, size_t hash
)
115 i
->off
= hash_bucket(ht
, hash
);
116 return htable_val(ht
, i
, hash
, ht
->perfect_bit
);
119 void *htable_nextval(const struct htable
*ht
,
120 struct htable_iter
*i
, size_t hash
)
122 i
->off
= (i
->off
+ 1) & ((1 << ht
->bits
)-1);
123 return htable_val(ht
, i
, hash
, 0);
126 void *htable_first(const struct htable
*ht
, struct htable_iter
*i
)
128 for (i
->off
= 0; i
->off
< (size_t)1 << ht
->bits
; i
->off
++) {
129 if (entry_is_valid(ht
->table
[i
->off
]))
130 return get_raw_ptr(ht
, ht
->table
[i
->off
]);
135 void *htable_next(const struct htable
*ht
, struct htable_iter
*i
)
137 for (i
->off
++; i
->off
< (size_t)1 << ht
->bits
; i
->off
++) {
138 if (entry_is_valid(ht
->table
[i
->off
]))
139 return get_raw_ptr(ht
, ht
->table
[i
->off
]);
144 /* This does not expand the hash table, that's up to caller. */
145 static void ht_add(struct htable
*ht
, const void *new, size_t h
)
148 uintptr_t perfect
= ht
->perfect_bit
;
150 i
= hash_bucket(ht
, h
);
152 while (entry_is_valid(ht
->table
[i
])) {
154 i
= (i
+ 1) & ((1 << ht
->bits
)-1);
156 ht
->table
[i
] = make_hval(ht
, new, get_hash_ptr_bits(ht
, h
)|perfect
);
159 static COLD
bool double_table(struct htable
*ht
)
162 size_t oldnum
= (size_t)1 << ht
->bits
;
163 uintptr_t *oldtable
, e
;
165 oldtable
= ht
->table
;
166 ht
->table
= calloc(1 << (ht
->bits
+1), sizeof(size_t));
168 ht
->table
= oldtable
;
173 ht
->max_with_deleted
*= 2;
175 /* If we lost our "perfect bit", get it back now. */
176 if (!ht
->perfect_bit
&& ht
->common_mask
) {
177 for (i
= 0; i
< sizeof(ht
->common_mask
) * CHAR_BIT
; i
++) {
178 if (ht
->common_mask
& ((size_t)1 << i
)) {
179 ht
->perfect_bit
= (size_t)1 << i
;
185 for (i
= 0; i
< oldnum
; i
++) {
186 if (entry_is_valid(e
= oldtable
[i
])) {
187 void *p
= get_raw_ptr(ht
, e
);
188 ht_add(ht
, p
, ht
->rehash(p
, ht
->priv
));
196 static COLD
void rehash_table(struct htable
*ht
)
201 /* Beware wrap cases: we need to start from first empty bucket. */
202 for (start
= 0; ht
->table
[start
]; start
++);
204 for (i
= 0; i
< (size_t)1 << ht
->bits
; i
++) {
205 size_t h
= (i
+ start
) & ((1 << ht
->bits
)-1);
209 if (e
== HTABLE_DELETED
)
211 else if (!(e
& ht
->perfect_bit
)) {
212 void *p
= get_raw_ptr(ht
, e
);
214 ht_add(ht
, p
, ht
->rehash(p
, ht
->priv
));
220 /* We stole some bits, now we need to put them back... */
221 static COLD
void update_common(struct htable
*ht
, const void *p
)
224 uintptr_t maskdiff
, bitsdiff
;
226 if (ht
->elems
== 0) {
227 ht
->common_mask
= -1;
228 ht
->common_bits
= (uintptr_t)p
;
233 /* Find bits which are unequal to old common set. */
234 maskdiff
= ht
->common_bits
^ ((uintptr_t)p
& ht
->common_mask
);
236 /* These are the bits which go there in existing entries. */
237 bitsdiff
= ht
->common_bits
& maskdiff
;
239 for (i
= 0; i
< (size_t)1 << ht
->bits
; i
++) {
240 if (!entry_is_valid(ht
->table
[i
]))
242 /* Clear the bits no longer in the mask, set them as
244 ht
->table
[i
] &= ~maskdiff
;
245 ht
->table
[i
] |= bitsdiff
;
248 /* Take away those bits from our mask, bits and perfect bit. */
249 ht
->common_mask
&= ~maskdiff
;
250 ht
->common_bits
&= ~maskdiff
;
251 ht
->perfect_bit
&= ~maskdiff
;
254 bool htable_add(struct htable
*ht
, size_t hash
, const void *p
)
256 if (ht
->elems
+1 > ht
->max
&& !double_table(ht
))
258 if (ht
->elems
+1 + ht
->deleted
> ht
->max_with_deleted
)
261 if (((uintptr_t)p
& ht
->common_mask
) != ht
->common_bits
)
262 update_common(ht
, p
);
269 bool htable_del(struct htable
*ht
, size_t h
, const void *p
)
271 struct htable_iter i
;
274 for (c
= htable_firstval(ht
,&i
,h
); c
; c
= htable_nextval(ht
,&i
,h
)) {
276 htable_delval(ht
, &i
);
283 void htable_delval(struct htable
*ht
, struct htable_iter
*i
)
285 assert(i
->off
< (size_t)1 << ht
->bits
);
286 assert(entry_is_valid(ht
->table
[i
->off
]));
289 ht
->table
[i
->off
] = HTABLE_DELETED
;