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;
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, "

View File

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

View File

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

View File

@ -43,8 +43,8 @@ void set_rand_numbers(const int multiple)
}
for (i=0; i<COUNT; i++) {
index1 = LAST_INDEX * (int64_t)rand() / (int64_t)RAND_MAX;
index2 = 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;
if (index1 == index2) {
continue;
}
@ -140,6 +140,7 @@ static void test_find_range()
int n_end;
int result;
int i;
int count;
int *value;
UniqSkiplistIterator iterator;
@ -157,15 +158,63 @@ static void test_find_range()
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
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_end = 0;
result = uniq_skiplist_find_range(sl, &n_start, &n_end, &iterator);
assert(result == ENOENT);
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);
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;
while ((value=(int *)uniq_skiplist_next(&iterator)) != NULL) {
@ -175,6 +224,23 @@ static void test_find_range()
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 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");

View File

@ -13,7 +13,6 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#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; i<level_count; i++) {
sl->top->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,

View File

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