From d5b5b3e0f49541ecc0b47b2a231dd0f2057e3c85 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Tue, 11 Dec 2018 16:58:51 +0800 Subject: [PATCH] def ipc::uint; optimize code --- include/circ_elem_array.h | 115 +++++++++++++++++++------------------- include/def.h | 10 ++++ test/test_circ.cpp | 6 +- 3 files changed, 72 insertions(+), 59 deletions(-) diff --git a/include/circ_elem_array.h b/include/circ_elem_array.h index 72d2d1c..607a7d9 100644 --- a/include/circ_elem_array.h +++ b/include/circ_elem_array.h @@ -10,35 +10,62 @@ namespace ipc { namespace circ { +template struct alignas(std::max_align_t) elem_array_head { - using ui_t = std::uint8_t; - using uc_t = std::uint16_t; - using ac_t = std::atomic; + using u1_t = uint_t; + using u2_t = uint_t; - std::atomic lc_ { 0 }; // write spin lock flag + std::atomic cc_ { 0 }; // connection counter, using for broadcast + std::atomic wt_ { 0 }; // write index + std::atomic lc_ { 0 }; // write spin lock flag - ac_t cc_ { 0 }; // connection counter, using for broadcast - ac_t wt_ { 0 }; // write index + static u1_t index_of(u2_t c) { return static_cast(c); } + + std::size_t connect(void) { + return cc_.fetch_add(1, std::memory_order_release); + } + + std::size_t disconnect(void) { + return cc_.fetch_sub(1, std::memory_order_release); + } + + std::size_t conn_count(void) const { + return cc_.load(std::memory_order_acquire); + } + + auto acquire(void) { + while (lc_.exchange(1, std::memory_order_acquire)) { + std::this_thread::yield(); + } + return index_of(wt_.load(std::memory_order_relaxed)); + } + + void commit(void) { + wt_.fetch_add(1, std::memory_order_relaxed); + lc_.store(0, std::memory_order_release); + } }; -enum : std::size_t { - elem_array_head_size = - (sizeof(elem_array_head) % alignof(std::max_align_t)) ? - ((sizeof(elem_array_head) / alignof(std::max_align_t)) + 1) * alignof(std::max_align_t) : - sizeof(elem_array_head) +template +constexpr std::size_t elem_array_head_size = + (sizeof(elem_array_head) % alignof(std::max_align_t)) ? + ((sizeof(elem_array_head) / alignof(std::max_align_t)) + 1) * alignof(std::max_align_t) : + sizeof(elem_array_head); + +struct elem_head { + std::atomic> rc_ { 0 }; // read counter }; -template -class elem_array : private elem_array_head { - struct head_t { - std::atomic rc_ { 0 }; // read counter - }; - +template +class elem_array : private elem_array_head { public: + using base_t = elem_array_head; + using head_t = elem_head; + enum : std::size_t { - head_size = elem_array_head_size, + head_size = elem_array_head_size, data_size = DataSize, - elem_max = std::numeric_limits::max() + 1, // default is 255 + 1 + elem_max = std::numeric_limits::max() + 1, // default is 255 + 1 elem_size = sizeof(head_t) + DataSize, block_size = elem_size * elem_max }; @@ -54,21 +81,8 @@ private: return block_; } - static elem_t* elem(void* ptr) { - return reinterpret_cast(static_cast(ptr) - sizeof(head_t)); - } - - elem_t* elem(ui_t i) { - return elem_start() + i; - } - - static ui_t index_of(uc_t c) { - return static_cast(c); - } - - ui_t index_of(elem_t* el) { - return static_cast(el - elem_start()); - } + static elem_t* elem(void* ptr) { return reinterpret_cast(static_cast(ptr) - sizeof(head_t)); } + elem_t* elem(u1_t i ) { return elem_start() + i; } public: elem_array(void) = default; @@ -78,48 +92,35 @@ public: elem_array(elem_array&&) = delete; elem_array& operator=(elem_array&&) = delete; - std::size_t connect(void) { - return cc_.fetch_add(1, std::memory_order_release); - } - - std::size_t disconnect(void) { - return cc_.fetch_sub(1, std::memory_order_release); - } - - std::size_t conn_count(void) const { - return cc_.load(std::memory_order_consume); - } + using base_t::connect; + using base_t::disconnect; + using base_t::conn_count; void* acquire(void) { - while (lc_.exchange(1, std::memory_order_acquire)) { - std::this_thread::yield(); - } - elem_t* el = elem(index_of(wt_.load(std::memory_order_relaxed))); + elem_t* el = elem(base_t::acquire()); // check all consumers have finished reading while(1) { - std::uint32_t expected = 0; + uint_t<32> expected = 0; if (el->head_.rc_.compare_exchange_weak( expected, - static_cast(cc_.load(std::memory_order_relaxed)), + static_cast>(conn_count()), std::memory_order_release)) { break; } std::this_thread::yield(); - std::atomic_thread_fence(std::memory_order_acquire); } return el->data_; } void commit(void* /*ptr*/) { - wt_.fetch_add(1, std::memory_order_relaxed); - lc_.store(0, std::memory_order_release); + base_t::commit(); } - uc_t cursor(void) const { - return wt_.load(std::memory_order_consume); + u2_t cursor(void) const { + return wt_.load(std::memory_order_acquire); } - void* take(uc_t cursor) { + void* take(u2_t cursor) { return elem(index_of(cursor))->data_; } diff --git a/include/def.h b/include/def.h index 67b4785..4fd1730 100644 --- a/include/def.h +++ b/include/def.h @@ -10,6 +10,16 @@ namespace ipc { using byte_t = std::uint8_t; +template +struct uint; + +template <> struct uint<8 > { using type = std::uint8_t ; }; +template <> struct uint<16> { using type = std::uint16_t; }; +template <> struct uint<32> { using type = std::uint32_t; }; + +template +using uint_t = typename uint::type; + // constants enum : std::size_t { diff --git a/test/test_circ.cpp b/test/test_circ.cpp index f8f953d..cff6abb 100644 --- a/test/test_circ.cpp +++ b/test/test_circ.cpp @@ -39,6 +39,8 @@ private slots: using cq_t = ipc::circ::elem_array<12>; cq_t* cq__; +constexpr int LoopCount = 1000000; + void Unit::initTestCase(void) { TestSuite::initTestCase(); cq__ = new cq_t; @@ -233,7 +235,7 @@ struct test_cq> { } }; -template +template void test_prod_cons(T* cq) { test_cq tcq { cq }; @@ -281,7 +283,7 @@ void test_prod_cons(T* cq) { for (auto& t : consumers) t.join(); } -template +template void test_prod_cons(void) { test_prod_cons(cq__); }