support free data callback
parent
9dc2f2901e
commit
a1fc869430
|
|
@ -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; i<sl->level_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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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; i<sl->level_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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<COUNT; i++) {
|
||||
if ((result=multi_skiplist_insert(&sl, numbers + i)) != 0) {
|
||||
return result;
|
||||
}
|
||||
instance_count++;
|
||||
}
|
||||
assert(instance_count == COUNT);
|
||||
|
||||
end_time = get_current_time_ms();
|
||||
printf("insert time used: %"PRId64" ms\n", end_time - start_time);
|
||||
|
||||
|
|
@ -74,6 +84,8 @@ static void test_delete()
|
|||
for (i=0; i<COUNT; i++) {
|
||||
assert(multi_skiplist_delete(&sl, numbers + i) == 0);
|
||||
}
|
||||
assert(instance_count == 0);
|
||||
|
||||
end_time = get_current_time_ms();
|
||||
printf("delete time used: %"PRId64" ms\n", end_time - start_time);
|
||||
|
||||
|
|
@ -120,7 +132,9 @@ static int test_stable_sort()
|
|||
Record target;
|
||||
void *value;
|
||||
|
||||
result = multi_skiplist_init_ex(&sl, 12, compare_record, 128);
|
||||
instance_count = 0;
|
||||
result = multi_skiplist_init_ex(&sl, 12, compare_record,
|
||||
free_test_func, 128);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
|
@ -142,7 +156,9 @@ static int test_stable_sort()
|
|||
if ((result=multi_skiplist_insert(&sl, records + i)) != 0) {
|
||||
return result;
|
||||
}
|
||||
instance_count++;
|
||||
}
|
||||
assert(instance_count == RECORDS);
|
||||
|
||||
for (i=0; i<RECORDS; i++) {
|
||||
value = multi_skiplist_find(&sl, records + i);
|
||||
|
|
@ -182,6 +198,7 @@ static int test_stable_sort()
|
|||
(result != 0 && delete_count == 0));
|
||||
}
|
||||
assert(total_delete_count == RECORDS);
|
||||
assert(instance_count == 0);
|
||||
|
||||
i = 0;
|
||||
multi_skiplist_iterator(&sl, &iterator);
|
||||
|
|
@ -191,6 +208,8 @@ static int test_stable_sort()
|
|||
assert(i == 0);
|
||||
|
||||
multi_skiplist_destroy(&sl);
|
||||
assert(instance_count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +240,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
fast_mblock_manager_init();
|
||||
result = multi_skiplist_init_ex(&sl, LEVEL_COUNT, compare_func, MIN_ALLOC_ONCE);
|
||||
result = multi_skiplist_init_ex(&sl, LEVEL_COUNT, compare_func,
|
||||
free_test_func, MIN_ALLOC_ONCE);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
|
@ -237,9 +257,13 @@ int main(int argc, char *argv[])
|
|||
test_insert();
|
||||
printf("\n");
|
||||
|
||||
/*
|
||||
test_delete();
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
multi_skiplist_destroy(&sl);
|
||||
assert(instance_count == 0);
|
||||
|
||||
test_stable_sort();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
#include "logger.h"
|
||||
#include "shared_func.h"
|
||||
|
||||
#define COUNT 100000
|
||||
#define LEVEL_COUNT 18
|
||||
#define COUNT 1000000
|
||||
#define LEVEL_COUNT 16
|
||||
#define MIN_ALLOC_ONCE 32
|
||||
#define LAST_INDEX (COUNT - 1)
|
||||
|
||||
|
|
@ -19,6 +19,13 @@ static int *numbers;
|
|||
static Skiplist sl;
|
||||
static SkiplistIterator 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)
|
||||
{
|
||||
return *((int *)p1) - *((int *)p2);
|
||||
|
|
@ -32,12 +39,16 @@ static int test_insert()
|
|||
int64_t end_time;
|
||||
void *value;
|
||||
|
||||
instance_count = 0;
|
||||
start_time = get_current_time_ms();
|
||||
for (i=0; i<COUNT; i++) {
|
||||
if ((result=skiplist_insert(&sl, numbers + i)) != 0) {
|
||||
return result;
|
||||
}
|
||||
instance_count++;
|
||||
}
|
||||
assert(instance_count == COUNT);
|
||||
|
||||
end_time = get_current_time_ms();
|
||||
printf("insert time used: %"PRId64" ms\n", end_time - start_time);
|
||||
|
||||
|
|
@ -74,6 +85,8 @@ static void test_delete()
|
|||
for (i=0; i<COUNT; i++) {
|
||||
assert(skiplist_delete(&sl, numbers + i) == 0);
|
||||
}
|
||||
assert(instance_count == 0);
|
||||
|
||||
end_time = get_current_time_ms();
|
||||
printf("delete time used: %"PRId64" ms\n", end_time - start_time);
|
||||
|
||||
|
|
@ -120,7 +133,9 @@ static int test_stable_sort()
|
|||
Record target;
|
||||
void *value;
|
||||
|
||||
result = skiplist_init_ex(&sl, 12, compare_record, 128);
|
||||
instance_count = 0;
|
||||
result = skiplist_init_ex(&sl, 12, compare_record,
|
||||
free_test_func, 128);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
|
@ -142,7 +157,9 @@ static int test_stable_sort()
|
|||
if ((result=skiplist_insert(&sl, records + i)) != 0) {
|
||||
return result;
|
||||
}
|
||||
instance_count++;
|
||||
}
|
||||
assert(instance_count == RECORDS);
|
||||
|
||||
for (i=0; i<RECORDS; i++) {
|
||||
value = skiplist_find(&sl, records + i);
|
||||
|
|
@ -182,6 +199,7 @@ static int test_stable_sort()
|
|||
(result != 0 && delete_count == 0));
|
||||
}
|
||||
assert(total_delete_count == RECORDS);
|
||||
assert(instance_count == 0);
|
||||
|
||||
i = 0;
|
||||
skiplist_iterator(&sl, &iterator);
|
||||
|
|
@ -191,6 +209,8 @@ static int test_stable_sort()
|
|||
assert(i == 0);
|
||||
|
||||
skiplist_destroy(&sl);
|
||||
assert(instance_count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +241,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
fast_mblock_manager_init();
|
||||
result = skiplist_init_ex(&sl, LEVEL_COUNT, compare_func, MIN_ALLOC_ONCE);
|
||||
result = skiplist_init_ex(&sl, LEVEL_COUNT, compare_func,
|
||||
free_test_func, MIN_ALLOC_ONCE);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
|
@ -233,14 +254,13 @@ int main(int argc, char *argv[])
|
|||
|
||||
test_delete();
|
||||
printf("\n");
|
||||
assert(instance_count == 0);
|
||||
|
||||
test_insert();
|
||||
printf("\n");
|
||||
|
||||
test_delete();
|
||||
printf("\n");
|
||||
skiplist_destroy(&sl);
|
||||
fast_mblock_manager_stat_print(false);
|
||||
assert(instance_count == 0);
|
||||
|
||||
test_stable_sort();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue