Skip to content

Commit

Permalink
Merge branch 'lazy_skip_list_dev' into lazy_skip_list_integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Rextuz committed Jan 28, 2018
2 parents fc6797e + 1552f37 commit 14b8e4e
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 42 deletions.
45 changes: 19 additions & 26 deletions cds/container/details/lazy_skip_list_set_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define CDSLIB_LAZY_SKIP_LIST_BASE_H

#include <cds/intrusive/details/skip_list_base.h>
#include <cds/gc/nogc.h>

namespace cds { namespace container {

Expand All @@ -19,28 +20,25 @@ namespace cds { namespace container {
class node
{
public:
typedef GC gc;
typedef T value_type;
typedef Lock lock_type;
typedef cds::gc::nogc gc;
typedef T value_type;
typedef Lock lock_type;

typedef std::size_t key_type;

typedef node* node_ptr;
typedef std::numeric_limits<key_type> limits;
typedef cds::details::Allocator<node> node_allocator;

typedef cds::details::marked_ptr<node, 1> marked_ptr;
typedef typename gc::template atomic_marked_ptr<marked_ptr> atomic_marked_ptr;

typedef cds::details::Allocator<atomic_marked_ptr> tower_allocator;
typedef cds::details::Allocator<node> node_allocator;
typedef cds::details::Allocator<node_ptr> tower_allocator;

protected:
value_type value;
key_type key;
unsigned int m_nHeight;
atomic_marked_ptr * m_arrNext;
node_ptr * m_arrNext;
atomics::atomic<bool> _marked;
atomics::atomic<bool> fullyLinked;
atomics::atomic<bool> _fully_linked;

key_type hash() {
return std::hash<value_type>{}(value);
Expand All @@ -49,7 +47,7 @@ namespace cds { namespace container {
public:
lock_type lock;

node() : _marked(false), fullyLinked(false) {
node() : _marked(false), _fully_linked(false) {

}

Expand All @@ -58,31 +56,26 @@ namespace cds { namespace container {
}

bool marked() {
return _marked;
return _marked.load();
}

bool mark() {
_marked = true;
}

bool mark_hard() {
marked_ptr next_marked(next(0).load(atomics::memory_order_relaxed).ptr());
next(0).compare_exchange_strong(next_marked, next_marked | 1, atomics::memory_order_release, atomics::memory_order_acquire);
_marked.store(true);
}

bool fully_linked() {
return fullyLinked.load(atomics::memory_order_relaxed);
return _fully_linked.load();
}

void set_fully_linked(bool value) {
fullyLinked.store(value, atomics::memory_order_relaxed);
_fully_linked.store(value);
}

key_type node_key() {
return key;
}

atomic_marked_ptr& next(unsigned int nLevel) {
node_ptr& next(unsigned int nLevel) {
return m_arrNext[nLevel];
}

Expand All @@ -107,8 +100,8 @@ namespace cds { namespace container {
ta.Delete(pNode->release_tower(), topLayer + 1);
}

atomic_marked_ptr * release_tower() {
atomic_marked_ptr * pTower = m_arrNext;
node_ptr * release_tower() {
node_ptr * pTower = m_arrNext;
m_arrNext = nullptr;
m_nHeight = 0;

Expand All @@ -121,7 +114,7 @@ namespace cds { namespace container {
new_node->key = key;
new_node->m_nHeight = cds::container::lazy_skip_list_set::c_nMaxHeight;
new_node->allocate_tower(new_node->m_nHeight);
new_node->fullyLinked = false;
new_node->_fully_linked = false;

return new_node;
}
Expand All @@ -133,7 +126,7 @@ namespace cds { namespace container {
new_node->value = v;
new_node->key = new_node->hash();
new_node->m_nHeight = topLayer;
new_node->fullyLinked = false;
new_node->_fully_linked = false;

new_node->allocate_tower(topLayer + 1);

Expand All @@ -147,7 +140,7 @@ namespace cds { namespace container {
}

static node * max_key() {
node_ptr new_node = allocate_node(limits::max() / 1000);
node_ptr new_node = allocate_node(limits::max());

return new_node;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <mutex>

#include <cds/container/details/lazy_skip_list_set_base.h>
#include <cds/gc/nogc.h>

namespace cds { namespace container {

Expand All @@ -15,12 +16,12 @@ namespace cds { namespace container {
class LazySkipListSet
{
public:
typedef GC gc;
typedef T value_type;
typedef Traits traits;
typedef cds::gc::nogc gc;
typedef T value_type;
typedef Traits traits;

static size_t const c_nMaxHeight = cds::container::lazy_skip_list_set::c_nMaxHeight;
// static size_t const c_nHazardPtrCount = c_nMaxHeight * 2 + 3;
static size_t const c_nHazardPtrCount = 0;

typedef typename traits::random_level_generator rand_height;

Expand All @@ -39,7 +40,7 @@ namespace cds { namespace container {
m_Tail = node_type::max_key();

for (unsigned int layer = 0; layer < c_nMaxHeight; layer++)
m_Head->next(layer).store(marked_ptr(m_Tail), traits::memory_model::memory_order_relaxed);
m_Head->next(layer) = m_Tail;
}

~LazySkipListSet() {
Expand Down Expand Up @@ -90,8 +91,8 @@ namespace cds { namespace container {

node_type *new_node = node_type::allocate_node(v, topLayer);
for (unsigned int layer = 0; layer <= topLayer; layer++) {
new_node->next(layer).store(marked_ptr(succs[layer]));
preds[layer]->next(layer).store(marked_ptr(new_node));
new_node->next(layer) = succs[layer];
preds[layer]->next(layer) = new_node;
}

new_node->set_fully_linked(true);
Expand Down Expand Up @@ -154,10 +155,10 @@ namespace cds { namespace container {
continue;

for (unsigned int layer = topLayer; layer >= 0 && layer < c_nMaxHeight; layer--)
preds[layer]->next(layer).store(nodeToDelete->next(layer), atomics::memory_order_relaxed);
preds[layer]->next(layer) = nodeToDelete->next(layer);

nodeToDelete->lock.unlock();
nodeToDelete->mark_hard();
node_type::dispose_node(nodeToDelete);
unlock(preds, highestLocked);
return true;
} catch (int e) {
Expand All @@ -184,25 +185,24 @@ namespace cds { namespace container {
}

bool empty() {
// FIXME
node_type *succ = m_Head->next(0).load(traits::memory_model::memory_order_relaxed).ptr();
node_type *succ = m_Head->next(0);

while (true) {
if (m_Head->next(0) == m_Tail)
return true;

if (succ->marked())
succ = m_Head->next(0).load(traits::memory_model::memory_order_relaxed).ptr();
succ = m_Head->next(0);
else
return false;
}
}

protected:
void destroy() {
node_type *p = m_Head; //->next(0).load(atomics::memory_order_relaxed).ptr();
node_type *p = m_Head;
while (p) {
node_type *pNext = p->next(0).load(atomics::memory_order_relaxed).ptr();
node_type *pNext = p->next(0);
node_type::dispose_node(p);
p = pNext;
}
Expand All @@ -223,11 +223,11 @@ namespace cds { namespace container {
node_type *pred = m_Head;

for (unsigned int layer = c_nMaxHeight - 1; layer >= 0 && layer < c_nMaxHeight; layer--) {
node_type *curr = pred->next(layer).load(traits::memory_model::memory_order_relaxed).ptr();
node_type *curr = pred->next(layer);

while (key > curr->node_key()) {
pred = curr;
curr = pred->next(layer).load(traits::memory_model::memory_order_relaxed).ptr();
curr = pred->next(layer);
}

if (lFound == -1 && key == curr->node_key())
Expand Down
10 changes: 10 additions & 0 deletions test/unit/set/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ add_executable(${UNIT_SET_SKIP} ${UNIT_SET_SKIP_SOURCES})
target_link_libraries(${UNIT_SET_SKIP} ${CDS_TEST_LIBRARIES})
add_test(NAME ${UNIT_SET_SKIP} COMMAND ${UNIT_SET_SKIP} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})

# LazySkipListSet
set(UNIT_SET_LAZY_SKIP unit-set-lazy-skip)
set(UNIT_SET_LAZY_SKIP_SOURCES
../main.cpp
lazy_skiplist.cpp
)
add_executable(${UNIT_SET_LAZY_SKIP} ${UNIT_SET_LAZY_SKIP_SOURCES})
target_link_libraries(${UNIT_SET_LAZY_SKIP} ${CDS_TEST_LIBRARIES})
add_test(NAME ${UNIT_SET_LAZY_SKIP} COMMAND ${UNIT_SET_SKIP} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})

# SplitListSet<MichaelList>
set(UNIT_SET_SPLIT_MICHAEL unit-set-split-michael)
set(UNIT_SET_SPLIT_MICHAEL_SOURCES
Expand Down
66 changes: 66 additions & 0 deletions test/unit/set/lazy_skiplist.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include <cds_test/ext_gtest.h>

#include <cds/gc/dhp.h>
#include <cds/container/lazy_skip_list_set.h>

template<typename T>
using Set = cds::container::LazySkipListSet<cds::gc::DHP, T>;

typedef int value_type;

TEST(LazyTest, test_insert) {
Set<value_type> set;

ASSERT_TRUE(set.insert(42));
ASSERT_TRUE(set.insert(41));
ASSERT_TRUE(set.insert(43));

ASSERT_FALSE(set.insert(42));
ASSERT_FALSE(set.insert(43.0f));
ASSERT_FALSE(set.insert(41));

ASSERT_TRUE(set.insert(-41));
}

TEST(LazyTest, test_contains) {
Set<value_type> set;

ASSERT_FALSE(set.contains(42));
ASSERT_FALSE(set.contains(43));

set.insert(42);
ASSERT_TRUE(set.contains(42));
ASSERT_FALSE(set.contains(43));

set.insert(43);
ASSERT_TRUE(set.contains(42));
ASSERT_TRUE(set.contains(43));
}

TEST(LazyTest, test_remove) {
Set<value_type> set;

ASSERT_FALSE(set.remove(42));

set.insert(42);
ASSERT_TRUE(set.remove(42));
ASSERT_FALSE(set.remove(42));
}

TEST(LazyTest, test_empty) {
Set<value_type> set;

ASSERT_TRUE(set.empty());

set.insert(42);
ASSERT_FALSE(set.empty());

set.insert(43);
ASSERT_FALSE(set.empty());

set.remove(42);
ASSERT_FALSE(set.empty());

set.remove(43);
ASSERT_TRUE(set.empty());
}

0 comments on commit 14b8e4e

Please sign in to comment.