commit 5cd68ce386f53c7cb088f2cce0100262f0edbba7 Author: Andrey V. Elsukov Date: Thu Aug 29 17:35:08 2019 +0300 Add ck_hs_reset_drain() function diff --git a/sys/contrib/ck/include/ck_hs.h b/sys/contrib/ck/include/ck_hs.h index 3c12b6e602a..7f978335162 100644 --- a/sys/contrib/ck/include/ck_hs.h +++ b/sys/contrib/ck/include/ck_hs.h @@ -75,6 +75,11 @@ typedef unsigned long ck_hs_hash_cb_t(const void *, unsigned long); */ typedef bool ck_hs_compare_cb_t(const void *, const void *); +/* + * Destroy item callback. + */ +typedef void ck_hs_destroy_item_cb_t(void *); + #if defined(CK_MD_POINTER_PACK_ENABLE) && defined(CK_MD_VMA_BITS) #define CK_HS_PP #define CK_HS_KEY_MASK ((1U << ((sizeof(void *) * 8) - CK_MD_VMA_BITS)) - 1) @@ -131,6 +136,7 @@ bool ck_hs_gc(ck_hs_t *, unsigned long, unsigned long); 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); +bool ck_hs_reset_drain(ck_hs_t *, ck_hs_destroy_item_cb_t *); void ck_hs_stat(ck_hs_t *, struct ck_hs_stat *); #endif /* CK_HS_H */ diff --git a/sys/contrib/ck/src/ck_hs.c b/sys/contrib/ck/src/ck_hs.c index a7e15eaddbe..64218ecc5af 100644 --- a/sys/contrib/ck/src/ck_hs.c +++ b/sys/contrib/ck/src/ck_hs.c @@ -246,17 +246,29 @@ ck_hs_map_create(struct ck_hs *hs, unsigned long entries) return map; } -bool -ck_hs_reset_size(struct ck_hs *hs, unsigned long capacity) +static struct ck_hs_map * +_ck_hs_reset_size(struct ck_hs *hs, unsigned long capacity) { struct ck_hs_map *map, *previous; previous = hs->map; map = ck_hs_map_create(hs, capacity); if (map == NULL) - return false; + return (NULL); ck_pr_store_ptr(&hs->map, map); + return (previous); +} + +bool +ck_hs_reset_size(struct ck_hs *hs, unsigned long capacity) +{ + struct ck_hs_map *previous; + + previous = _ck_hs_reset_size(hs, capacity); + if (previous == NULL) + return false; + ck_hs_map_destroy(hs->m, previous, true); return true; } @@ -270,6 +282,35 @@ ck_hs_reset(struct ck_hs *hs) return ck_hs_reset_size(hs, previous->capacity); } +bool +ck_hs_reset_drain(struct ck_hs *hs, ck_hs_destroy_item_cb_t *fn) +{ + struct ck_hs_map *map; + unsigned long capacity, offset; + void *value; + + capacity = hs->map->capacity; + map = _ck_hs_reset_size(hs, capacity); + if (map == NULL) + return (false); + + offset = 0; + do { + value = CK_CC_DECONST_PTR(map->entries[offset]); + if (value != CK_HS_EMPTY && value != CK_HS_TOMBSTONE) { +#ifdef CK_HS_PP + if (hs->mode & CK_HS_MODE_OBJECT) + value = CK_HS_VMA(value); +#endif + offset++; + fn(value); + } + } while (++offset < capacity); + + ck_hs_map_destroy(hs->m, map, true); + return (true); +} + static inline unsigned long ck_hs_map_probe_next(struct ck_hs_map *map, unsigned long offset,