diff --git a/src/multi_skiplist.c b/src/multi_skiplist.c index 15cc32c..611f1a6 100644 --- a/src/multi_skiplist.c +++ b/src/multi_skiplist.c @@ -19,6 +19,7 @@ int multi_skiplist_init_ex(MultiSkiplist *sl, const int level_count, multi_skiplist_compare_func compare_func, + multi_skiplist_free_func free_func, const int min_alloc_elements_once) { int bytes; @@ -99,6 +100,7 @@ int multi_skiplist_init_ex(MultiSkiplist *sl, const int level_count, sl->level_count = level_count; sl->compare_func = compare_func; + sl->free_func = free_func; srand(time(NULL)); return 0; @@ -107,11 +109,31 @@ int multi_skiplist_init_ex(MultiSkiplist *sl, const int level_count, void multi_skiplist_destroy(MultiSkiplist *sl) { int i; + MultiSkiplistNode *node; + MultiSkiplistNode *deleted; + MultiSkiplistData *dataCurrent; + MultiSkiplistData *dataNode; if (sl->mblocks == NULL) { return; } + if (sl->free_func != NULL) { + node = sl->top->links[0]; + while (node != sl->tail) { + deleted = node; + node = node->links[0]; + + dataCurrent = deleted->head; + while (dataCurrent != NULL) { + dataNode = dataCurrent; + dataCurrent = dataCurrent->next; + + sl->free_func(dataNode->data); + } + } + } + for (i=0; ilevel_count; i++) { fast_mblock_destroy(sl->mblocks + i); } @@ -151,6 +173,15 @@ DONE: return found; } +static inline void multi_skiplist_free_data_node(MultiSkiplist *sl, + MultiSkiplistData *dataNode) +{ + if (sl->free_func != NULL) { + sl->free_func(dataNode->data); + } + fast_mblock_free_object(&sl->data_mblock, dataNode); +} + static inline int multi_skiplist_get_level_index(MultiSkiplist *sl) { int i; @@ -244,7 +275,8 @@ int multi_skiplist_do_delete(MultiSkiplist *sl, void *data, if (deleted->head->next != NULL) { dataNode = deleted->head; deleted->head = dataNode->next; - fast_mblock_free_object(&sl->data_mblock, dataNode); + + multi_skiplist_free_data_node(sl, dataNode); *delete_count = 1; return 0; } @@ -266,7 +298,7 @@ int multi_skiplist_do_delete(MultiSkiplist *sl, void *data, dataCurrent = dataCurrent->next; (*delete_count)++; - fast_mblock_free_object(&sl->data_mblock, dataNode); + multi_skiplist_free_data_node(sl, dataNode); } fast_mblock_free_object(sl->mblocks + level_index, deleted); diff --git a/src/multi_skiplist.h b/src/multi_skiplist.h index 30249e5..3ad5930 100644 --- a/src/multi_skiplist.h +++ b/src/multi_skiplist.h @@ -17,6 +17,7 @@ #include "fast_mblock.h" typedef int (*multi_skiplist_compare_func)(const void *p1, const void *p2); +typedef void (*multi_skiplist_free_func)(void *ptr); typedef struct multi_skiplist_data { @@ -36,6 +37,7 @@ typedef struct multi_skiplist int level_count; int top_level_index; multi_skiplist_compare_func compare_func; + multi_skiplist_free_func free_func; struct fast_mblock_man data_mblock; //data node allocators struct fast_mblock_man *mblocks; //node allocators MultiSkiplistNode *top; //the top node @@ -56,12 +58,13 @@ extern "C" { #define SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE 128 -#define multi_skiplist_init(sl, level_count, compare_func) \ - multi_skiplist_init_ex(sl, level_count, compare_func, \ +#define multi_skiplist_init(sl, level_count, compare_func, free_func) \ + multi_skiplist_init_ex(sl, level_count, compare_func, free_func, \ SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE) int multi_skiplist_init_ex(MultiSkiplist *sl, const int level_count, multi_skiplist_compare_func compare_func, + multi_skiplist_free_func free_func, const int min_alloc_elements_once); void multi_skiplist_destroy(MultiSkiplist *sl); diff --git a/src/skiplist.c b/src/skiplist.c index 1377e67..bad230d 100644 --- a/src/skiplist.c +++ b/src/skiplist.c @@ -18,7 +18,8 @@ #include "skiplist.h" int skiplist_init_ex(Skiplist *sl, const int level_count, - skiplist_compare_func compare_func, const int min_alloc_elements_once) + skiplist_compare_func compare_func, skiplist_free_func free_func, + const int min_alloc_elements_once) { int bytes; int element_size; @@ -92,6 +93,7 @@ int skiplist_init_ex(Skiplist *sl, const int level_count, sl->level_count = level_count; sl->compare_func = compare_func; + sl->free_func = free_func; srand(time(NULL)); return 0; @@ -100,11 +102,22 @@ int skiplist_init_ex(Skiplist *sl, const int level_count, void skiplist_destroy(Skiplist *sl) { int i; + SkiplistNode *node; + SkiplistNode *deleted; if (sl->mblocks == NULL) { return; } + if (sl->free_func != NULL) { + node = sl->top->links[0]; + while (node != sl->tail) { + deleted = node; + node = node->links[0]; + sl->free_func(deleted->data); + } + } + for (i=0; ilevel_count; i++) { fast_mblock_destroy(sl->mblocks + i); } @@ -225,6 +238,9 @@ int skiplist_delete(Skiplist *sl, void *data) deleted->links[0]->prev = previous; + if (sl->free_func != NULL) { + sl->free_func(deleted->data); + } fast_mblock_free_object(sl->mblocks + level_index, deleted); return 0; } diff --git a/src/skiplist.h b/src/skiplist.h index 6ee80be..97bc942 100644 --- a/src/skiplist.h +++ b/src/skiplist.h @@ -17,6 +17,7 @@ #include "fast_mblock.h" typedef int (*skiplist_compare_func)(const void *p1, const void *p2); +typedef void (*skiplist_free_func)(void *ptr); typedef struct skiplist_node { @@ -30,6 +31,7 @@ typedef struct skiplist int level_count; int top_level_index; skiplist_compare_func compare_func; + skiplist_free_func free_func; struct fast_mblock_man *mblocks; //node allocators SkiplistNode *top; //the top node SkiplistNode *tail; //the tail node for interator @@ -46,12 +48,13 @@ extern "C" { #define SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE 128 -#define skiplist_init(sl, level_count, compare_func) \ - skiplist_init_ex(sl, level_count, compare_func, \ +#define skiplist_init(sl, level_count, compare_func, free_func) \ + skiplist_init_ex(sl, level_count, compare_func, free_func, \ SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE) int skiplist_init_ex(Skiplist *sl, const int level_count, - skiplist_compare_func compare_func, const int min_alloc_elements_once); + skiplist_compare_func compare_func, skiplist_free_func free_func, + const int min_alloc_elements_once); void skiplist_destroy(Skiplist *sl); diff --git a/src/tests/test_multi_skiplist.c b/src/tests/test_multi_skiplist.c index 64a8039..32a5bbc 100644 --- a/src/tests/test_multi_skiplist.c +++ b/src/tests/test_multi_skiplist.c @@ -10,14 +10,20 @@ #include "logger.h" #include "shared_func.h" -#define COUNT 12800 -#define LEVEL_COUNT 18 +#define COUNT 1000000 +#define LEVEL_COUNT 16 #define MIN_ALLOC_ONCE 32 #define LAST_INDEX (COUNT - 1) static int *numbers; static MultiSkiplist sl; static MultiSkiplistIterator iterator; +static int instance_count = 0; + +static void free_test_func(void *ptr) +{ + instance_count--; +} static int compare_func(const void *p1, const void *p2) { @@ -32,12 +38,16 @@ static int test_insert() int64_t end_time; void *value; + instance_count = 0; start_time = get_current_time_ms(); for (i=0; i