From 66e2db7b6f616e1dbdd98e0dbccbea5ad705fb3d Mon Sep 17 00:00:00 2001 From: yuqing Date: Wed, 30 Dec 2015 11:16:06 +0800 Subject: [PATCH] add skiplist wrapper --- HISTORY | 2 +- src/Makefile.in | 7 +- src/{skiplist.c => flat_skiplist.c} | 64 ++++++------- src/flat_skiplist.h | 87 +++++++++++++++++ src/multi_skiplist.c | 4 +- src/multi_skiplist.h | 14 +-- src/skiplist.h | 140 ++++++++++++++++++++-------- src/skiplist_common.h | 32 +++++++ src/tests/test_skiplist.c | 15 ++- 9 files changed, 276 insertions(+), 89 deletions(-) rename src/{skiplist.c => flat_skiplist.c} (78%) create mode 100644 src/flat_skiplist.h create mode 100644 src/skiplist_common.h diff --git a/HISTORY b/HISTORY index 9c7377f..a9204da 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,5 @@ -Version 1.24 2015-12-29 +Version 1.24 2015-12-30 * php extension compiled on PHP 7 * add skiplist which support stable sort * make.sh: use sed to replace perl diff --git a/src/Makefile.in b/src/Makefile.in index fa4d65b..b705734 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -10,7 +10,7 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.lo \ avl_tree.lo ioevent.lo ioevent_loop.lo fast_task_queue.lo \ fast_timer.lo process_ctrl.lo fast_mblock.lo \ connection_pool.lo fast_mpool.lo fast_allocator.lo \ - fast_buffer.lo skiplist.lo multi_skiplist.lo + fast_buffer.lo multi_skiplist.lo flat_skiplist.lo FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \ logger.o sockopt.o base64.o sched_thread.o \ @@ -18,7 +18,7 @@ FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \ avl_tree.o ioevent.o ioevent_loop.o fast_task_queue.o \ fast_timer.o process_ctrl.o fast_mblock.o \ connection_pool.o fast_mpool.o fast_allocator.o \ - fast_buffer.o skiplist.o multi_skiplist.o + fast_buffer.o multi_skiplist.o flat_skiplist.o HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \ shared_func.h pthread_func.h ini_file_reader.h _os_define.h \ @@ -26,7 +26,8 @@ HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \ avl_tree.h ioevent.h ioevent_loop.h fast_task_queue.h \ fast_timer.h process_ctrl.h fast_mblock.h \ connection_pool.h fast_mpool.h fast_allocator.h \ - fast_buffer.h skiplist.h multi_skiplist.h + fast_buffer.h skiplist.h multi_skiplist.h flat_skiplist.h \ + skiplist_common.h ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS) diff --git a/src/skiplist.c b/src/flat_skiplist.c similarity index 78% rename from src/skiplist.c rename to src/flat_skiplist.c index bad230d..ae0ff2b 100644 --- a/src/skiplist.c +++ b/src/flat_skiplist.c @@ -6,7 +6,7 @@ * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. **/ -//skiplist.c +//flat_skiplist.c #include #include @@ -15,9 +15,9 @@ #include #include #include "logger.h" -#include "skiplist.h" +#include "flat_skiplist.h" -int skiplist_init_ex(Skiplist *sl, const int level_count, +int flat_skiplist_init_ex(FlatSkiplist *sl, const int level_count, skiplist_compare_func compare_func, skiplist_free_func free_func, const int min_alloc_elements_once) { @@ -61,7 +61,7 @@ int skiplist_init_ex(Skiplist *sl, const int level_count, } for (i=level_count-1; i>=0; i--) { - element_size = sizeof(SkiplistNode) + sizeof(SkiplistNode *) * (i + 1); + element_size = sizeof(FlatSkiplistNode) + sizeof(FlatSkiplistNode *) * (i + 1); if ((result=fast_mblock_init_ex(sl->mblocks + i, element_size, alloc_elements_once, NULL, false)) != 0) { @@ -74,13 +74,13 @@ int skiplist_init_ex(Skiplist *sl, const int level_count, sl->top_level_index = level_count - 1; top_mblock = sl->mblocks + sl->top_level_index; - sl->top = (SkiplistNode *)fast_mblock_alloc_object(top_mblock); + sl->top = (FlatSkiplistNode *)fast_mblock_alloc_object(top_mblock); if (sl->top == NULL) { return ENOMEM; } memset(sl->top, 0, top_mblock->info.element_size); - sl->tail = (SkiplistNode *)fast_mblock_alloc_object(sl->mblocks + 0); + sl->tail = (FlatSkiplistNode *)fast_mblock_alloc_object(sl->mblocks + 0); if (sl->tail == NULL) { return ENOMEM; } @@ -99,11 +99,11 @@ int skiplist_init_ex(Skiplist *sl, const int level_count, return 0; } -void skiplist_destroy(Skiplist *sl) +void flat_skiplist_destroy(FlatSkiplist *sl) { int i; - SkiplistNode *node; - SkiplistNode *deleted; + FlatSkiplistNode *node; + FlatSkiplistNode *deleted; if (sl->mblocks == NULL) { return; @@ -126,7 +126,7 @@ void skiplist_destroy(Skiplist *sl) sl->mblocks = NULL; } -static inline int skiplist_get_level_index(Skiplist *sl) +static inline int flat_skiplist_get_level_index(FlatSkiplist *sl) { int i; @@ -139,16 +139,16 @@ static inline int skiplist_get_level_index(Skiplist *sl) return i; } -int skiplist_insert(Skiplist *sl, void *data) +int flat_skiplist_insert(FlatSkiplist *sl, void *data) { int i; int level_index; - SkiplistNode *node; - SkiplistNode *previous; - SkiplistNode *current = NULL; + FlatSkiplistNode *node; + FlatSkiplistNode *previous; + FlatSkiplistNode *current = NULL; - level_index = skiplist_get_level_index(sl); - node = (SkiplistNode *)fast_mblock_alloc_object(sl->mblocks + level_index); + level_index = flat_skiplist_get_level_index(sl); + node = (FlatSkiplistNode *)fast_mblock_alloc_object(sl->mblocks + level_index); if (node == NULL) { return ENOMEM; } @@ -182,13 +182,13 @@ int skiplist_insert(Skiplist *sl, void *data) return 0; } -static SkiplistNode *skiplist_get_previous(Skiplist *sl, void *data, +static FlatSkiplistNode *flat_skiplist_get_previous(FlatSkiplist *sl, void *data, int *level_index) { int i; int cmp; - SkiplistNode *previous; - SkiplistNode *found; + FlatSkiplistNode *previous; + FlatSkiplistNode *found; found = NULL; previous = sl->top; @@ -212,14 +212,14 @@ DONE: return found; } -int skiplist_delete(Skiplist *sl, void *data) +int flat_skiplist_delete(FlatSkiplist *sl, void *data) { int i; int level_index; - SkiplistNode *previous; - SkiplistNode *deleted; + FlatSkiplistNode *previous; + FlatSkiplistNode *deleted; - previous = skiplist_get_previous(sl, data, &level_index); + previous = flat_skiplist_get_previous(sl, data, &level_index); if (previous == NULL) { return ENOENT; } @@ -245,32 +245,32 @@ int skiplist_delete(Skiplist *sl, void *data) return 0; } -int skiplist_delete_all(Skiplist *sl, void *data, int *delete_count) +int flat_skiplist_delete_all(FlatSkiplist *sl, void *data, int *delete_count) { *delete_count = 0; - while (skiplist_delete(sl, data) == 0) { + while (flat_skiplist_delete(sl, data) == 0) { (*delete_count)++; } return *delete_count > 0 ? 0 : ENOENT; } -void *skiplist_find(Skiplist *sl, void *data) +void *flat_skiplist_find(FlatSkiplist *sl, void *data) { int level_index; - SkiplistNode *previous; + FlatSkiplistNode *previous; - previous = skiplist_get_previous(sl, data, &level_index); + previous = flat_skiplist_get_previous(sl, data, &level_index); return (previous != NULL) ? previous->links[level_index]->data : NULL; } -int skiplist_find_all(Skiplist *sl, void *data, SkiplistIterator *iterator) +int flat_skiplist_find_all(FlatSkiplist *sl, void *data, FlatSkiplistIterator *iterator) { int level_index; - SkiplistNode *previous; - SkiplistNode *last; + FlatSkiplistNode *previous; + FlatSkiplistNode *last; - previous = skiplist_get_previous(sl, data, &level_index); + previous = flat_skiplist_get_previous(sl, data, &level_index); if (previous == NULL) { iterator->top = sl->top; iterator->current = sl->top; diff --git a/src/flat_skiplist.h b/src/flat_skiplist.h new file mode 100644 index 0000000..86e3a64 --- /dev/null +++ b/src/flat_skiplist.h @@ -0,0 +1,87 @@ +/** +* Copyright (C) 2015 Happy Fish / YuQing +* +* libfastcommon may be copied only under the terms of the GNU General +* Public License V3, which may be found in the FastDFS source kit. +* Please visit the FastDFS Home Page http://www.csource.org/ for more detail. +**/ + +//flat_skiplist.h, support stable sort :) +#ifndef _FLAT_SKIPLIST_H +#define _FLAT_SKIPLIST_H + +#include +#include +#include +#include "common_define.h" +#include "skiplist_common.h" +#include "fast_mblock.h" + +typedef struct flat_skiplist_node +{ + void *data; + struct flat_skiplist_node *prev; //for stable sort + struct flat_skiplist_node *links[0]; +} FlatSkiplistNode; + +typedef struct flat_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 + FlatSkiplistNode *top; //the top node + FlatSkiplistNode *tail; //the tail node for interator +} FlatSkiplist; + +typedef struct flat_skiplist_iterator { + FlatSkiplistNode *top; + FlatSkiplistNode *current; +} FlatSkiplistIterator; + +#ifdef __cplusplus +extern "C" { +#endif + +#define flat_skiplist_init(sl, level_count, compare_func, free_func) \ + flat_skiplist_init_ex(sl, level_count, compare_func, free_func, \ + SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE) + +int flat_skiplist_init_ex(FlatSkiplist *sl, const int level_count, + skiplist_compare_func compare_func, skiplist_free_func free_func, + const int min_alloc_elements_once); + +void flat_skiplist_destroy(FlatSkiplist *sl); + +int flat_skiplist_insert(FlatSkiplist *sl, void *data); +int flat_skiplist_delete(FlatSkiplist *sl, void *data); +int flat_skiplist_delete_all(FlatSkiplist *sl, void *data, int *delete_count); +void *flat_skiplist_find(FlatSkiplist *sl, void *data); +int flat_skiplist_find_all(FlatSkiplist *sl, void *data, FlatSkiplistIterator *iterator); + +static inline void flat_skiplist_iterator(FlatSkiplist *sl, FlatSkiplistIterator *iterator) +{ + iterator->top = sl->top; + iterator->current = sl->tail->prev; +} + +static inline void *flat_skiplist_next(FlatSkiplistIterator *iterator) +{ + void *data; + + if (iterator->current == iterator->top) { + return NULL; + } + + data = iterator->current->data; + iterator->current = iterator->current->prev; + return data; +} + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/multi_skiplist.c b/src/multi_skiplist.c index 611f1a6..1432cb4 100644 --- a/src/multi_skiplist.c +++ b/src/multi_skiplist.c @@ -18,8 +18,8 @@ #include "multi_skiplist.h" int multi_skiplist_init_ex(MultiSkiplist *sl, const int level_count, - multi_skiplist_compare_func compare_func, - multi_skiplist_free_func free_func, + skiplist_compare_func compare_func, + skiplist_free_func free_func, const int min_alloc_elements_once) { int bytes; diff --git a/src/multi_skiplist.h b/src/multi_skiplist.h index 3ad5930..0414fcc 100644 --- a/src/multi_skiplist.h +++ b/src/multi_skiplist.h @@ -15,9 +15,7 @@ #include #include "common_define.h" #include "fast_mblock.h" - -typedef int (*multi_skiplist_compare_func)(const void *p1, const void *p2); -typedef void (*multi_skiplist_free_func)(void *ptr); +#include "skiplist_common.h" typedef struct multi_skiplist_data { @@ -36,8 +34,8 @@ typedef struct multi_skiplist { int level_count; int top_level_index; - multi_skiplist_compare_func compare_func; - multi_skiplist_free_func free_func; + skiplist_compare_func compare_func; + 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,15 +54,13 @@ typedef struct multi_skiplist_iterator { extern "C" { #endif -#define SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE 128 - #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, + skiplist_compare_func compare_func, + skiplist_free_func free_func, const int min_alloc_elements_once); void multi_skiplist_destroy(MultiSkiplist *sl); diff --git a/src/skiplist.h b/src/skiplist.h index 97bc942..15e3bbd 100644 --- a/src/skiplist.h +++ b/src/skiplist.h @@ -14,73 +14,133 @@ #include #include #include "common_define.h" -#include "fast_mblock.h" +#include "skiplist_common.h" +#include "flat_skiplist.h" +#include "multi_skiplist.h" -typedef int (*skiplist_compare_func)(const void *p1, const void *p2); -typedef void (*skiplist_free_func)(void *ptr); - -typedef struct skiplist_node -{ - void *data; - struct skiplist_node *prev; //for stable sort - struct skiplist_node *links[0]; -} SkiplistNode; +#define SKIPLIST_TYPE_FLAT 0 +#define SKIPLIST_TYPE_MULTI 1 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 + int type; + union { + FlatSkiplist flat; + MultiSkiplist multi; + } u; } Skiplist; typedef struct skiplist_iterator { - SkiplistNode *top; - SkiplistNode *current; + int type; + union { + FlatSkiplistIterator flat; + MultiSkiplistIterator multi; + } u; } SkiplistIterator; #ifdef __cplusplus extern "C" { #endif -#define SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE 128 - #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) + SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE, SKIPLIST_TYPE_FLAT) -int skiplist_init_ex(Skiplist *sl, const int level_count, +static inline int skiplist_init_ex(Skiplist *sl, const int level_count, skiplist_compare_func compare_func, skiplist_free_func free_func, - const int min_alloc_elements_once); + const int min_alloc_elements_once, const int type) +{ + sl->type = type; + if (type == SKIPLIST_TYPE_FLAT) { + return flat_skiplist_init_ex(&sl->u.flat, level_count, + compare_func, free_func, min_alloc_elements_once); + } + else { + return multi_skiplist_init_ex(&sl->u.multi, level_count, + compare_func, free_func, min_alloc_elements_once); + } +} -void skiplist_destroy(Skiplist *sl); +static inline void skiplist_destroy(Skiplist *sl) +{ + if (sl->type == SKIPLIST_TYPE_FLAT) { + flat_skiplist_destroy(&sl->u.flat); + } + else { + multi_skiplist_destroy(&sl->u.multi); + } +} -int skiplist_insert(Skiplist *sl, void *data); -int skiplist_delete(Skiplist *sl, void *data); -int skiplist_delete_all(Skiplist *sl, void *data, int *delete_count); -void *skiplist_find(Skiplist *sl, void *data); -int skiplist_find_all(Skiplist *sl, void *data, SkiplistIterator *iterator); +static inline int skiplist_insert(Skiplist *sl, void *data) +{ + if (sl->type == SKIPLIST_TYPE_FLAT) { + return flat_skiplist_insert(&sl->u.flat, data); + } + else { + return multi_skiplist_insert(&sl->u.multi, data); + } +} + +static inline int skiplist_delete(Skiplist *sl, void *data) +{ + if (sl->type == SKIPLIST_TYPE_FLAT) { + return flat_skiplist_delete(&sl->u.flat, data); + } + else { + return multi_skiplist_delete(&sl->u.multi, data); + } +} + +static inline int skiplist_delete_all(Skiplist *sl, void *data, int *delete_count) +{ + if (sl->type == SKIPLIST_TYPE_FLAT) { + return flat_skiplist_delete_all(&sl->u.flat, data, delete_count); + } + else { + return multi_skiplist_delete_all(&sl->u.multi, data, delete_count); + } +} + +static inline void *skiplist_find(Skiplist *sl, void *data) +{ + if (sl->type == SKIPLIST_TYPE_FLAT) { + return flat_skiplist_find(&sl->u.flat, data); + } + else { + return multi_skiplist_find(&sl->u.multi, data); + } +} + +static inline int skiplist_find_all(Skiplist *sl, void *data, SkiplistIterator *iterator) +{ + iterator->type = sl->type; + if (sl->type == SKIPLIST_TYPE_FLAT) { + return flat_skiplist_find_all(&sl->u.flat, data, &iterator->u.flat); + } + else { + return multi_skiplist_find_all(&sl->u.multi, data, &iterator->u.multi); + } +} static inline void skiplist_iterator(Skiplist *sl, SkiplistIterator *iterator) { - iterator->top = sl->top; - iterator->current = sl->tail->prev; + iterator->type = sl->type; + if (sl->type == SKIPLIST_TYPE_FLAT) { + return flat_skiplist_iterator(&sl->u.flat, &iterator->u.flat); + } + else { + return multi_skiplist_iterator(&sl->u.multi, &iterator->u.multi); + } } static inline void *skiplist_next(SkiplistIterator *iterator) { - void *data; - - if (iterator->current == iterator->top) { - return NULL; + if (iterator->type == SKIPLIST_TYPE_FLAT) { + return flat_skiplist_next(&iterator->u.flat); + } + else { + return multi_skiplist_next(&iterator->u.multi); } - - data = iterator->current->data; - iterator->current = iterator->current->prev; - return data; } #ifdef __cplusplus diff --git a/src/skiplist_common.h b/src/skiplist_common.h new file mode 100644 index 0000000..2a53aa3 --- /dev/null +++ b/src/skiplist_common.h @@ -0,0 +1,32 @@ +/** +* Copyright (C) 2015 Happy Fish / YuQing +* +* libfastcommon may be copied only under the terms of the GNU General +* Public License V3, which may be found in the FastDFS source kit. +* Please visit the FastDFS Home Page http://www.csource.org/ for more detail. +**/ + +//skiplist_common.h +#ifndef _SKIPLIST_COMMON_H +#define _SKIPLIST_COMMON_H + +#include +#include +#include +#include "common_define.h" + +#define SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE 128 + +typedef int (*skiplist_compare_func)(const void *p1, const void *p2); +typedef void (*skiplist_free_func)(void *ptr); + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/tests/test_skiplist.c b/src/tests/test_skiplist.c index 412e9da..1620a6f 100644 --- a/src/tests/test_skiplist.c +++ b/src/tests/test_skiplist.c @@ -18,6 +18,7 @@ static int *numbers; static Skiplist sl; static SkiplistIterator iterator; +static int skiplist_type = SKIPLIST_TYPE_FLAT; static int instance_count = 0; @@ -135,7 +136,7 @@ static int test_stable_sort() instance_count = 0; result = skiplist_init_ex(&sl, 12, compare_record, - free_test_func, 128); + free_test_func, 128, skiplist_type); if (result != 0) { return result; } @@ -222,7 +223,17 @@ int main(int argc, char *argv[]) int index2; int result; + log_init(); + + if (argc > 1) { + if (strcasecmp(argv[1], "multi") == 0 || strcmp(argv[1], "1") == 0) { + skiplist_type = SKIPLIST_TYPE_MULTI; + } + } + printf("skiplist type: %s\n", + skiplist_type == SKIPLIST_TYPE_FLAT ? "flat" : "multi"); + numbers = (int *)malloc(sizeof(int) * COUNT); srand(time(NULL)); for (i=0; i