From 9baa37f5e4e780bf655c3d0d05d93a44d38e003b Mon Sep 17 00:00:00 2001 From: Arthur O'Dwyer Date: Wed, 6 Jan 2021 09:53:59 -0500 Subject: [PATCH] Add HASH_FREE_AND_CLEAR. Still needs tests. --- doc/userguide.txt | 34 ++++++++++++++++++++++++++++++---- src/uthash.h | 19 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/doc/userguide.txt b/doc/userguide.txt index b24ee337..11133d36 100644 --- a/doc/userguide.txt +++ b/doc/userguide.txt @@ -382,13 +382,39 @@ void delete_all() { } ---------------------------------------------------------------------- -All-at-once deletion -^^^^^^^^^^^^^^^^^^^^ -If you only want to delete all the items, but not free them or do any -per-element clean up, you can do this more efficiently in a single operation: +All-at-once deletion with cleanup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If you want to delete absolutely all the items, +you can do this more efficiently in a single operation: + +.Delete all items from a hash, faster +---------------------------------------------------------------------- +void delete_all_faster() { + HASH_FREE_AND_CLEAR(hh, users, free); +} +---------------------------------------------------------------------- + +Afterward, the list head (here, `users`) will be set to `NULL`. + +This is equivalent to the `HASH_ITER` approach, but it skips fixing up +all of the prev/next pointers on each iteration. Note that if the +specified deleter (here, `free`) ever does a `longjmp` or otherwise exits +non-locally, the hash table will be left in an inconsistent and +unusable state. + +All-at-once deletion without cleanup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If you only want to delete all the items from the hash, but not do any +per-element cleanup (such as `free`), you can do this in constant time: HASH_CLEAR(hh,users); +`HASH_CLEAR` has the same effect as + + HASH_FREE_AND_CLEAR(hh,users,item,(void)); + +but is much faster because it does not iterate the hash. + Afterward, the list head (here, `users`) will be set to `NULL`. Count items diff --git a/src/uthash.h b/src/uthash.h index 8ab39815..96f58ec9 100644 --- a/src/uthash.h +++ b/src/uthash.h @@ -1041,6 +1041,25 @@ do { } \ } while (0) +#define HASH_FREE_AND_CLEAR(hh,head,el,deleter) \ +do { \ + if ((head) != NULL) { \ + void *_hh_fac_next = (head); \ + while (1) { \ + (el) = DECLTYPE(el)(_hh_fac_next); \ + _hh_fac_next = (el)->hh.next; \ + if (_hh_fac_next == NULL) break; \ + deleter(el); \ + } \ + HASH_BLOOM_FREE((el)->hh.tbl); \ + uthash_free((el)->hh.tbl->buckets, \ + (el)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + uthash_free((el)->hh.tbl, sizeof(UT_hash_table)); \ + deleter(el); \ + (head) = NULL; \ + } \ +} while (0) + #define HASH_OVERHEAD(hh,head) \ (((head) != NULL) ? ( \ (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \