From c8e81e279434cac899f4969ef614b6db0a58c46e Mon Sep 17 00:00:00 2001 From: zhangyi Date: Fri, 30 Nov 2018 15:13:44 +0800 Subject: [PATCH] use std::atomic instead of flag for better performance in arm; cross-platform supporting; add more test cases --- include/circ_elem_array.h | 8 ++++---- include/circ_queue.h | 21 ++++++++++++++++++++- test/test_circ.cpp | 37 +++++++++++++++++++------------------ 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/include/circ_elem_array.h b/include/circ_elem_array.h index 8ba53c3..1cc6339 100644 --- a/include/circ_elem_array.h +++ b/include/circ_elem_array.h @@ -16,10 +16,10 @@ struct alignas(std::max_align_t) elem_array_head { using uc_t = std::uint16_t; using ac_t = std::atomic; + std::atomic lc_ { 0 }; // write spin lock flag + ac_t cc_ { 0 }; // connection counter, using for broadcast ac_t wt_ { 0 }; // write index - - std::atomic_flag lc_ ATOMIC_FLAG_INIT; // write spin lock flag }; enum : std::size_t { @@ -93,7 +93,7 @@ public: } void* acquire(void) { - while (lc_.test_and_set(std::memory_order_acquire)) { + while (lc_.exchange(1, std::memory_order_acquire)) { std::this_thread::yield(); } elem_t* el = elem(wt_.load(std::memory_order_relaxed)); @@ -114,7 +114,7 @@ public: void commit(void* /*ptr*/) { wt_.fetch_add(1, std::memory_order_relaxed); - lc_.clear(std::memory_order_release); + lc_.store(0, std::memory_order_release); } uc_t cursor(void) const { diff --git a/include/circ_queue.h b/include/circ_queue.h index 71ddddd..b294189 100644 --- a/include/circ_queue.h +++ b/include/circ_queue.h @@ -84,8 +84,27 @@ public: return old; } + bool push(T const & item) { + if (elems_ == nullptr) return false; + auto ptr = elems_->acquire(); + ::new (ptr) T(item); + elems_->commit(ptr); + return true; + } + + template + auto push(P&& param) // disable this if P is the same as T + -> std::enable_if_t, T>::value, bool> { + if (elems_ == nullptr) return false; + auto ptr = elems_->acquire(); + ::new (ptr) T { std::forward

(param) }; + elems_->commit(ptr); + return true; + } + template - bool push(P&&... params) { + auto push(P&&... params) // some old compilers are not support this well + -> std::enable_if_t<(sizeof...(P) != 1), bool> { if (elems_ == nullptr) return false; auto ptr = elems_->acquire(); ::new (ptr) T { std::forward

(params)... }; diff --git a/test/test_circ.cpp b/test/test_circ.cpp index fae0893..95fc5cf 100644 --- a/test/test_circ.cpp +++ b/test/test_circ.cpp @@ -293,41 +293,42 @@ void Unit::test_prod_cons_3v1(void) { test_prod_cons<3, 1>(); } -template -struct test_cons_performance { +template +struct test_performance { static void start(void) { - test_prod_cons<1, B, false>(); - test_cons_performance::start(); + test_performance

::start(); + test_prod_cons(); } }; -template -struct test_cons_performance { +template +struct test_performance<1, C> { static void start(void) { - test_prod_cons<1, E, false>(); + test_performance<1, C - 1>::start(); + test_prod_cons<1, C, false>(); } }; -template -struct test_prod_performance { +template +struct test_performance { static void start(void) { - test_prod_cons(); - test_prod_performance::start(); + test_performance

::start(); + test_prod_cons(); } }; -template -struct test_prod_performance { +template <> +struct test_performance<1, 1> { static void start(void) { - test_prod_cons(); + test_prod_cons<1, 1, false>(); } }; void Unit::test_prod_cons_performance(void) { - test_cons_performance<1, 10>::start(); - test_prod_performance<1, 10>::start(); - test_prod_cons<3, 3, false>(); // just test - test_prod_cons<5, 5>(); // test & verify + test_performance<1 , 10>::start(); + test_performance<10, 1 >::start(); + test_performance<10, 10>::start(); + test_prod_cons <3 , 3 >(); // test & verify } void Unit::test_queue(void) {