diff --git a/src/common_blocked_queue.c b/src/common_blocked_queue.c index 5bd5105..92ad2c4 100644 --- a/src/common_blocked_queue.c +++ b/src/common_blocked_queue.c @@ -13,7 +13,7 @@ int common_blocked_queue_init_ex(struct common_blocked_queue *queue, { int result; - if ((result=init_pthread_lock(&(queue->lock))) != 0) + if ((result=init_pthread_lock(&queue->lock)) != 0) { logError("file: "__FILE__", line: %d, " "init_pthread_lock fail, errno: %d, error info: %s", @@ -21,8 +21,7 @@ int common_blocked_queue_init_ex(struct common_blocked_queue *queue, return result; } - result = pthread_cond_init(&(queue->cond), NULL); - if (result != 0) + if ((result=pthread_cond_init(&queue->cond, NULL)) != 0) { logError("file: "__FILE__", line: %d, " "pthread_cond_init fail, " diff --git a/src/shared_func.c b/src/shared_func.c index 5a011f3..be676cb 100644 --- a/src/shared_func.c +++ b/src/shared_func.c @@ -3092,3 +3092,13 @@ int fc_init_buffer(BufferInfo *buffer, const int buffer_size) buffer->length = 0; return 0; } + +void fc_free_buffer(BufferInfo *buffer) +{ + if (buffer->buff != NULL) + { + free(buffer->buff); + buffer->buff = NULL; + buffer->alloc_size = buffer->length = 0; + } +} diff --git a/src/shared_func.h b/src/shared_func.h index 06a823c..1ca0551 100644 --- a/src/shared_func.h +++ b/src/shared_func.h @@ -945,6 +945,13 @@ int fc_ceil_prime(const int n); */ int fc_init_buffer(BufferInfo *buffer, const int buffer_size); +/** free buffer + * parameters: + * buffer: the buffer to free + * return: none +*/ +void fc_free_buffer(BufferInfo *buffer); + #ifdef __cplusplus } #endif diff --git a/src/tests/test_uniq_skiplist.c b/src/tests/test_uniq_skiplist.c index 34f7dbd..74928f0 100644 --- a/src/tests/test_uniq_skiplist.c +++ b/src/tests/test_uniq_skiplist.c @@ -43,8 +43,8 @@ void set_rand_numbers(const int multiple) } for (i=0; itop) { + value = (int *)node->data; + printf("value: %d\n", *value); + node = (UniqSkiplistNode *)LEVEL0_DOUBLE_CHAIN_PREV_LINK(node); + } + } +} + int main(int argc, char *argv[]) { int result; @@ -189,7 +255,7 @@ int main(int argc, char *argv[]) fast_mblock_manager_init(); result = uniq_skiplist_init_ex(&factory, LEVEL_COUNT, compare_func, - free_test_func, 0, MIN_ALLOC_ONCE, 0); + free_test_func, 0, MIN_ALLOC_ONCE, 0, true); if (result != 0) { return result; } @@ -209,6 +275,8 @@ int main(int argc, char *argv[]) test_find_range(); + test_reverse_iterator(); + test_delete(); printf("\n"); diff --git a/src/uniq_skiplist.c b/src/uniq_skiplist.c index a4d37e1..b8f3594 100644 --- a/src/uniq_skiplist.c +++ b/src/uniq_skiplist.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "logger.h" #include "uniq_skiplist.h" @@ -46,12 +45,14 @@ static void init_best_element_counts() int uniq_skiplist_init_ex(UniqSkiplistFactory *factory, const int max_level_count, skiplist_compare_func compare_func, uniq_skiplist_free_func free_func, const int alloc_skiplist_once, - const int min_alloc_elements_once, const int delay_free_seconds) + const int min_alloc_elements_once, const int delay_free_seconds, + const bool bidirection) { char name[64]; int bytes; int element_size; int i; + int extra_links_count; int alloc_elements_once; int result; @@ -91,10 +92,11 @@ int uniq_skiplist_init_ex(UniqSkiplistFactory *factory, alloc_elements_once = 1024; } + extra_links_count = bidirection ? 1 : 0; for (i=max_level_count-1; i>=0; i--) { sprintf(name, "sl-level%02d", i); element_size = sizeof(UniqSkiplistNode) + - sizeof(UniqSkiplistNode *) * (i + 1); + sizeof(UniqSkiplistNode *) * (i + 1 + extra_links_count); if ((result=fast_mblock_init_ex1(factory->node_allocators + i, name, element_size, alloc_elements_once, NULL, NULL, false)) != 0) { @@ -120,6 +122,7 @@ int uniq_skiplist_init_ex(UniqSkiplistFactory *factory, } memset(factory->tail, 0, factory->node_allocators[0].info.element_size); + factory->bidirection = bidirection; factory->max_level_count = max_level_count; factory->compare_func = compare_func; factory->free_func = free_func; @@ -186,6 +189,10 @@ UniqSkiplist *uniq_skiplist_new(UniqSkiplistFactory *factory, return NULL; } memset(sl->top, 0, top_mblock->info.element_size); + sl->top->level_index = sl->top_level_index; + if (sl->factory->bidirection) { + LEVEL0_DOUBLE_CHAIN_TAIL(sl) = sl->top; + } for (i=0; itop->links[i] = sl->factory->tail; @@ -214,6 +221,7 @@ static int uniq_skiplist_grow(UniqSkiplist *sl) return ENOMEM; } memset(top, 0, top_mblock->info.element_size); + top->level_index = top_level_index; top->links[top_level_index] = sl->factory->tail; for (i=0; i<=sl->top_level_index; i++) { @@ -227,6 +235,11 @@ static int uniq_skiplist_grow(UniqSkiplist *sl) compile_barrier(); sl->top_level_index = top_level_index; + if (sl->factory->bidirection) { + LEVEL0_DOUBLE_CHAIN_TAIL(sl) = + LEVEL0_DOUBLE_CHAIN_PREV_LINK(old_top); + } + UNIQ_SKIPLIST_FREE_MBLOCK_OBJECT(sl, old_top_level_index, old_top); return 0; } @@ -332,6 +345,14 @@ int uniq_skiplist_insert(UniqSkiplist *sl, void *data) compile_barrier(); //thread safe for one write with many read model + if (sl->factory->bidirection) { + LEVEL0_DOUBLE_CHAIN_PREV_LINK(node) = tmp_previous[0]; + if (tmp_previous[0]->links[0] == sl->factory->tail) { + LEVEL0_DOUBLE_CHAIN_TAIL(sl) = node; + } else { + LEVEL0_DOUBLE_CHAIN_PREV_LINK(tmp_previous[0]->links[0]) = node; + } + } for (i=0; i<=level_index; i++) { node->links[i] = tmp_previous[i]->links[i]; tmp_previous[i]->links[i] = node; @@ -441,10 +462,19 @@ int uniq_skiplist_delete(UniqSkiplist *sl, void *data) previous = previous->links[i]; } - assert(previous->links[i] == deleted); previous->links[i] = previous->links[i]->links[i]; } + if (sl->factory->bidirection) { + if (deleted->links[0] == sl->factory->tail) { + LEVEL0_DOUBLE_CHAIN_TAIL(sl) = + LEVEL0_DOUBLE_CHAIN_PREV_LINK(deleted); + } else { + LEVEL0_DOUBLE_CHAIN_PREV_LINK(deleted->links[0]) = + LEVEL0_DOUBLE_CHAIN_PREV_LINK(deleted); + } + } + if (sl->factory->free_func != NULL) { sl->factory->free_func(deleted->data, sl->factory->delay_free_seconds); @@ -482,7 +512,7 @@ int uniq_skiplist_find_all(UniqSkiplist *sl, void *data, return 0; } -void *uniq_skiplist_find_ge(UniqSkiplist *sl, void *data) +UniqSkiplistNode *uniq_skiplist_find_ge_node(UniqSkiplist *sl, void *data) { UniqSkiplistNode *node; node = uniq_skiplist_get_first_larger_or_equal(sl, data); @@ -490,7 +520,7 @@ void *uniq_skiplist_find_ge(UniqSkiplist *sl, void *data) return NULL; } - return node->data; + return node; } int uniq_skiplist_find_range(UniqSkiplist *sl, void *start_data, diff --git a/src/uniq_skiplist.h b/src/uniq_skiplist.h index b402f03..c92a320 100644 --- a/src/uniq_skiplist.h +++ b/src/uniq_skiplist.h @@ -31,6 +31,7 @@ typedef struct uniq_skiplist_factory { int max_level_count; int delay_free_seconds; + bool bidirection; //if need reverse iteration for level 0 skiplist_compare_func compare_func; uniq_skiplist_free_func free_func; UniqSkiplistNode *tail; //the tail node for interator @@ -43,7 +44,7 @@ typedef struct uniq_skiplist UniqSkiplistFactory *factory; int top_level_index; int element_count; - UniqSkiplistNode *top; //the top node + UniqSkiplistNode *top; //the top node } UniqSkiplist; typedef struct uniq_skiplist_iterator { @@ -60,12 +61,13 @@ extern "C" { #define uniq_skiplist_init(factory, max_level_count, compare_func, free_func) \ uniq_skiplist_init_ex(factory, max_level_count, \ compare_func, free_func, 64 * 1024, \ - SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE, 0) + SKIPLIST_DEFAULT_MIN_ALLOC_ELEMENTS_ONCE, 0, false) int uniq_skiplist_init_ex(UniqSkiplistFactory *factory, const int max_level_count, skiplist_compare_func compare_func, uniq_skiplist_free_func free_func, const int alloc_skiplist_once, - const int min_alloc_elements_once, const int delay_free_seconds); + const int min_alloc_elements_once, const int delay_free_seconds, + const bool bidirection); void uniq_skiplist_destroy(UniqSkiplistFactory *factory); @@ -81,7 +83,19 @@ int uniq_skiplist_find_all(UniqSkiplist *sl, void *data, UniqSkiplistIterator *iterator); int uniq_skiplist_find_range(UniqSkiplist *sl, void *start_data, void *end_data, UniqSkiplistIterator *iterator); -void *uniq_skiplist_find_ge(UniqSkiplist *sl, void *data); + +UniqSkiplistNode *uniq_skiplist_find_ge_node(UniqSkiplist *sl, void *data); + +static inline void *uniq_skiplist_find_ge(UniqSkiplist *sl, void *data) +{ + UniqSkiplistNode *node; + node = uniq_skiplist_find_ge_node(sl, data); + if (node == NULL) { + return NULL; + } + + return node->data; +} static inline void uniq_skiplist_iterator(UniqSkiplist *sl, UniqSkiplistIterator *iterator) @@ -103,11 +117,38 @@ static inline void *uniq_skiplist_next(UniqSkiplistIterator *iterator) return data; } +static inline int uniq_skiplist_iterator_count(UniqSkiplistIterator *iterator) +{ + volatile UniqSkiplistNode *current; + int count; + + count = 0; + current = iterator->current; + while (current != iterator->tail) { + ++count; + current = current->links[0]; + } + + return count; +} + +static inline void *uniq_skiplist_get_first(UniqSkiplist *sl) +{ + if (sl->top->links[0] != sl->factory->tail) { + return sl->top->links[0]->data; + } else { + return NULL; + } +} + static inline bool uniq_skiplist_empty(UniqSkiplist *sl) { return sl->top->links[0] == sl->factory->tail; } +#define LEVEL0_DOUBLE_CHAIN_PREV_LINK(node) node->links[node->level_index + 1] +#define LEVEL0_DOUBLE_CHAIN_TAIL(sl) LEVEL0_DOUBLE_CHAIN_PREV_LINK(sl->top) + #ifdef __cplusplus } #endif