uniq_skiplist support bidirection
parent
4e53bd3e2d
commit
759fd117d8
|
|
@ -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, "
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -43,7 +44,7 @@ typedef struct uniq_skiplist
|
||||||
UniqSkiplistFactory *factory;
|
UniqSkiplistFactory *factory;
|
||||||
int top_level_index;
|
int top_level_index;
|
||||||
int element_count;
|
int element_count;
|
||||||
UniqSkiplistNode *top; //the top node
|
UniqSkiplistNode *top; //the top node
|
||||||
} UniqSkiplist;
|
} UniqSkiplist;
|
||||||
|
|
||||||
typedef struct uniq_skiplist_iterator {
|
typedef struct uniq_skiplist_iterator {
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue