diff --git a/include/circ_elem_array.h b/include/circ_elem_array.h index 38173f8..5b0d77f 100644 --- a/include/circ_elem_array.h +++ b/include/circ_elem_array.h @@ -8,8 +8,8 @@ #include "rw_lock.h" namespace ipc { -namespace circ { +namespace circ { namespace detail { using u1_t = uint_t<8>; @@ -40,30 +40,28 @@ elem_t* elem_of(void* ptr) noexcept { } } // namespace detail +} // namespace circ //////////////////////////////////////////////////////////////// /// producer-consumer policies //////////////////////////////////////////////////////////////// -template -struct prod_cons; - template <> -struct prod_cons { - std::atomic rd_ { 0 }; // read index - std::atomic wt_ { 0 }; // write index +struct prod_cons { + std::atomic rd_ { 0 }; // read index + std::atomic wt_ { 0 }; // write index template - constexpr static std::size_t elem_param = DataSize - sizeof(detail::elem_head); + constexpr static std::size_t elem_param = DataSize - sizeof(circ::detail::elem_head); - constexpr detail::u2_t cursor() const noexcept { + constexpr circ::detail::u2_t cursor() const noexcept { return 0; } template - bool push(E* /*elems*/, F&& f, detail::elem_t* elem_start) { - auto cur_wt = detail::index_of(wt_.load(std::memory_order_acquire)); - if (cur_wt == detail::index_of(rd_.load(std::memory_order_relaxed) - 1)) { + bool push(E* /*elems*/, F&& f, circ::detail::elem_t* elem_start) { + auto cur_wt = circ::detail::index_of(wt_.load(std::memory_order_acquire)); + if (cur_wt == circ::detail::index_of(rd_.load(std::memory_order_relaxed) - 1)) { return false; // full } std::forward(f)(elem_start + cur_wt); @@ -72,9 +70,9 @@ struct prod_cons { } template - bool pop(E* /*elems*/, detail::u2_t& /*cur*/, F&& f, detail::elem_t* elem_start) noexcept { - auto cur_rd = detail::index_of(rd_.load(std::memory_order_acquire)); - if (cur_rd == detail::index_of(wt_.load(std::memory_order_relaxed))) { + bool pop(E* /*elems*/, circ::detail::u2_t& /*cur*/, F&& f, circ::detail::elem_t* elem_start) noexcept { + auto cur_rd = circ::detail::index_of(rd_.load(std::memory_order_acquire)); + if (cur_rd == circ::detail::index_of(wt_.load(std::memory_order_relaxed))) { return false; // empty } std::forward(f)(elem_start + cur_rd); @@ -84,19 +82,19 @@ struct prod_cons { }; template <> -struct prod_cons - : prod_cons { +struct prod_cons + : prod_cons { template - bool pop(E* /*elems*/, detail::u2_t& /*cur*/, F&& f, detail::elem_t* elem_start) noexcept { - byte_t buff[sizeof(detail::elem_t)]; + bool pop(E* /*elems*/, circ::detail::u2_t& /*cur*/, F&& f, circ::detail::elem_t* elem_start) noexcept { + byte_t buff[sizeof(circ::detail::elem_t)]; for (unsigned k = 0;;) { auto cur_rd = rd_.load(std::memory_order_acquire); - if (detail::index_of(cur_rd) == - detail::index_of(wt_.load(std::memory_order_relaxed))) { + if (circ::detail::index_of(cur_rd) == + circ::detail::index_of(wt_.load(std::memory_order_relaxed))) { return false; // empty } - std::memcpy(buff, elem_start + detail::index_of(cur_rd), sizeof(buff)); + std::memcpy(buff, elem_start + circ::detail::index_of(cur_rd), sizeof(buff)); if (rd_.compare_exchange_weak(cur_rd, cur_rd + 1, std::memory_order_release)) { std::forward(f)(buff); return true; @@ -107,18 +105,18 @@ struct prod_cons }; template <> -struct prod_cons - : prod_cons { +struct prod_cons + : prod_cons { - std::atomic ct_ { 0 }; // commit index + std::atomic ct_ { 0 }; // commit index template - bool push(E* /*elems*/, F&& f, detail::elem_t* elem_start) { - detail::u2_t cur_ct, nxt_ct; + bool push(E* /*elems*/, F&& f, circ::detail::elem_t* elem_start) { + circ::detail::u2_t cur_ct, nxt_ct; while(1) { cur_ct = ct_.load(std::memory_order_acquire); - if (detail::index_of(nxt_ct = cur_ct + 1) == - detail::index_of(rd_.load(std::memory_order_relaxed))) { + if (circ::detail::index_of(nxt_ct = cur_ct + 1) == + circ::detail::index_of(rd_.load(std::memory_order_relaxed))) { return false; // full } if (ct_.compare_exchange_weak(cur_ct, nxt_ct, std::memory_order_relaxed)) { @@ -126,7 +124,7 @@ struct prod_cons } std::this_thread::yield(); } - std::forward(f)(elem_start + detail::index_of(cur_ct)); + std::forward(f)(elem_start + circ::detail::index_of(cur_ct)); while(1) { auto exp_wt = cur_ct; if (wt_.compare_exchange_weak(exp_wt, nxt_ct, std::memory_order_release)) { @@ -139,8 +137,8 @@ struct prod_cons }; template <> -struct prod_cons { - std::atomic wt_ { 0 }; // write index +struct prod_cons { + std::atomic wt_ { 0 }; // write index template constexpr static std::size_t elem_param = DataSize; @@ -149,17 +147,17 @@ struct prod_cons { std::atomic may not have value_type. See: https://stackoverflow.com/questions/53648614/what-happened-to-stdatomicxvalue-type */ - using rc_t = decltype(detail::elem_head::rc_.load()); + using rc_t = decltype(circ::detail::elem_head::rc_.load()); - detail::u2_t cursor() const noexcept { + circ::detail::u2_t cursor() const noexcept { return wt_.load(std::memory_order_acquire); } template - bool push(E* elems, F&& f, detail::elem_t* elem_start) { + bool push(E* elems, F&& f, circ::detail::elem_t* elem_start) { auto conn_cnt = elems->conn_count(); // acquire if (conn_cnt == 0) return false; - auto el = elem_start + detail::index_of(wt_.load(std::memory_order_relaxed)); + auto el = elem_start + circ::detail::index_of(wt_.load(std::memory_order_relaxed)); // check all consumers have finished reading this element while(1) { rc_t expected = 0; @@ -177,9 +175,9 @@ struct prod_cons { } template - bool pop(E* /*elems*/, detail::u2_t& cur, F&& f, detail::elem_t* elem_start) noexcept { + bool pop(E* /*elems*/, circ::detail::u2_t& cur, F&& f, circ::detail::elem_t* elem_start) noexcept { if (cur == cursor()) return false; // acquire - auto el = elem_start + detail::index_of(cur++); + auto el = elem_start + circ::detail::index_of(cur++); std::forward(f)(el->data_); for (unsigned k = 0;;) { rc_t cur_rc = el->head_.rc_.load(std::memory_order_acquire); @@ -196,18 +194,18 @@ struct prod_cons { }; template <> -struct prod_cons - : prod_cons { +struct prod_cons + : prod_cons { - std::atomic ct_ { 0 }; // commit index + std::atomic ct_ { 0 }; // commit index template - bool push(E* elems, F&& f, detail::elem_t* elem_start) { + bool push(E* elems, F&& f, circ::detail::elem_t* elem_start) { auto conn_cnt = elems->conn_count(); // acquire if (conn_cnt == 0) return false; - detail::u2_t cur_ct = ct_.fetch_add(1, std::memory_order_relaxed), - nxt_ct = cur_ct + 1; - auto el = elem_start + detail::index_of(cur_ct); + circ::detail::u2_t cur_ct = ct_.fetch_add(1, std::memory_order_relaxed), + nxt_ct = cur_ct + 1; + auto el = elem_start + circ::detail::index_of(cur_ct); // check all consumers have finished reading this element while(1) { rc_t expected = 0; @@ -231,6 +229,11 @@ struct prod_cons } }; +template +using prod_cons_circ = prod_cons; + +namespace circ { + //////////////////////////////////////////////////////////////// /// element-array implementation //////////////////////////////////////////////////////////////// diff --git a/include/def.h b/include/def.h index 46b22a4..a775a04 100644 --- a/include/def.h +++ b/include/def.h @@ -31,6 +31,11 @@ enum : std::size_t { data_length = 16 }; +enum class organ { // data structure organization + linked, + cyclic +}; + enum class relat { // multiplicity of the relationship single, multi @@ -41,6 +46,11 @@ enum class trans { // transmission broadcast }; +// producer-consumer policy declaration + +template +struct prod_cons; + // concept helpers template diff --git a/include/ipc.h b/include/ipc.h index f30c472..c9ede7f 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -7,7 +7,7 @@ #include "def.h" #include "buffer.h" #include "shm.h" -#include "circ_queue.h" +#include "queue.h" namespace ipc { @@ -138,8 +138,7 @@ public: * (one producer/server/sender to multi consumers/clients/receivers) */ using route = channel_ipml + ipc::queue, ipc::prod_cons_circ >>; /* @@ -151,8 +150,7 @@ using route = channel_ipml + ipc::queue, ipc::prod_cons_circ >>; } // namespace ipc diff --git a/include/circ_queue.h b/include/queue.h similarity index 93% rename from include/circ_queue.h rename to include/queue.h index ffd2837..8da4fc4 100644 --- a/include/circ_queue.h +++ b/include/queue.h @@ -14,13 +14,12 @@ #include "circ_elem_array.h" namespace ipc { -namespace circ { template > + typename Policy = ipc::prod_cons_circ> class queue { public: - using array_t = elem_array; + using array_t = circ::elem_array; using policy_t = typename array_t::policy_t; private: @@ -113,5 +112,4 @@ public: } }; -} // namespace circ } // namespace ipc diff --git a/src/ipc.cpp b/src/ipc.cpp index 8cee789..cdd95fe 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -27,7 +27,7 @@ template