From 9dd095ec1b653ccea9c55626379eb1f71c53663e Mon Sep 17 00:00:00 2001 From: tidwall Date: Sun, 6 Dec 2020 16:47:52 -0700 Subject: [PATCH] Added hashmap_clear function 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. closes #1 --- hashmap.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ hashmap.h | 1 + 2 files changed, 54 insertions(+) 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);