uniq_skiplist support bidirection

pull/37/head
YuQing 2020-04-21 08:50:22 +08:00
parent 4e53bd3e2d
commit 759fd117d8
6 changed files with 172 additions and 17 deletions

View File

@ -13,7 +13,7 @@ int common_blocked_queue_init_ex(struct common_blocked_queue *queue,
{ {
int result; int result;
if ((result=init_pthread_lock(&(queue->lock))) != 0) if ((result=init_pthread_lock(&queue->lock)) != 0)
{ {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"init_pthread_lock fail, errno: %d, error info: %s", "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; return result;
} }
result = pthread_cond_init(&(queue->cond), NULL); if ((result=pthread_cond_init(&queue->cond, NULL)) != 0)
if (result != 0)
{ {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"pthread_cond_init fail, " "pthread_cond_init fail, "

View File

@ -3092,3 +3092,13 @@ int fc_init_buffer(BufferInfo *buffer, const int buffer_size)
buffer->length = 0; buffer->length = 0;
return 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;
}
}

View File

@ -945,6 +945,13 @@ int fc_ceil_prime(const int n);
*/ */
int fc_init_buffer(BufferInfo *buffer, const int buffer_size); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -43,8 +43,8 @@ void set_rand_numbers(const int multiple)
} }
for (i=0; i<COUNT; i++) { for (i=0; i<COUNT; i++) {
index1 = LAST_INDEX * (int64_t)rand() / (int64_t)RAND_MAX; index1 = (LAST_INDEX * (int64_t)rand()) / (int64_t)RAND_MAX;
index2 = LAST_INDEX * (int64_t)rand() / (int64_t)RAND_MAX; index2 = (LAST_INDEX * (int64_t)rand()) / (int64_t)RAND_MAX;
if (index1 == index2) { if (index1 == index2) {
continue; continue;
} }
@ -140,6 +140,7 @@ static void test_find_range()
int n_end; int n_end;
int result; int result;
int i; int i;
int count;
int *value; int *value;
UniqSkiplistIterator iterator; UniqSkiplistIterator iterator;
@ -157,15 +158,63 @@ static void test_find_range()
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator); result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
assert(result == EINVAL); assert(result == EINVAL);
n_start = -100;
n_end = -1;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
assert(result == ENOENT);
n_start = -1; n_start = -1;
n_end = 0; n_end = 0;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator); result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
assert(result == ENOENT); assert(result == ENOENT);
n_start = 0; n_start = 0;
n_end = 10; n_end = 0;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
assert(result == ENOENT);
n_start = 2 * COUNT;
n_end = 2 * COUNT;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
assert(result == ENOENT);
count = uniq_skiplist_iterator_count(&iterator);
assert(count == 0);
n_start = 2 * COUNT;
n_end = 4 * COUNT;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
assert(result == ENOENT);
count = uniq_skiplist_iterator_count(&iterator);
assert(count == 0);
n_start = -100;
n_end = 2;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator); result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
assert(result == 0); assert(result == 0);
count = uniq_skiplist_iterator_count(&iterator);
if (n_end % 2 == 0) {
assert(count == n_end / 2);
} else {
assert(count == n_end / 2 + 1);
}
n_start = 0;
n_end = COUNT;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
count = uniq_skiplist_iterator_count(&iterator);
assert(count == (n_end - n_start) / 2);
n_start = COUNT;
n_end = 2 * COUNT;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
count = uniq_skiplist_iterator_count(&iterator);
assert(count == (n_end - n_start) / 2);
n_start = 100;
n_end = 152;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
count = uniq_skiplist_iterator_count(&iterator);
assert(count == (n_end - n_start) / 2);
i = 0; i = 0;
while ((value=(int *)uniq_skiplist_next(&iterator)) != NULL) { while ((value=(int *)uniq_skiplist_next(&iterator)) != NULL) {
@ -175,6 +224,23 @@ static void test_find_range()
printf("count: %d\n\n", i); printf("count: %d\n\n", i);
} }
static void test_reverse_iterator()
{
UniqSkiplistNode *node;
int v;
int *value;
v = 21;
node = uniq_skiplist_find_ge_node(sl, &v);
if (node != NULL) {
while (node != sl->top) {
value = (int *)node->data;
printf("value: %d\n", *value);
node = (UniqSkiplistNode *)LEVEL0_DOUBLE_CHAIN_PREV_LINK(node);
}
}
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int result; int result;
@ -189,7 +255,7 @@ int main(int argc, char *argv[])
fast_mblock_manager_init(); fast_mblock_manager_init();
result = uniq_skiplist_init_ex(&factory, LEVEL_COUNT, compare_func, 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) { if (result != 0) {
return result; return result;
} }
@ -209,6 +275,8 @@ int main(int argc, char *argv[])
test_find_range(); test_find_range();
test_reverse_iterator();
test_delete(); test_delete();
printf("\n"); printf("\n");

View File

@ -13,7 +13,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <assert.h>
#include "logger.h" #include "logger.h"
#include "uniq_skiplist.h" #include "uniq_skiplist.h"
@ -46,12 +45,14 @@ static void init_best_element_counts()
int uniq_skiplist_init_ex(UniqSkiplistFactory *factory, int uniq_skiplist_init_ex(UniqSkiplistFactory *factory,
const int max_level_count, skiplist_compare_func compare_func, const int max_level_count, skiplist_compare_func compare_func,
uniq_skiplist_free_func free_func, const int alloc_skiplist_once, 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]; char name[64];
int bytes; int bytes;
int element_size; int element_size;
int i; int i;
int extra_links_count;
int alloc_elements_once; int alloc_elements_once;
int result; int result;
@ -91,10 +92,11 @@ int uniq_skiplist_init_ex(UniqSkiplistFactory *factory,
alloc_elements_once = 1024; alloc_elements_once = 1024;
} }
extra_links_count = bidirection ? 1 : 0;
for (i=max_level_count-1; i>=0; i--) { for (i=max_level_count-1; i>=0; i--) {
sprintf(name, "sl-level%02d", i); sprintf(name, "sl-level%02d", i);
element_size = sizeof(UniqSkiplistNode) + 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, if ((result=fast_mblock_init_ex1(factory->node_allocators + i,
name, element_size, alloc_elements_once, NULL, NULL, false)) != 0) 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); memset(factory->tail, 0, factory->node_allocators[0].info.element_size);
factory->bidirection = bidirection;
factory->max_level_count = max_level_count; factory->max_level_count = max_level_count;
factory->compare_func = compare_func; factory->compare_func = compare_func;
factory->free_func = free_func; factory->free_func = free_func;
@ -186,6 +189,10 @@ UniqSkiplist *uniq_skiplist_new(UniqSkiplistFactory *factory,
return NULL; return NULL;
} }
memset(sl->top, 0, top_mblock->info.element_size); 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; i<level_count; i++) { for (i=0; i<level_count; i++) {
sl->top->links[i] = sl->factory->tail; sl->top->links[i] = sl->factory->tail;
@ -214,6 +221,7 @@ static int uniq_skiplist_grow(UniqSkiplist *sl)
return ENOMEM; return ENOMEM;
} }
memset(top, 0, top_mblock->info.element_size); memset(top, 0, top_mblock->info.element_size);
top->level_index = top_level_index;
top->links[top_level_index] = sl->factory->tail; top->links[top_level_index] = sl->factory->tail;
for (i=0; i<=sl->top_level_index; i++) { for (i=0; i<=sl->top_level_index; i++) {
@ -227,6 +235,11 @@ static int uniq_skiplist_grow(UniqSkiplist *sl)
compile_barrier(); compile_barrier();
sl->top_level_index = top_level_index; 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); UNIQ_SKIPLIST_FREE_MBLOCK_OBJECT(sl, old_top_level_index, old_top);
return 0; return 0;
} }
@ -332,6 +345,14 @@ int uniq_skiplist_insert(UniqSkiplist *sl, void *data)
compile_barrier(); compile_barrier();
//thread safe for one write with many read model //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++) { for (i=0; i<=level_index; i++) {
node->links[i] = tmp_previous[i]->links[i]; node->links[i] = tmp_previous[i]->links[i];
tmp_previous[i]->links[i] = node; tmp_previous[i]->links[i] = node;
@ -441,10 +462,19 @@ int uniq_skiplist_delete(UniqSkiplist *sl, void *data)
previous = previous->links[i]; previous = previous->links[i];
} }
assert(previous->links[i] == deleted);
previous->links[i] = previous->links[i]->links[i]; 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) { if (sl->factory->free_func != NULL) {
sl->factory->free_func(deleted->data, sl->factory->free_func(deleted->data,
sl->factory->delay_free_seconds); sl->factory->delay_free_seconds);
@ -482,7 +512,7 @@ int uniq_skiplist_find_all(UniqSkiplist *sl, void *data,
return 0; return 0;
} }
void *uniq_skiplist_find_ge(UniqSkiplist *sl, void *data) UniqSkiplistNode *uniq_skiplist_find_ge_node(UniqSkiplist *sl, void *data)
{ {
UniqSkiplistNode *node; UniqSkiplistNode *node;
node = uniq_skiplist_get_first_larger_or_equal(sl, data); 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 NULL;
} }
return node->data; return node;
} }
int uniq_skiplist_find_range(UniqSkiplist *sl, void *start_data, int uniq_skiplist_find_range(UniqSkiplist *sl, void *start_data,

View File

@ -31,6 +31,7 @@ typedef struct uniq_skiplist_factory
{ {
int max_level_count; int max_level_count;
int delay_free_seconds; int delay_free_seconds;
bool bidirection; //if need reverse iteration for level 0
skiplist_compare_func compare_func; skiplist_compare_func compare_func;
uniq_skiplist_free_func free_func; uniq_skiplist_free_func free_func;
UniqSkiplistNode *tail; //the tail node for interator UniqSkiplistNode *tail; //the tail node for interator
@ -60,12 +61,13 @@ extern "C" {
#define uniq_skiplist_init(factory, max_level_count, compare_func, free_func) \ #define uniq_skiplist_init(factory, max_level_count, compare_func, free_func) \
uniq_skiplist_init_ex(factory, max_level_count, \ uniq_skiplist_init_ex(factory, max_level_count, \
compare_func, free_func, 64 * 1024, \ 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, int uniq_skiplist_init_ex(UniqSkiplistFactory *factory,
const int max_level_count, skiplist_compare_func compare_func, const int max_level_count, skiplist_compare_func compare_func,
uniq_skiplist_free_func free_func, const int alloc_skiplist_once, 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); void uniq_skiplist_destroy(UniqSkiplistFactory *factory);
@ -81,7 +83,19 @@ int uniq_skiplist_find_all(UniqSkiplist *sl, void *data,
UniqSkiplistIterator *iterator); UniqSkiplistIterator *iterator);
int uniq_skiplist_find_range(UniqSkiplist *sl, void *start_data, int uniq_skiplist_find_range(UniqSkiplist *sl, void *start_data,
void *end_data, UniqSkiplistIterator *iterator); 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, static inline void uniq_skiplist_iterator(UniqSkiplist *sl,
UniqSkiplistIterator *iterator) UniqSkiplistIterator *iterator)
@ -103,11 +117,38 @@ static inline void *uniq_skiplist_next(UniqSkiplistIterator *iterator)
return data; 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) static inline bool uniq_skiplist_empty(UniqSkiplist *sl)
{ {
return sl->top->links[0] == sl->factory->tail; 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 #ifdef __cplusplus
} }
#endif #endif