diff --git a/src/lib/cuckoo.c b/src/lib/cuckoo.c index bbcb0e71a..04bf4a31c 100644 --- a/src/lib/cuckoo.c +++ b/src/lib/cuckoo.c @@ -52,6 +52,8 @@ struct cuckoo_struct enum compact_state autocompact; size_t elements; + + cuckoo_dtorfunc dtor; }; @@ -68,7 +70,8 @@ cuckoo_init (Cuckoo self, cuckoo_hashfunc h3, cuckoo_cmpfunc cmp, size_t itemsize, - unsigned startsize) + unsigned startsize, + cuckoo_dtorfunc dtor) { if (!self) return NULL; @@ -101,6 +104,8 @@ cuckoo_init (Cuckoo self, self->autocompact = COMPACTING_AUTO; self->elements = 0; + + self->dtor = dtor; return self; } @@ -110,10 +115,11 @@ cuckoo_new (cuckoo_hashfunc h1, cuckoo_hashfunc h3, cuckoo_cmpfunc cmp, size_t itemsize, - unsigned startsize) + unsigned startsize, + cuckoo_dtorfunc dtor) { Cuckoo self = malloc (sizeof (struct cuckoo_struct)); - if (!cuckoo_init (self, h1, h2, h3, cmp, itemsize, startsize)) + if (!cuckoo_init (self, h1, h2, h3, cmp, itemsize, startsize, dtor)) { free (self); return NULL; @@ -126,6 +132,18 @@ cuckoo_destroy (Cuckoo self) { if (self) { + + if (self->dtor) + { + void* elem; + for (elem = self->t1; elem < self->t1 + self->size * 4; elem += self->size) + self->dtor (elem); + for (elem = self->t2; elem < self->t1 + self->size * 2; elem += self->size) + self->dtor (elem); + for (elem = self->t3; elem < self->t1 + self->size; elem += self->size) + self->dtor (elem); + } + free (self->t1); free (self->t2); free (self->t3); @@ -135,7 +153,7 @@ cuckoo_destroy (Cuckoo self) void -cuckoo_free (Cuckoo self) +cuckoo_delete (Cuckoo self) { free (cuckoo_destroy (self)); } @@ -486,6 +504,9 @@ cuckoo_remove (Cuckoo self, void* item) { if (item) { + if (self->dtor) + self->dtor (item); + memset (item, 0, self->itemsize); --self->elements; diff --git a/src/lib/cuckoo.h b/src/lib/cuckoo.h index 323b5cc75..ed14f6cc8 100644 --- a/src/lib/cuckoo.h +++ b/src/lib/cuckoo.h @@ -54,6 +54,14 @@ typedef size_t (*cuckoo_hashfunc)(const void* item, const uint32_t r); */ typedef int (*cuckoo_cmpfunc)(const void* item1, const void* item2); +/** + * Item destructor function. + * User supplied destructor function. This function is called when items are removed + * from the hash or at hash detroy/delete time. Must be safe to be called on a zeroed element. + * @param item address of the item to be destroyed + */ +typedef void (*cuckoo_dtorfunc)(void* item); + /** * Initialize a cuckoo hash. * @param self pointer to a uninitialized cuckoo datastructure @@ -62,6 +70,7 @@ typedef int (*cuckoo_cmpfunc)(const void* item1, const void* item2); * @param h3 hash function for the third table * @param cmp function which compares two keys * @param startsize initial size of table t3, as 2's exponent + * @param dtor a function used to clean up hash entries, might be NULL if nothing required * @return The initialized hashtable or NULL at allocation failure */ Cuckoo @@ -71,7 +80,8 @@ cuckoo_init (Cuckoo self, cuckoo_hashfunc h3, cuckoo_cmpfunc cmp, size_t itemsize, - unsigned startsize); + unsigned startsize, + cuckoo_dtorfunc dtor); /** * Allocate a new cuckoo hash. @@ -80,6 +90,7 @@ cuckoo_init (Cuckoo self, * @param h3 hash function for the third table * @param cmp function which compares two keys * @param startsize initial size of table t3, as 2's exponent + * @param dtor a function used to clean up hash entries, might be NULL if nothing required * @return The initialized hashtable or NULL at allocation failure */ Cuckoo @@ -88,7 +99,8 @@ cuckoo_new (cuckoo_hashfunc h1, cuckoo_hashfunc h3, cuckoo_cmpfunc cmp, size_t itemsize, - unsigned startsize); + unsigned startsize, + cuckoo_dtorfunc dtor); /** * Destroy a cuckoo hash. @@ -104,7 +116,7 @@ cuckoo_destroy (Cuckoo self); * @param self handle of the hash table to be freed */ void -cuckoo_free (Cuckoo self); +cuckoo_delete (Cuckoo self); /** * Get the number of elements stored in a hash.