diff --git a/hashmap.c b/hashmap.c index 17b5dfd..635d4ca 100644 --- a/hashmap.c +++ b/hashmap.c @@ -129,6 +129,29 @@ struct hashmap *hashmap_new(size_t elsize, size_t cap, return map; } +// hashmap_clear quickly clears the map. +// When the update_cap is provided, the map's capacity will be updated to match +// the currently number of allocated buckets. This is an optimization to ensure +// that this operation does not perform any allocations. +void hashmap_clear(struct hashmap *map, bool update_cap) { + map->count = 0; + if (update_cap) { + map->cap = map->nbuckets; + } else if (map->nbuckets != map->cap) { + void *new_buckets = hmmalloc(map->bucketsz*map->cap); + if (new_buckets) { + hmfree(map->buckets); + map->buckets = new_buckets; + } + map->nbuckets = map->cap; + } + memset(map->buckets, 0, map->bucketsz*map->nbuckets); + map->mask = map->nbuckets-1; + map->growat = map->nbuckets*0.75; + map->shrinkat = map->nbuckets*0.10; +} + + static bool resize(struct hashmap *map, size_t new_cap) { struct hashmap *map2 = hashmap_new(map->elsize, new_cap, map->seed1, map->seed1, map->hash, map->compare, @@ -666,6 +689,36 @@ static void all() { assert(v && *v == vals[j]); } } + + for (int i = 0; i < N; i++) { + while (true) { + assert(!hashmap_set(map, &vals[i])); + if (!hashmap_oom(map)) { + break; + } + } + } + + assert(map->count != 0); + size_t prev_cap = map->cap; + hashmap_clear(map, true); + assert(prev_cap < map->cap); + assert(map->count == 0); + + + for (int i = 0; i < N; i++) { + while (true) { + assert(!hashmap_set(map, &vals[i])); + if (!hashmap_oom(map)) { + break; + } + } + } + + prev_cap = map->cap; + hashmap_clear(map, false); + assert(prev_cap == map->cap); + hashmap_free(map); xfree(vals); diff --git a/hashmap.h b/hashmap.h index 5be32d2..6fb083d 100644 --- a/hashmap.h +++ b/hashmap.h @@ -19,6 +19,7 @@ struct hashmap *hashmap_new(size_t elsize, size_t cap, void *udata), void *udata); void hashmap_free(struct hashmap *map); +void hashmap_clear(struct hashmap *map, bool update_cap); size_t hashmap_count(struct hashmap *map); bool hashmap_oom(struct hashmap *map); void *hashmap_get(struct hashmap *map, void *item);