fast_mblock stats refine
parent
590aa8d3a0
commit
427818d005
2
HISTORY
2
HISTORY
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
Version 1.44 2020-03-28
|
||||
Version 1.44 2020-03-29
|
||||
* add test file src/tests/test_pthread_lock.c
|
||||
* add uniq_skiplist.[hc]
|
||||
* add function split_string_ex
|
||||
|
|
|
|||
|
|
@ -116,6 +116,8 @@ extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
|
|||
#define ENONET 64 /* Machine is not on the network */
|
||||
#endif
|
||||
|
||||
#define compile_barrier() __asm__ __volatile__("" : : : "memory")
|
||||
|
||||
#define IS_UPPER_HEX(ch) ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F'))
|
||||
#define IS_HEX_CHAR(ch) (IS_UPPER_HEX(ch) || (ch >= 'a' && ch <= 'f'))
|
||||
#define FC_IS_DIGITAL(ch) (ch >= '0' && ch <= '9')
|
||||
|
|
|
|||
|
|
@ -108,13 +108,15 @@ static int allocator_array_check_capacity(struct fast_allocator_context *acontex
|
|||
}
|
||||
|
||||
static int region_init(struct fast_allocator_context *acontext,
|
||||
struct fast_region_info *region)
|
||||
const char *mblock_name_prefix, struct fast_region_info *region)
|
||||
{
|
||||
int result;
|
||||
int bytes;
|
||||
int element_size;
|
||||
int allocator_count;
|
||||
struct fast_allocator_info *allocator;
|
||||
char *name;
|
||||
char name_buff[FAST_MBLOCK_NAME_SIZE];
|
||||
|
||||
region->pad_mask = region->step - 1;
|
||||
allocator_count = (region->end - region->start) / region->step;
|
||||
|
|
@ -136,12 +138,22 @@ static int region_init(struct fast_allocator_context *acontext,
|
|||
return result;
|
||||
}
|
||||
|
||||
name = name_buff;
|
||||
result = 0;
|
||||
allocator = region->allocators;
|
||||
for (element_size=region->start+region->step; element_size<=region->end;
|
||||
element_size+=region->step,allocator++)
|
||||
{
|
||||
result = fast_mblock_init_ex2(&allocator->mblock, NULL, element_size,
|
||||
if (mblock_name_prefix != NULL)
|
||||
{
|
||||
snprintf(name, FAST_MBLOCK_NAME_SIZE, "%s-%d",
|
||||
mblock_name_prefix, element_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = NULL;
|
||||
}
|
||||
result = fast_mblock_init_ex2(&allocator->mblock, name, element_size,
|
||||
region->alloc_elements_once, NULL, NULL, acontext->need_lock,
|
||||
fast_allocator_malloc_trunk_check,
|
||||
fast_allocator_malloc_trunk_notify_func, acontext);
|
||||
|
|
@ -174,9 +186,10 @@ static void region_destroy(struct fast_allocator_context *acontext,
|
|||
}
|
||||
|
||||
int fast_allocator_init_ex(struct fast_allocator_context *acontext,
|
||||
struct fast_region_info *regions, const int region_count,
|
||||
const int64_t alloc_bytes_limit, const double expect_usage_ratio,
|
||||
const int reclaim_interval, const bool need_lock)
|
||||
const char *mblock_name_prefix, struct fast_region_info *regions,
|
||||
const int region_count, const int64_t alloc_bytes_limit,
|
||||
const double expect_usage_ratio, const int reclaim_interval,
|
||||
const bool need_lock)
|
||||
{
|
||||
int result;
|
||||
int bytes;
|
||||
|
|
@ -263,7 +276,7 @@ int fast_allocator_init_ex(struct fast_allocator_context *acontext,
|
|||
}
|
||||
previous_end = pRegion->end;
|
||||
|
||||
if ((result=region_init(acontext, pRegion)) != 0)
|
||||
if ((result=region_init(acontext, mblock_name_prefix, pRegion)) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
@ -288,8 +301,9 @@ int fast_allocator_init_ex(struct fast_allocator_context *acontext,
|
|||
}
|
||||
|
||||
int fast_allocator_init(struct fast_allocator_context *acontext,
|
||||
const int64_t alloc_bytes_limit, const double expect_usage_ratio,
|
||||
const int reclaim_interval, const bool need_lock)
|
||||
const char *mblock_name_prefix, const int64_t alloc_bytes_limit,
|
||||
const double expect_usage_ratio, const int reclaim_interval,
|
||||
const bool need_lock)
|
||||
{
|
||||
#define DEFAULT_REGION_COUNT 5
|
||||
|
||||
|
|
@ -301,9 +315,9 @@ int fast_allocator_init(struct fast_allocator_context *acontext,
|
|||
FAST_ALLOCATOR_INIT_REGION(regions[3], 4096, 16384, 256, 64);
|
||||
FAST_ALLOCATOR_INIT_REGION(regions[4], 16384, 65536, 1024, 16);
|
||||
|
||||
return fast_allocator_init_ex(acontext, regions,
|
||||
DEFAULT_REGION_COUNT, alloc_bytes_limit,
|
||||
expect_usage_ratio, reclaim_interval, need_lock);
|
||||
return fast_allocator_init_ex(acontext, mblock_name_prefix, regions,
|
||||
DEFAULT_REGION_COUNT, alloc_bytes_limit, expect_usage_ratio,
|
||||
reclaim_interval, need_lock);
|
||||
}
|
||||
|
||||
void fast_allocator_destroy(struct fast_allocator_context *acontext)
|
||||
|
|
|
|||
|
|
@ -76,15 +76,17 @@ extern "C" {
|
|||
allocator init by default region allocators
|
||||
parameters:
|
||||
acontext: the context pointer
|
||||
alloc_bytes_limit: the alloc limit, 0 for no limit
|
||||
mblock_name_prefix: the name prefix of mblock
|
||||
alloc_bytes_limit: the alloc limit, 0 for no limit
|
||||
expect_usage_ratio: the trunk usage ratio
|
||||
reclaim_interval: reclaim interval in second, 0 for never reclaim
|
||||
need_lock: if need lock
|
||||
return error no, 0 for success, != 0 fail
|
||||
*/
|
||||
int fast_allocator_init(struct fast_allocator_context *acontext,
|
||||
const int64_t alloc_bytes_limit, const double expect_usage_ratio,
|
||||
const int reclaim_interval, const bool need_lock);
|
||||
const char *mblock_name_prefix, const int64_t alloc_bytes_limit,
|
||||
const double expect_usage_ratio, const int reclaim_interval,
|
||||
const bool need_lock);
|
||||
|
||||
/**
|
||||
allocator init
|
||||
|
|
@ -99,9 +101,10 @@ parameters:
|
|||
return error no, 0 for success, != 0 fail
|
||||
*/
|
||||
int fast_allocator_init_ex(struct fast_allocator_context *acontext,
|
||||
struct fast_region_info *regions, const int region_count,
|
||||
const int64_t alloc_bytes_limit, const double expect_usage_ratio,
|
||||
const int reclaim_interval, const bool need_lock);
|
||||
const char *mblock_name_prefix, struct fast_region_info *regions,
|
||||
const int region_count, const int64_t alloc_bytes_limit,
|
||||
const double expect_usage_ratio, const int reclaim_interval,
|
||||
const bool need_lock);
|
||||
|
||||
/**
|
||||
allocator destroy
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ static void delete_from_mblock_list(struct fast_mblock_man *mblock)
|
|||
} \
|
||||
pStat->element_total_count += current->info.element_total_count; \
|
||||
pStat->element_used_count += current->info.element_used_count; \
|
||||
pStat->delay_free_elements += current->info.delay_free_elements; \
|
||||
pStat->trunk_total_count += current->info.trunk_total_count; \
|
||||
pStat->trunk_used_count += current->info.trunk_used_count; \
|
||||
pStat->instance_count += current->info.instance_count; \
|
||||
|
|
@ -233,8 +234,10 @@ int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
|
|||
int64_t alloc_mem;
|
||||
int64_t used_mem;
|
||||
int64_t amem;
|
||||
int64_t delay_free_mem;
|
||||
char alloc_mem_str[32];
|
||||
char used_mem_str[32];
|
||||
char delay_free_mem_str[32];
|
||||
|
||||
if (order_by == FAST_MBLOCK_ORDER_BY_ALLOC_BYTES)
|
||||
{
|
||||
|
|
@ -249,31 +252,37 @@ int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
|
|||
|
||||
alloc_mem = 0;
|
||||
used_mem = 0;
|
||||
logInfo("%20s %12s %8s %12s %10s %10s %14s %12s %12s", "name", "element_size",
|
||||
"instance", "alloc_bytes", "trunc_alloc", "trunk_used",
|
||||
"element_alloc", "element_used", "used_ratio");
|
||||
delay_free_mem = 0;
|
||||
logInfo("%20s %8s %8s %12s %10s %10s %10s %10s %10s %12s",
|
||||
"name", "el_size", "instance", "alloc_bytes",
|
||||
"trunc_alloc", "trunk_used", "el_alloc",
|
||||
"el_used", "delay_free", "used_ratio");
|
||||
stat_end = stats + count;
|
||||
for (pStat=stats; pStat<stat_end; pStat++)
|
||||
{
|
||||
if (pStat->trunk_total_count > 0)
|
||||
{
|
||||
amem = pStat->trunk_size * pStat->trunk_total_count;
|
||||
amem = pStat->trunk_size * pStat->trunk_total_count;
|
||||
alloc_mem += amem;
|
||||
used_mem += GET_BLOCK_SIZE(*pStat) * pStat->element_used_count;
|
||||
used_mem += GET_BLOCK_SIZE(*pStat) *
|
||||
pStat->element_used_count;
|
||||
delay_free_mem += GET_BLOCK_SIZE(*pStat) *
|
||||
pStat->delay_free_elements;
|
||||
}
|
||||
else
|
||||
{
|
||||
amem = 0;
|
||||
amem = 0;
|
||||
if (hide_empty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
logInfo("%20s %12d %8d %12"PRId64" %10d %10d %14d %12d %11.2f%%", pStat->name,
|
||||
pStat->element_size, pStat->instance_count, amem,
|
||||
pStat->trunk_total_count, pStat->trunk_used_count,
|
||||
logInfo("%20s %8d %8d %12"PRId64" %10d %10d %10d %10d %10d %11.2f%%",
|
||||
pStat->name, pStat->element_size, pStat->instance_count,
|
||||
amem, pStat->trunk_total_count, pStat->trunk_used_count,
|
||||
pStat->element_total_count, pStat->element_used_count,
|
||||
pStat->delay_free_elements,
|
||||
pStat->element_total_count > 0 ? 100.00 * (double)
|
||||
pStat->element_used_count / (double)
|
||||
pStat->element_total_count : 0.00);
|
||||
|
|
@ -283,26 +292,40 @@ int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
|
|||
{
|
||||
sprintf(alloc_mem_str, "%"PRId64" bytes", alloc_mem);
|
||||
sprintf(used_mem_str, "%"PRId64" bytes", used_mem);
|
||||
sprintf(delay_free_mem_str, "%"PRId64" bytes", delay_free_mem);
|
||||
}
|
||||
else if (alloc_mem < 1024 * 1024)
|
||||
{
|
||||
sprintf(alloc_mem_str, "%.3f KB", (double)alloc_mem / 1024);
|
||||
sprintf(used_mem_str, "%.3f KB", (double)used_mem / 1024);
|
||||
sprintf(delay_free_mem_str, "%.3f KB",
|
||||
(double)delay_free_mem / 1024);
|
||||
}
|
||||
else if (alloc_mem < 1024 * 1024 * 1024)
|
||||
{
|
||||
sprintf(alloc_mem_str, "%.3f MB", (double)alloc_mem / (1024 * 1024));
|
||||
sprintf(used_mem_str, "%.3f MB", (double)used_mem / (1024 * 1024));
|
||||
sprintf(alloc_mem_str, "%.3f MB",
|
||||
(double)alloc_mem / (1024 * 1024));
|
||||
sprintf(used_mem_str, "%.3f MB",
|
||||
(double)used_mem / (1024 * 1024));
|
||||
sprintf(delay_free_mem_str, "%.3f MB",
|
||||
(double)delay_free_mem / (1024 * 1024));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(alloc_mem_str, "%.3f GB", (double)alloc_mem / (1024 * 1024 * 1024));
|
||||
sprintf(used_mem_str, "%.3f GB", (double)used_mem / (1024 * 1024 * 1024));
|
||||
sprintf(alloc_mem_str, "%.3f GB",
|
||||
(double)alloc_mem / (1024 * 1024 * 1024));
|
||||
sprintf(used_mem_str, "%.3f GB",
|
||||
(double)used_mem / (1024 * 1024 * 1024));
|
||||
sprintf(delay_free_mem_str, "%.3f GB",
|
||||
(double)delay_free_mem / (1024 * 1024 * 1024));
|
||||
}
|
||||
|
||||
logInfo("mblock entry count: %d, alloc memory: %s, used memory: %s, used ratio: %.2f%%",
|
||||
count, alloc_mem_str, used_mem_str,
|
||||
alloc_mem > 0 ? 100.00 * (double)used_mem / alloc_mem : 0.00);
|
||||
logInfo("mblock entry count: %d, memory stat => { alloc : %s, "
|
||||
"used: %s (%.2f%%), delay free: %s (%.2f%%) }",
|
||||
count, alloc_mem_str, used_mem_str, alloc_mem > 0 ?
|
||||
100.00 * (double)used_mem / alloc_mem : 0.00,
|
||||
delay_free_mem_str, alloc_mem > 0 ? 100.00 *
|
||||
(double)delay_free_mem / alloc_mem : 0.00);
|
||||
}
|
||||
|
||||
if (stats != NULL) free(stats);
|
||||
|
|
@ -362,6 +385,7 @@ int fast_mblock_init_ex2(struct fast_mblock_man *mblock, const char *name,
|
|||
INIT_HEAD(&mblock->trunks.head);
|
||||
mblock->info.trunk_total_count = 0;
|
||||
mblock->info.trunk_used_count = 0;
|
||||
mblock->info.delay_free_elements = 0;
|
||||
mblock->free_chain_head = NULL;
|
||||
mblock->delay_free_chain.head = NULL;
|
||||
mblock->delay_free_chain.tail = NULL;
|
||||
|
|
@ -534,6 +558,7 @@ void fast_mblock_destroy(struct fast_mblock_man *mblock)
|
|||
mblock->info.trunk_used_count = 0;
|
||||
mblock->free_chain_head = NULL;
|
||||
mblock->info.element_used_count = 0;
|
||||
mblock->info.delay_free_elements = 0;
|
||||
mblock->info.element_total_count = 0;
|
||||
|
||||
if (mblock->need_lock) pthread_mutex_destroy(&(mblock->lock));
|
||||
|
|
@ -558,9 +583,6 @@ struct fast_mblock_node *fast_mblock_alloc(struct fast_mblock_man *mblock)
|
|||
{
|
||||
pNode = mblock->free_chain_head;
|
||||
mblock->free_chain_head = pNode->next;
|
||||
mblock->info.element_used_count++;
|
||||
|
||||
fast_mblock_ref_counter_inc(mblock, pNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -573,13 +595,13 @@ struct fast_mblock_node *fast_mblock_alloc(struct fast_mblock_man *mblock)
|
|||
{
|
||||
mblock->delay_free_chain.tail = NULL;
|
||||
}
|
||||
|
||||
mblock->info.delay_free_elements--;
|
||||
}
|
||||
else if ((result=fast_mblock_prealloc(mblock)) == 0)
|
||||
{
|
||||
pNode = mblock->free_chain_head;
|
||||
mblock->free_chain_head = pNode->next;
|
||||
mblock->info.element_used_count++;
|
||||
fast_mblock_ref_counter_inc(mblock, pNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -587,6 +609,11 @@ struct fast_mblock_node *fast_mblock_alloc(struct fast_mblock_man *mblock)
|
|||
}
|
||||
}
|
||||
|
||||
if (pNode != NULL)
|
||||
{
|
||||
mblock->info.element_used_count++;
|
||||
fast_mblock_ref_counter_inc(mblock, pNode);
|
||||
}
|
||||
if (mblock->need_lock && (result=pthread_mutex_unlock(&(mblock->lock))) != 0)
|
||||
{
|
||||
logError("file: "__FILE__", line: %d, " \
|
||||
|
|
@ -654,6 +681,10 @@ int fast_mblock_delay_free(struct fast_mblock_man *mblock,
|
|||
mblock->delay_free_chain.tail = pNode;
|
||||
pNode->next = NULL;
|
||||
|
||||
mblock->info.element_used_count--;
|
||||
mblock->info.delay_free_elements++;
|
||||
fast_mblock_ref_counter_dec(mblock, pNode);
|
||||
|
||||
if (mblock->need_lock && (result=pthread_mutex_unlock(&(mblock->lock))) != 0)
|
||||
{
|
||||
logError("file: "__FILE__", line: %d, " \
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ struct fast_mblock_info
|
|||
int element_size; //element size
|
||||
int element_total_count; //total element count
|
||||
int element_used_count; //used element count
|
||||
int delay_free_elements; //delay free element count
|
||||
int trunk_size; //trunk size
|
||||
int trunk_total_count; //total trunk count
|
||||
int trunk_used_count; //used trunk count
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ int main(int argc, char *argv[])
|
|||
g_log_context.log_level = LOG_DEBUG;
|
||||
|
||||
fast_mblock_manager_init();
|
||||
if ((result=fast_allocator_init(&acontext, 0, 0.00, 0, true)) != 0)
|
||||
if ((result=fast_allocator_init(&acontext, NULL, 0, 0.00, 0, true)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,14 @@ int uniq_skiplist_init_ex(UniqSkiplistFactory *factory,
|
|||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
factory->tail = (UniqSkiplistNode *)fast_mblock_alloc_object(
|
||||
factory->node_allocators + 0);
|
||||
if (factory->tail == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
memset(factory->tail, 0, factory->node_allocators[0].info.element_size);
|
||||
|
||||
factory->max_level_count = max_level_count;
|
||||
factory->compare_func = compare_func;
|
||||
factory->free_func = free_func;
|
||||
|
|
@ -130,6 +137,8 @@ void uniq_skiplist_destroy(UniqSkiplistFactory *factory)
|
|||
return;
|
||||
}
|
||||
|
||||
fast_mblock_free_object(factory->node_allocators + 0,
|
||||
(void *)factory->tail);
|
||||
fast_mblock_destroy(&factory->skiplist_allocator);
|
||||
|
||||
for (i=0; i<factory->max_level_count; i++) {
|
||||
|
|
@ -178,16 +187,8 @@ UniqSkiplist *uniq_skiplist_new(UniqSkiplistFactory *factory,
|
|||
}
|
||||
memset(sl->top, 0, top_mblock->info.element_size);
|
||||
|
||||
sl->tail = (UniqSkiplistNode *)fast_mblock_alloc_object(
|
||||
sl->factory->node_allocators + 0);
|
||||
if (sl->tail == NULL) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
memset(sl->tail, 0, sl->factory->node_allocators[0].info.element_size);
|
||||
|
||||
for (i=0; i<level_count; i++) {
|
||||
sl->top->links[i] = sl->tail;
|
||||
sl->top->links[i] = sl->factory->tail;
|
||||
}
|
||||
|
||||
return sl;
|
||||
|
|
@ -214,7 +215,7 @@ static int uniq_skiplist_grow(UniqSkiplist *sl)
|
|||
}
|
||||
memset(top, 0, top_mblock->info.element_size);
|
||||
|
||||
top->links[top_level_index] = sl->tail;
|
||||
top->links[top_level_index] = sl->factory->tail;
|
||||
for (i=0; i<=sl->top_level_index; i++) {
|
||||
top->links[i] = sl->top->links[i];
|
||||
}
|
||||
|
|
@ -223,7 +224,7 @@ static int uniq_skiplist_grow(UniqSkiplist *sl)
|
|||
old_top = sl->top;
|
||||
sl->top = top;
|
||||
|
||||
__sync_synchronize();
|
||||
compile_barrier();
|
||||
sl->top_level_index = top_level_index;
|
||||
|
||||
UNIQ_SKIPLIST_FREE_MBLOCK_OBJECT(sl, old_top_level_index, old_top);
|
||||
|
|
@ -241,7 +242,7 @@ void uniq_skiplist_free(UniqSkiplist *sl)
|
|||
|
||||
node = sl->top->links[0];
|
||||
if (sl->factory->free_func != NULL) {
|
||||
while (node != sl->tail) {
|
||||
while (node != sl->factory->tail) {
|
||||
deleted = node;
|
||||
node = node->links[0];
|
||||
sl->factory->free_func(deleted->data, 0);
|
||||
|
|
@ -249,7 +250,7 @@ void uniq_skiplist_free(UniqSkiplist *sl)
|
|||
deleted->level_index, (void *)deleted);
|
||||
}
|
||||
} else {
|
||||
while (node != sl->tail) {
|
||||
while (node != sl->factory->tail) {
|
||||
deleted = node;
|
||||
node = node->links[0];
|
||||
fast_mblock_free_object(sl->factory->node_allocators +
|
||||
|
|
@ -259,11 +260,8 @@ void uniq_skiplist_free(UniqSkiplist *sl)
|
|||
|
||||
fast_mblock_free_object(sl->factory->node_allocators +
|
||||
sl->top_level_index, (void *)sl->top);
|
||||
fast_mblock_free_object(sl->factory->node_allocators + 0,
|
||||
(void *)sl->tail);
|
||||
|
||||
sl->top = NULL;
|
||||
sl->tail = NULL;
|
||||
sl->element_count = 0;
|
||||
fast_mblock_free_object(&sl->factory->skiplist_allocator, sl);
|
||||
}
|
||||
|
|
@ -293,7 +291,7 @@ int uniq_skiplist_insert(UniqSkiplist *sl, void *data)
|
|||
level_index = uniq_skiplist_get_level_index(sl);
|
||||
previous = sl->top;
|
||||
for (i=sl->top_level_index; i>level_index; i--) {
|
||||
while (previous->links[i] != sl->tail) {
|
||||
while (previous->links[i] != sl->factory->tail) {
|
||||
cmp = sl->factory->compare_func(data, previous->links[i]->data);
|
||||
if (cmp < 0) {
|
||||
break;
|
||||
|
|
@ -307,7 +305,7 @@ int uniq_skiplist_insert(UniqSkiplist *sl, void *data)
|
|||
}
|
||||
|
||||
while (i >= 0) {
|
||||
while (previous->links[i] != sl->tail) {
|
||||
while (previous->links[i] != sl->factory->tail) {
|
||||
cmp = sl->factory->compare_func(data, previous->links[i]->data);
|
||||
if (cmp < 0) {
|
||||
break;
|
||||
|
|
@ -331,7 +329,7 @@ int uniq_skiplist_insert(UniqSkiplist *sl, void *data)
|
|||
node->level_index = level_index;
|
||||
node->data = data;
|
||||
|
||||
__sync_synchronize();
|
||||
compile_barrier();
|
||||
|
||||
//thread safe for one write with many read model
|
||||
for (i=0; i<=level_index; i++) {
|
||||
|
|
@ -356,7 +354,7 @@ static UniqSkiplistNode *uniq_skiplist_get_equal_previous(UniqSkiplist *sl,
|
|||
|
||||
previous = sl->top;
|
||||
for (i=sl->top_level_index; i>=0; i--) {
|
||||
while (previous->links[i] != sl->tail) {
|
||||
while (previous->links[i] != sl->factory->tail) {
|
||||
cmp = sl->factory->compare_func(data, previous->links[i]->data);
|
||||
if (cmp < 0) {
|
||||
break;
|
||||
|
|
@ -382,7 +380,7 @@ static UniqSkiplistNode *uniq_skiplist_get_first_larger_or_equal(
|
|||
|
||||
previous = sl->top;
|
||||
for (i=sl->top_level_index; i>=0; i--) {
|
||||
while (previous->links[i] != sl->tail) {
|
||||
while (previous->links[i] != sl->factory->tail) {
|
||||
cmp = sl->factory->compare_func(data, previous->links[i]->data);
|
||||
if (cmp < 0) {
|
||||
break;
|
||||
|
|
@ -407,7 +405,7 @@ static UniqSkiplistNode *uniq_skiplist_get_first_larger(
|
|||
|
||||
previous = sl->top;
|
||||
for (i=sl->top_level_index; i>=0; i--) {
|
||||
while (previous->links[i] != sl->tail) {
|
||||
while (previous->links[i] != sl->factory->tail) {
|
||||
cmp = sl->factory->compare_func(data, previous->links[i]->data);
|
||||
if (cmp < 0) {
|
||||
break;
|
||||
|
|
@ -437,7 +435,7 @@ int uniq_skiplist_delete(UniqSkiplist *sl, void *data)
|
|||
|
||||
deleted = previous->links[level_index];
|
||||
for (i=level_index; i>=0; i--) {
|
||||
while (previous->links[i] != sl->tail &&
|
||||
while (previous->links[i] != sl->factory->tail &&
|
||||
previous->links[i] != deleted)
|
||||
{
|
||||
previous = previous->links[i];
|
||||
|
|
@ -474,8 +472,8 @@ int uniq_skiplist_find_all(UniqSkiplist *sl, void *data,
|
|||
|
||||
previous = uniq_skiplist_get_equal_previous(sl, data, &level_index);
|
||||
if (previous == NULL) {
|
||||
iterator->tail = sl->tail;
|
||||
iterator->current = sl->tail;
|
||||
iterator->tail = sl->factory->tail;
|
||||
iterator->current = sl->factory->tail;
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
|
|
@ -488,18 +486,17 @@ int uniq_skiplist_find_range(UniqSkiplist *sl, void *start_data,
|
|||
void *end_data, UniqSkiplistIterator *iterator)
|
||||
{
|
||||
if (sl->factory->compare_func(start_data, end_data) > 0) {
|
||||
iterator->current = sl->tail;
|
||||
iterator->tail = sl->tail;
|
||||
iterator->current = sl->factory->tail;
|
||||
iterator->tail = sl->factory->tail;
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
iterator->current = uniq_skiplist_get_first_larger_or_equal(sl, start_data);
|
||||
if (iterator->current == sl->tail) {
|
||||
iterator->tail = sl->tail;
|
||||
if (iterator->current == sl->factory->tail) {
|
||||
iterator->tail = sl->factory->tail;
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
iterator->tail = uniq_skiplist_get_first_larger(sl, end_data);
|
||||
return iterator->current != iterator->tail ? 0 : ENOENT;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ typedef struct uniq_skiplist_factory
|
|||
int delay_free_seconds;
|
||||
skiplist_compare_func compare_func;
|
||||
uniq_skiplist_free_func free_func;
|
||||
UniqSkiplistNode *tail; //the tail node for interator
|
||||
struct fast_mblock_man skiplist_allocator;
|
||||
struct fast_mblock_man *node_allocators;
|
||||
} UniqSkiplistFactory;
|
||||
|
|
@ -43,7 +44,6 @@ typedef struct uniq_skiplist
|
|||
int top_level_index;
|
||||
int element_count;
|
||||
UniqSkiplistNode *top; //the top node
|
||||
UniqSkiplistNode *tail; //the tail node for interator
|
||||
} UniqSkiplist;
|
||||
|
||||
typedef struct uniq_skiplist_iterator {
|
||||
|
|
@ -85,7 +85,7 @@ int uniq_skiplist_find_range(UniqSkiplist *sl, void *start_data,
|
|||
static inline void uniq_skiplist_iterator(UniqSkiplist *sl, UniqSkiplistIterator *iterator)
|
||||
{
|
||||
iterator->current = sl->top->links[0];
|
||||
iterator->tail = sl->tail;
|
||||
iterator->tail = sl->factory->tail;
|
||||
}
|
||||
|
||||
static inline void *uniq_skiplist_next(UniqSkiplistIterator *iterator)
|
||||
|
|
@ -103,7 +103,7 @@ static inline void *uniq_skiplist_next(UniqSkiplistIterator *iterator)
|
|||
|
||||
static inline bool uniq_skiplist_empty(UniqSkiplist *sl)
|
||||
{
|
||||
return sl->top->links[0] == sl->tail;
|
||||
return sl->top->links[0] == sl->factory->tail;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -111,4 +111,3 @@ static inline bool uniq_skiplist_empty(UniqSkiplist *sl)
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue