support free data callback

pull/5/head
yuqing 2015-12-29 16:55:29 +08:00
parent 9dc2f2901e
commit a1fc869430
6 changed files with 117 additions and 19 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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();

View File

@ -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();