blob: 09501de199b0e61fc0be38527443adb872e08fe4 [file] [log] [blame]
Victor Stinner285cf0a2016-03-21 22:00:58 +01001/* The implementation of the hash table (_Py_hashtable_t) is based on the
2 cfuhash project:
Victor Stinnered3b0bc2013-11-23 12:27:24 +01003 http://sourceforge.net/projects/libcfu/
4
5 Copyright of cfuhash:
6 ----------------------------------
7 Creation date: 2005-06-24 21:22:40
8 Authors: Don
9 Change log:
10
11 Copyright (c) 2005 Don Owens
12 All rights reserved.
13
14 This code is released under the BSD license:
15
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions
18 are met:
19
20 * Redistributions of source code must retain the above copyright
21 notice, this list of conditions and the following disclaimer.
22
23 * Redistributions in binary form must reproduce the above
24 copyright notice, this list of conditions and the following
25 disclaimer in the documentation and/or other materials provided
26 with the distribution.
27
28 * Neither the name of the author nor the names of its
29 contributors may be used to endorse or promote products derived
30 from this software without specific prior written permission.
31
32 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
36 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
37 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43 OF THE POSSIBILITY OF SUCH DAMAGE.
44 ----------------------------------
45*/
46
47#include "Python.h"
Victor Stinnerb6179932020-05-12 02:42:19 +020048#include "pycore_hashtable.h"
Victor Stinnered3b0bc2013-11-23 12:27:24 +010049
50#define HASHTABLE_MIN_SIZE 16
51#define HASHTABLE_HIGH 0.50
52#define HASHTABLE_LOW 0.10
53#define HASHTABLE_REHASH_FACTOR 2.0 / (HASHTABLE_LOW + HASHTABLE_HIGH)
54
55#define BUCKETS_HEAD(SLIST) \
56 ((_Py_hashtable_entry_t *)_Py_SLIST_HEAD(&(SLIST)))
57#define TABLE_HEAD(HT, BUCKET) \
58 ((_Py_hashtable_entry_t *)_Py_SLIST_HEAD(&(HT)->buckets[BUCKET]))
59#define ENTRY_NEXT(ENTRY) \
60 ((_Py_hashtable_entry_t *)_Py_SLIST_ITEM_NEXT(ENTRY))
Victor Stinner5dacbd42016-03-23 09:52:13 +010061
Victor Stinnered3b0bc2013-11-23 12:27:24 +010062/* Forward declaration */
Victor Stinnerd2dc8272020-05-14 22:44:32 +020063static int hashtable_rehash(_Py_hashtable_t *ht);
Victor Stinnered3b0bc2013-11-23 12:27:24 +010064
65static void
66_Py_slist_init(_Py_slist_t *list)
67{
68 list->head = NULL;
69}
70
Victor Stinner285cf0a2016-03-21 22:00:58 +010071
Victor Stinnered3b0bc2013-11-23 12:27:24 +010072static void
73_Py_slist_prepend(_Py_slist_t *list, _Py_slist_item_t *item)
74{
75 item->next = list->head;
76 list->head = item;
77}
78
Victor Stinner285cf0a2016-03-21 22:00:58 +010079
Victor Stinnered3b0bc2013-11-23 12:27:24 +010080static void
81_Py_slist_remove(_Py_slist_t *list, _Py_slist_item_t *previous,
82 _Py_slist_item_t *item)
83{
84 if (previous != NULL)
85 previous->next = item->next;
86 else
87 list->head = item->next;
88}
89
Victor Stinnered3b0bc2013-11-23 12:27:24 +010090
Victor Stinner322bc122016-03-21 14:36:39 +010091Py_uhash_t
Victor Stinnerf9b3b582020-05-13 02:26:02 +020092_Py_hashtable_hash_ptr(const void *key)
Victor Stinner322bc122016-03-21 14:36:39 +010093{
Victor Stinnerf4532212020-05-12 18:46:20 +020094 return (Py_uhash_t)_Py_HashPointerRaw(key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +010095}
96
Victor Stinner285cf0a2016-03-21 22:00:58 +010097
Victor Stinnered3b0bc2013-11-23 12:27:24 +010098int
Victor Stinnerf9b3b582020-05-13 02:26:02 +020099_Py_hashtable_compare_direct(const void *key1, const void *key2)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100100{
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200101 return (key1 == key2);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100102}
103
Victor Stinner285cf0a2016-03-21 22:00:58 +0100104
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100105/* makes sure the real size of the buckets array is a power of 2 */
106static size_t
107round_size(size_t s)
108{
109 size_t i;
110 if (s < HASHTABLE_MIN_SIZE)
111 return HASHTABLE_MIN_SIZE;
112 i = 1;
113 while (i < s)
114 i <<= 1;
115 return i;
116}
117
Victor Stinner285cf0a2016-03-21 22:00:58 +0100118
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100119size_t
Victor Stinner5b0a3032020-05-13 04:40:30 +0200120_Py_hashtable_size(const _Py_hashtable_t *ht)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100121{
Victor Stinnera482dc52020-05-14 21:55:47 +0200122 size_t size = sizeof(_Py_hashtable_t);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100123 /* buckets */
Victor Stinnera482dc52020-05-14 21:55:47 +0200124 size += ht->nbuckets * sizeof(_Py_hashtable_entry_t *);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100125 /* entries */
Victor Stinnera482dc52020-05-14 21:55:47 +0200126 size += ht->nentries * sizeof(_Py_hashtable_entry_t);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100127 return size;
128}
129
Victor Stinner285cf0a2016-03-21 22:00:58 +0100130
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100131_Py_hashtable_entry_t *
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200132_Py_hashtable_get_entry_generic(_Py_hashtable_t *ht, const void *key)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100133{
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200134 Py_uhash_t key_hash = ht->hash_func(key);
Victor Stinnera482dc52020-05-14 21:55:47 +0200135 size_t index = key_hash & (ht->nbuckets - 1);
Christian Heimes4901ea92020-06-22 09:41:48 +0200136 _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index);
Victor Stinner7c6e9702020-05-12 13:31:59 +0200137 while (1) {
138 if (entry == NULL) {
139 return NULL;
140 }
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200141 if (entry->key_hash == key_hash && ht->compare_func(key, entry->key)) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100142 break;
Victor Stinner7c6e9702020-05-12 13:31:59 +0200143 }
144 entry = ENTRY_NEXT(entry);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100145 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100146 return entry;
147}
148
Victor Stinner285cf0a2016-03-21 22:00:58 +0100149
Victor Stinner42bae3a2020-05-13 05:36:23 +0200150// Specialized for:
151// hash_func == _Py_hashtable_hash_ptr
152// compare_func == _Py_hashtable_compare_direct
153static _Py_hashtable_entry_t *
154_Py_hashtable_get_entry_ptr(_Py_hashtable_t *ht, const void *key)
155{
156 Py_uhash_t key_hash = _Py_hashtable_hash_ptr(key);
Victor Stinnera482dc52020-05-14 21:55:47 +0200157 size_t index = key_hash & (ht->nbuckets - 1);
Christian Heimes4901ea92020-06-22 09:41:48 +0200158 _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index);
Victor Stinner42bae3a2020-05-13 05:36:23 +0200159 while (1) {
160 if (entry == NULL) {
161 return NULL;
162 }
163 // Compare directly keys (ignore entry->key_hash)
164 if (entry->key == key) {
165 break;
166 }
167 entry = ENTRY_NEXT(entry);
168 }
169 return entry;
170}
171
172
Victor Stinner5b0a3032020-05-13 04:40:30 +0200173void*
174_Py_hashtable_steal(_Py_hashtable_t *ht, const void *key)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100175{
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200176 Py_uhash_t key_hash = ht->hash_func(key);
Victor Stinnera482dc52020-05-14 21:55:47 +0200177 size_t index = key_hash & (ht->nbuckets - 1);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100178
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200179 _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index);
180 _Py_hashtable_entry_t *previous = NULL;
181 while (1) {
182 if (entry == NULL) {
183 // not found
Victor Stinner5b0a3032020-05-13 04:40:30 +0200184 return NULL;
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200185 }
186 if (entry->key_hash == key_hash && ht->compare_func(key, entry->key)) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100187 break;
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200188 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100189 previous = entry;
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200190 entry = ENTRY_NEXT(entry);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100191 }
192
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100193 _Py_slist_remove(&ht->buckets[index], (_Py_slist_item_t *)previous,
194 (_Py_slist_item_t *)entry);
Victor Stinnera482dc52020-05-14 21:55:47 +0200195 ht->nentries--;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100196
Victor Stinner5b0a3032020-05-13 04:40:30 +0200197 void *value = entry->value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100198 ht->alloc.free(entry);
199
Victor Stinnera482dc52020-05-14 21:55:47 +0200200 if ((float)ht->nentries / (float)ht->nbuckets < HASHTABLE_LOW) {
Victor Stinnerd2dc8272020-05-14 22:44:32 +0200201 // Ignore failure: error cannot be reported to the caller
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100202 hashtable_rehash(ht);
Victor Stinner5b0a3032020-05-13 04:40:30 +0200203 }
204 return value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100205}
206
Victor Stinner285cf0a2016-03-21 22:00:58 +0100207
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100208int
Victor Stinner5b0a3032020-05-13 04:40:30 +0200209_Py_hashtable_set(_Py_hashtable_t *ht, const void *key, void *value)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100210{
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100211 _Py_hashtable_entry_t *entry;
212
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100213#ifndef NDEBUG
214 /* Don't write the assertion on a single line because it is interesting
215 to know the duplicated entry if the assertion failed. The entry can
216 be read using a debugger. */
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200217 entry = ht->get_entry_func(ht, key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100218 assert(entry == NULL);
219#endif
220
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100221
Victor Stinner5b0a3032020-05-13 04:40:30 +0200222 entry = ht->alloc.malloc(sizeof(_Py_hashtable_entry_t));
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100223 if (entry == NULL) {
224 /* memory allocation failed */
225 return -1;
226 }
227
Victor Stinnera482dc52020-05-14 21:55:47 +0200228 entry->key_hash = ht->hash_func(key);
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200229 entry->key = (void *)key;
Victor Stinner5b0a3032020-05-13 04:40:30 +0200230 entry->value = value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100231
Victor Stinnerd2dc8272020-05-14 22:44:32 +0200232 ht->nentries++;
233 if ((float)ht->nentries / (float)ht->nbuckets > HASHTABLE_HIGH) {
234 if (hashtable_rehash(ht) < 0) {
235 ht->nentries--;
236 ht->alloc.free(entry);
237 return -1;
238 }
239 }
240
Victor Stinnera482dc52020-05-14 21:55:47 +0200241 size_t index = entry->key_hash & (ht->nbuckets - 1);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100242 _Py_slist_prepend(&ht->buckets[index], (_Py_slist_item_t*)entry);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100243 return 0;
244}
245
Victor Stinner285cf0a2016-03-21 22:00:58 +0100246
Victor Stinner5b0a3032020-05-13 04:40:30 +0200247void*
248_Py_hashtable_get(_Py_hashtable_t *ht, const void *key)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100249{
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200250 _Py_hashtable_entry_t *entry = ht->get_entry_func(ht, key);
Victor Stinner7c6e9702020-05-12 13:31:59 +0200251 if (entry != NULL) {
Victor Stinner5b0a3032020-05-13 04:40:30 +0200252 return entry->value;
Victor Stinner7c6e9702020-05-12 13:31:59 +0200253 }
254 else {
Victor Stinner5b0a3032020-05-13 04:40:30 +0200255 return NULL;
Victor Stinner7c6e9702020-05-12 13:31:59 +0200256 }
257}
258
259
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100260int
261_Py_hashtable_foreach(_Py_hashtable_t *ht,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100262 _Py_hashtable_foreach_func func,
Victor Stinner5b0a3032020-05-13 04:40:30 +0200263 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100264{
Victor Stinnera482dc52020-05-14 21:55:47 +0200265 for (size_t hv = 0; hv < ht->nbuckets; hv++) {
266 _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, hv);
267 while (entry != NULL) {
Victor Stinner5b0a3032020-05-13 04:40:30 +0200268 int res = func(ht, entry->key, entry->value, user_data);
Victor Stinnera482dc52020-05-14 21:55:47 +0200269 if (res) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100270 return res;
Victor Stinnera482dc52020-05-14 21:55:47 +0200271 }
272 entry = ENTRY_NEXT(entry);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100273 }
274 }
275 return 0;
276}
277
Victor Stinner285cf0a2016-03-21 22:00:58 +0100278
Victor Stinnerd2dc8272020-05-14 22:44:32 +0200279static int
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100280hashtable_rehash(_Py_hashtable_t *ht)
281{
Victor Stinnera482dc52020-05-14 21:55:47 +0200282 size_t new_size = round_size((size_t)(ht->nentries * HASHTABLE_REHASH_FACTOR));
283 if (new_size == ht->nbuckets) {
Victor Stinnerd2dc8272020-05-14 22:44:32 +0200284 return 0;
Victor Stinnera482dc52020-05-14 21:55:47 +0200285 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100286
Victor Stinnera482dc52020-05-14 21:55:47 +0200287 size_t buckets_size = new_size * sizeof(ht->buckets[0]);
288 _Py_slist_t *new_buckets = ht->alloc.malloc(buckets_size);
289 if (new_buckets == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100290 /* memory allocation failed */
Victor Stinnerd2dc8272020-05-14 22:44:32 +0200291 return -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100292 }
Victor Stinnera482dc52020-05-14 21:55:47 +0200293 memset(new_buckets, 0, buckets_size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100294
Victor Stinnera482dc52020-05-14 21:55:47 +0200295 for (size_t bucket = 0; bucket < ht->nbuckets; bucket++) {
296 _Py_hashtable_entry_t *entry = BUCKETS_HEAD(ht->buckets[bucket]);
297 while (entry != NULL) {
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200298 assert(ht->hash_func(entry->key) == entry->key_hash);
Victor Stinnera482dc52020-05-14 21:55:47 +0200299 _Py_hashtable_entry_t *next = ENTRY_NEXT(entry);
300 size_t entry_index = entry->key_hash & (new_size - 1);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100301
Victor Stinnera482dc52020-05-14 21:55:47 +0200302 _Py_slist_prepend(&new_buckets[entry_index], (_Py_slist_item_t*)entry);
303
304 entry = next;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100305 }
306 }
307
Victor Stinnera482dc52020-05-14 21:55:47 +0200308 ht->alloc.free(ht->buckets);
309 ht->nbuckets = new_size;
310 ht->buckets = new_buckets;
Victor Stinnerd2dc8272020-05-14 22:44:32 +0200311 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100312}
313
Victor Stinner285cf0a2016-03-21 22:00:58 +0100314
Victor Stinner7c6e9702020-05-12 13:31:59 +0200315_Py_hashtable_t *
Victor Stinner5b0a3032020-05-13 04:40:30 +0200316_Py_hashtable_new_full(_Py_hashtable_hash_func hash_func,
Victor Stinner7c6e9702020-05-12 13:31:59 +0200317 _Py_hashtable_compare_func compare_func,
Victor Stinner2d0a3d62020-05-13 02:50:18 +0200318 _Py_hashtable_destroy_func key_destroy_func,
Victor Stinner5b0a3032020-05-13 04:40:30 +0200319 _Py_hashtable_destroy_func value_destroy_func,
Victor Stinner7c6e9702020-05-12 13:31:59 +0200320 _Py_hashtable_allocator_t *allocator)
321{
Victor Stinner7c6e9702020-05-12 13:31:59 +0200322 _Py_hashtable_allocator_t alloc;
Victor Stinner7c6e9702020-05-12 13:31:59 +0200323 if (allocator == NULL) {
324 alloc.malloc = PyMem_Malloc;
325 alloc.free = PyMem_Free;
326 }
327 else {
328 alloc = *allocator;
329 }
330
Victor Stinnera482dc52020-05-14 21:55:47 +0200331 _Py_hashtable_t *ht = (_Py_hashtable_t *)alloc.malloc(sizeof(_Py_hashtable_t));
332 if (ht == NULL) {
Victor Stinner7c6e9702020-05-12 13:31:59 +0200333 return ht;
Victor Stinnera482dc52020-05-14 21:55:47 +0200334 }
Victor Stinner7c6e9702020-05-12 13:31:59 +0200335
Victor Stinnera482dc52020-05-14 21:55:47 +0200336 ht->nbuckets = HASHTABLE_MIN_SIZE;
337 ht->nentries = 0;
Victor Stinner7c6e9702020-05-12 13:31:59 +0200338
Victor Stinnera482dc52020-05-14 21:55:47 +0200339 size_t buckets_size = ht->nbuckets * sizeof(ht->buckets[0]);
Victor Stinner7c6e9702020-05-12 13:31:59 +0200340 ht->buckets = alloc.malloc(buckets_size);
341 if (ht->buckets == NULL) {
342 alloc.free(ht);
343 return NULL;
344 }
345 memset(ht->buckets, 0, buckets_size);
346
Victor Stinner7c6e9702020-05-12 13:31:59 +0200347 ht->get_entry_func = _Py_hashtable_get_entry_generic;
348 ht->hash_func = hash_func;
349 ht->compare_func = compare_func;
Victor Stinner2d0a3d62020-05-13 02:50:18 +0200350 ht->key_destroy_func = key_destroy_func;
351 ht->value_destroy_func = value_destroy_func;
Victor Stinner7c6e9702020-05-12 13:31:59 +0200352 ht->alloc = alloc;
Victor Stinnerf9b3b582020-05-13 02:26:02 +0200353 if (ht->hash_func == _Py_hashtable_hash_ptr
Victor Stinner7c6e9702020-05-12 13:31:59 +0200354 && ht->compare_func == _Py_hashtable_compare_direct)
355 {
Victor Stinner7c6e9702020-05-12 13:31:59 +0200356 ht->get_entry_func = _Py_hashtable_get_entry_ptr;
357 }
358 return ht;
359}
360
361
362_Py_hashtable_t *
Victor Stinner5b0a3032020-05-13 04:40:30 +0200363_Py_hashtable_new(_Py_hashtable_hash_func hash_func,
Victor Stinner7c6e9702020-05-12 13:31:59 +0200364 _Py_hashtable_compare_func compare_func)
365{
Victor Stinner5b0a3032020-05-13 04:40:30 +0200366 return _Py_hashtable_new_full(hash_func, compare_func,
Victor Stinner2d0a3d62020-05-13 02:50:18 +0200367 NULL, NULL, NULL);
Victor Stinner7c6e9702020-05-12 13:31:59 +0200368}
369
370
Victor Stinner5b0a3032020-05-13 04:40:30 +0200371static void
372_Py_hashtable_destroy_entry(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry)
373{
374 if (ht->key_destroy_func) {
375 ht->key_destroy_func(entry->key);
376 }
377 if (ht->value_destroy_func) {
378 ht->value_destroy_func(entry->value);
379 }
380 ht->alloc.free(entry);
381}
382
383
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100384void
385_Py_hashtable_clear(_Py_hashtable_t *ht)
386{
Victor Stinnera482dc52020-05-14 21:55:47 +0200387 for (size_t i=0; i < ht->nbuckets; i++) {
388 _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, i);
389 while (entry != NULL) {
390 _Py_hashtable_entry_t *next = ENTRY_NEXT(entry);
Victor Stinner5b0a3032020-05-13 04:40:30 +0200391 _Py_hashtable_destroy_entry(ht, entry);
Victor Stinnera482dc52020-05-14 21:55:47 +0200392 entry = next;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100393 }
394 _Py_slist_init(&ht->buckets[i]);
395 }
Victor Stinnera482dc52020-05-14 21:55:47 +0200396 ht->nentries = 0;
Victor Stinnerd2dc8272020-05-14 22:44:32 +0200397 // Ignore failure: clear function is not expected to fail
398 // because of a memory allocation failure.
399 (void)hashtable_rehash(ht);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100400}
401
Victor Stinner285cf0a2016-03-21 22:00:58 +0100402
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100403void
404_Py_hashtable_destroy(_Py_hashtable_t *ht)
405{
Victor Stinnera482dc52020-05-14 21:55:47 +0200406 for (size_t i = 0; i < ht->nbuckets; i++) {
Victor Stinner2d0a3d62020-05-13 02:50:18 +0200407 _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, i);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100408 while (entry) {
Victor Stinner2d0a3d62020-05-13 02:50:18 +0200409 _Py_hashtable_entry_t *entry_next = ENTRY_NEXT(entry);
410 _Py_hashtable_destroy_entry(ht, entry);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100411 entry = entry_next;
412 }
413 }
414
415 ht->alloc.free(ht->buckets);
416 ht->alloc.free(ht);
417}