diff --git a/src/skiplist.cc b/src/skiplist.cc index b64c060..85ea202 100644 --- a/src/skiplist.cc +++ b/src/skiplist.cc @@ -111,6 +111,7 @@ void skiplist_init(skiplist_raw *slist, // for +17M items, complexity will grow linearly: O(k lg n). slist->fanout = 4; slist->max_layer = 12; + slist->num_entries = 0; skiplist_init_node(&slist->head); skiplist_init_node(&slist->tail); @@ -155,6 +156,12 @@ void skiplist_free_node(skiplist_node *node) FREE_NODE_PTR(node->next); } +size_t skiplist_get_size(skiplist_raw* slist) { + uint32_t val; + ATM_LOAD(slist->num_entries, val); + return val; +} + skiplist_raw_config skiplist_get_default_config() { skiplist_raw_config ret; @@ -464,6 +471,7 @@ void skiplist_insert(skiplist_raw *slist, // modification is done for all layers _sl_clr_flags(prevs, 0, top_layer); ATM_FETCH_SUB(cur_node->ref_count, 1); + ATM_FETCH_ADD(slist->num_entries, 1); return; } while (cur_node != &slist->tail); } @@ -679,6 +687,7 @@ int skiplist_erase_node(skiplist_raw *slist, ATM_FETCH_SUB(cur_node->ref_count, 1); ATM_STORE(node->being_modified, bool_false); + ATM_FETCH_SUB(slist->num_entries, 1); return 0; } @@ -714,9 +723,6 @@ int skiplist_erase(skiplist_raw *slist, return ret; } - -#include - int skiplist_is_safe_to_free(skiplist_node* node) { if (node->accessing_next) return 0; if (node->being_modified) return 0; @@ -733,7 +739,7 @@ void skiplist_grab_node(skiplist_node* node) { } void skiplist_release_node(skiplist_node* node) { - assert(node->ref_count); + __SLD_ASSERT(node->ref_count); ATM_FETCH_SUB(node->ref_count, 1); } diff --git a/src/skiplist.h b/src/skiplist.h index 860e688..d4fa707 100644 --- a/src/skiplist.h +++ b/src/skiplist.h @@ -78,6 +78,7 @@ typedef struct { skiplist_node tail; skiplist_cmp_t *cmp_func; void *aux; + atm_uint32_t num_entries; uint8_t fanout; uint8_t max_layer; } skiplist_raw; @@ -94,6 +95,8 @@ void skiplist_free(skiplist_raw* slist); void skiplist_init_node(skiplist_node* node); void skiplist_free_node(skiplist_node* node); +size_t skiplist_get_size(skiplist_raw* slist); + skiplist_raw_config skiplist_get_default_config(); skiplist_raw_config skiplist_get_config(skiplist_raw* slist); diff --git a/tests/mt_itr_write_erase_test.cc b/tests/mt_itr_write_erase_test.cc index 7c779ae..ebda85c 100644 --- a/tests/mt_itr_write_erase_test.cc +++ b/tests/mt_itr_write_erase_test.cc @@ -71,12 +71,11 @@ void itr_thread(ThreadArgs* args) { args->ret = _itr_thread(args); } -void writer_thread(ThreadArgs* args) { +int _writer_thread(ThreadArgs* args) { std::chrono::time_point start, cur; std::chrono::duration elapsed; start = std::chrono::system_clock::now(); - do { int r; TestNode* node; @@ -115,10 +114,26 @@ void writer_thread(ThreadArgs* args) { cur = std::chrono::system_clock::now(); elapsed = cur - start; } while (args->duration_ms > elapsed.count() * 1000); + + uint64_t c_check = 0; + skiplist_node* cursor = skiplist_begin(args->slist); + while (cursor) { + skiplist_node* temp_node = cursor; + cursor = skiplist_next(args->slist, cursor); + skiplist_release_node(temp_node); + c_check++; + } + if (cursor) skiplist_release_node(cursor); + + CHK_EQ(c_check, skiplist_get_size(args->slist)); + return 0; +} + +void writer_thread(ThreadArgs* args) { + args->ret = _writer_thread(args); } int itr_write_erase() { - ThreadArgs args; std::thread iterator; std::thread writer; int num = 30000; @@ -132,6 +147,8 @@ int itr_write_erase() { node[ii]->value = ii; skiplist_insert(&slist, &node[ii]->snode); } + CHK_EQ(num, (int)skiplist_get_size(&slist)); + for (int ii=0; iisnode.ref_count); } @@ -143,15 +160,22 @@ int itr_write_erase() { CHK_EQ(0, node[ii]->snode.ref_count); } - args.slist = &slist; - args.duration_ms = 1000; - args.max_num = num; - iterator = std::thread(itr_thread, &args); - writer = std::thread(writer_thread, &args); + ThreadArgs args_itr; + ThreadArgs args_writer; + args_itr.slist = &slist; + args_itr.duration_ms = 1000; + args_itr.max_num = num; + args_itr.ret = 0; + args_writer = args_itr; + iterator = std::thread(itr_thread, &args_itr); + writer = std::thread(writer_thread, &args_writer); iterator.join(); writer.join(); + CHK_EQ(0, args_itr.ret); + CHK_EQ(0, args_writer.ret); + for (int ii=0; iisnode.ref_count); }