diff --git a/include/ck_hs.h b/include/ck_hs.h index 098ae72..f405ce3 100644 --- a/include/ck_hs.h +++ b/include/ck_hs.h @@ -124,6 +124,7 @@ bool ck_hs_fas(ck_hs_t *, unsigned long, const void *, void **); void *ck_hs_remove(ck_hs_t *, unsigned long, const void *); bool ck_hs_grow(ck_hs_t *, unsigned long); bool ck_hs_rebuild(ck_hs_t *); +bool ck_hs_gc(ck_hs_t *); unsigned long ck_hs_count(ck_hs_t *); bool ck_hs_reset(ck_hs_t *); bool ck_hs_reset_size(ck_hs_t *, unsigned long); diff --git a/src/ck_hs.c b/src/ck_hs.c index 6150bf7..e77948b 100644 --- a/src/ck_hs.c +++ b/src/ck_hs.c @@ -492,6 +492,48 @@ ck_hs_marshal(unsigned int mode, const void *key, unsigned long h) return insert; } +bool +ck_hs_gc(struct ck_hs *hs) +{ + unsigned long i; + struct ck_hs_map *map = hs->map; + unsigned long size = sizeof(CK_HS_WORD) * map->capacity; + CK_HS_WORD *bounds; + + if (map->probe_bound == NULL) + return true; + + bounds = hs->m->malloc(size); + if (bounds == NULL) + return false; + + memset(bounds, 0, size); + for (i = 0; i < map->capacity; i++) { + void **first, *object, *entry; + unsigned long n_probes, offset, h; + + entry = map->entries[i & map->mask]; + if (entry == CK_HS_EMPTY || entry == CK_HS_TOMBSTONE) + continue; + + h = hs->hf(entry, hs->seed); + offset = h & map->mask; + + ck_hs_map_probe(hs, map, &n_probes, &first, h, entry, &object, map->probe_maximum, CK_HS_PROBE); + if (n_probes > CK_HS_WORD_MAX) + n_probes = CK_HS_WORD_MAX; + + if (n_probes > bounds[offset]) + bounds[offset] = n_probes; + } + + for (i = 0; i < map->capacity; i++) + CK_HS_STORE(&map->probe_bound[i], bounds[i]); + + hs->m->free(bounds, size, false); + return true; +} + bool ck_hs_fas(struct ck_hs *hs, unsigned long h,