diff --git a/include/libconcur/intrusive_stack.h b/include/libconcur/intrusive_stack.h index abaf735..e315ebb 100644 --- a/include/libconcur/intrusive_stack.h +++ b/include/libconcur/intrusive_stack.h @@ -12,13 +12,21 @@ LIBCONCUR_NAMESPACE_BEG_ +/// \brief Intrusive stack node. +/// \tparam T The type of the value. template +struct intrusive_node { + T value; + std::atomic next; +}; + +/// \brief Intrusive stack. +/// \tparam T The type of the value. +/// \tparam Node The type of the node. +template > class intrusive_stack { public: - struct node { - T value; - std::atomic next{nullptr}; - }; + using node = Node; private: std::atomic top_{nullptr}; @@ -50,8 +58,8 @@ public: return nullptr; } } while (!top_.compare_exchange_weak(old_top, old_top->next.load(std::memory_order_relaxed) - , std::memory_order_release - , std::memory_order_acquire)); + , std::memory_order_release + , std::memory_order_acquire)); return old_top; } }; diff --git a/test/concur/test_concur_stack.cpp b/test/concur/test_concur_stack.cpp index 6dc8428..33544c1 100644 --- a/test/concur/test_concur_stack.cpp +++ b/test/concur/test_concur_stack.cpp @@ -10,7 +10,7 @@ TEST(intrusive_stack, construct) { } TEST(intrusive_stack, construct_node) { - concur::intrusive_stack::node n; + concur::intrusive_stack::node n{}; EXPECT_TRUE(n.next.load(std::memory_order_relaxed) == nullptr); } @@ -26,18 +26,19 @@ TEST(intrusive_stack, moveable) { TEST(intrusive_stack, push_one) { concur::intrusive_stack s; - concur::intrusive_stack::node n; + concur::intrusive_stack::node n{123}; s.push(&n); EXPECT_FALSE(s.empty()); EXPECT_TRUE(s.top_.load(std::memory_order_relaxed) == &n); EXPECT_TRUE(n.next.load(std::memory_order_relaxed) == nullptr); + EXPECT_EQ(n.value, 123); } TEST(intrusive_stack, push_many) { concur::intrusive_stack s; - concur::intrusive_stack::node n1; - concur::intrusive_stack::node n2; - concur::intrusive_stack::node n3; + concur::intrusive_stack::node n1{111111}; + concur::intrusive_stack::node n2{222222}; + concur::intrusive_stack::node n3{333333}; s.push(&n1); s.push(&n2); s.push(&n3); @@ -46,16 +47,20 @@ TEST(intrusive_stack, push_many) { EXPECT_TRUE(n3.next.load(std::memory_order_relaxed) == &n2); EXPECT_TRUE(n2.next.load(std::memory_order_relaxed) == &n1); EXPECT_TRUE(n1.next.load(std::memory_order_relaxed) == nullptr); + EXPECT_EQ(n1.value, 111111); + EXPECT_EQ(n2.value, 222222); + EXPECT_EQ(n3.value, 333333); } TEST(intrusive_stack, push_same) { concur::intrusive_stack s; - concur::intrusive_stack::node n; + concur::intrusive_stack::node n{321}; s.push(&n); s.push(&n); EXPECT_FALSE(s.empty()); EXPECT_TRUE(s.top_.load(std::memory_order_relaxed) == &n); EXPECT_TRUE(n.next.load(std::memory_order_relaxed) == &n); + EXPECT_EQ(n.value, 321); } TEST(intrusive_stack, pop_empty) { @@ -65,19 +70,20 @@ TEST(intrusive_stack, pop_empty) { TEST(intrusive_stack, pop_one) { concur::intrusive_stack s; - concur::intrusive_stack::node n; + concur::intrusive_stack::node n{112233}; s.push(&n); EXPECT_TRUE(s.pop() == &n); EXPECT_TRUE(s.empty()); EXPECT_TRUE(s.top_.load(std::memory_order_relaxed) == nullptr); EXPECT_TRUE(n.next.load(std::memory_order_relaxed) == nullptr); + EXPECT_EQ(n.value, 112233); } TEST(intrusive_stack, pop_many) { concur::intrusive_stack s; - concur::intrusive_stack::node n1; - concur::intrusive_stack::node n2; - concur::intrusive_stack::node n3; + concur::intrusive_stack::node n1{111111}; + concur::intrusive_stack::node n2{222222}; + concur::intrusive_stack::node n3{333333}; s.push(&n1); s.push(&n2); s.push(&n3); @@ -89,4 +95,7 @@ TEST(intrusive_stack, pop_many) { EXPECT_TRUE(n3.next.load(std::memory_order_relaxed) == &n2); EXPECT_TRUE(n2.next.load(std::memory_order_relaxed) == &n1); EXPECT_TRUE(n1.next.load(std::memory_order_relaxed) == nullptr); + EXPECT_EQ(n1.value, 111111); + EXPECT_EQ(n2.value, 222222); + EXPECT_EQ(n3.value, 333333); }