From 1565ae0eafadabbd6ab20d4d2c5d79229903ac74 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Sun, 2 Apr 2023 21:00:55 +0800 Subject: [PATCH] upd: [concur] adjust and optimize the comments, as well as some other details. --- include/libconcur/concurrent.h | 68 +++++++++++++++++----------------- include/libconcur/element.h | 37 ++++++++++++++---- 2 files changed, 64 insertions(+), 41 deletions(-) diff --git a/include/libconcur/concurrent.h b/include/libconcur/concurrent.h index f536e0b..10a9d88 100644 --- a/include/libconcur/concurrent.h +++ b/include/libconcur/concurrent.h @@ -8,6 +8,7 @@ #include #include +#include #include #include "libimp/span.h" @@ -17,7 +18,7 @@ LIBCONCUR_NAMESPACE_BEG_ -/// \brief The queue index type. +/// \typedef The queue index type. using index_t = std::uint32_t; /// \brief Multiplicity of the relationship. @@ -31,7 +32,12 @@ class multi {}; /// \brief Transmission mode namespace trans { -class unicast {}; +/// \brief In this transmission mode, the message transmission is similar to a queue. +/// When the receiving side is not timely enough, the sending side will be unable to write data. +class unicast {}; + +/// \brief In this transmission mode, the message will be perceived by each receiver. +/// When the receiving side is not timely enough, the sending side will overwrite unread data. class broadcast {}; } // namespace trans @@ -56,7 +62,7 @@ using is_context = decltype(typename std::enable_if> constexpr index_t trunc_index(C const &ctx, index_t idx) noexcept { - /// \remark `circ_size == 2^N` => `idx & (circ_size - 1)` + // `circ_size == 2^N` => `idx & (circ_size - 1)` return ctx.valid() ? (idx % ctx.circ_size) : 0; } @@ -81,8 +87,8 @@ template <> struct producer { struct context_impl { - /// \brief Write index. - alignas(cache_line_size) index_t w_idx {0}; + index_t w_idx {0}; ///< write index + private: padding ___; }; template { auto w_cur = trunc_index(ctx, w_idx); auto &elem = elems[w_cur]; auto f_ct = elem.get_flag(); - /// \remark Verify index. + // Verify index. if ((f_ct != state::invalid_value) && (f_ct != w_idx)) { return false; // full } - /// \remark Get a valid index and iterate backwards. + // Get a valid index and iterate backwards. ctx.w_idx += 1; - /// \remark Set data & flag. + // Set data & flag. elem.set_data(std::forward(src)); elem.set_flag(static_cast(~w_idx)); return true; @@ -112,8 +118,8 @@ template <> struct producer { struct context_impl { - /// \brief Write index. - alignas(cache_line_size) std::atomic w_idx {0}; + std::atomic w_idx {0}; ///< write index + private: padding ___; }; template { auto w_cur = trunc_index(ctx, w_idx); auto &elem = elems[w_cur]; auto f_ct = elem.get_flag(); - /// \remark Verify index. + // Verify index. if ((f_ct != state::invalid_value) && (f_ct != w_idx)) { return false; // full } - /// \remark Get a valid index and iterate backwards. + // Get a valid index and iterate backwards. if (!ctx.w_idx.compare_exchange_weak(w_idx, w_idx + 1, std::memory_order_acq_rel)) { continue; } - /// \remark Set data & flag. + // Set data & flag. elem.set_data(std::forward(src)); elem.set_flag(static_cast(~w_idx)); return true; @@ -147,8 +153,8 @@ template <> struct consumer { struct context_impl { - /// \brief Read index. - alignas(cache_line_size) index_t r_idx {0}; + index_t r_idx {0}; ///< read index + private: padding ___; }; template { auto r_cur = trunc_index(ctx, r_idx); auto &elem = elems[r_cur]; auto f_ct = elem.get_flag(); - /// \remark Verify index. + // Verify index. if (f_ct != static_cast(~r_idx)) { return false; // empty } - /// \remark Get a valid index and iterate backwards. + // Get a valid index and iterate backwards. ctx.r_idx += 1; - /// \remark Get data & set flag. - des = elem.get_data(); - elem.set_flag(r_idx + static_cast(elems.size())); + // Get data & set flag. + des = LIBCONCUR::get(elem); + elem.set_flag(r_idx + static_cast(elems.size())/*avoid overflow*/); return true; } }; @@ -177,8 +183,8 @@ template <> struct consumer { struct context_impl { - /// \brief Read index. - alignas(cache_line_size) std::atomic r_idx {0}; + std::atomic r_idx {0}; ///< read index + private: padding ___; }; template { auto r_cur = trunc_index(ctx, r_idx); auto &elem = elems[r_cur]; auto f_ct = elem.get_flag(); - /// \remark Verify index. + // Verify index. if (f_ct != static_cast(~r_idx)) { return false; // empty } - /// \remark Get a valid index and iterate backwards. + // Get a valid index and iterate backwards. if (!ctx.r_idx.compare_exchange_weak(r_idx, r_idx + 1, std::memory_order_acq_rel)) { continue; } - /// \remark Get data & set flag. - des = elem.get_data(); - elem.set_flag(r_idx + static_cast(elems.size())); + // Get data & set flag. + des = LIBCONCUR::get(elem); + elem.set_flag(r_idx + static_cast(elems.size())/*avoid overflow*/); return true; } } @@ -220,12 +226,8 @@ template <> struct producer { }; -/// \brief Single-read consumer model implementation. -template <> -struct consumer { -}; - /// \brief Multi-read consumer model implementation. +// Single-read consumer model is not required. template <> struct consumer { }; @@ -254,7 +256,7 @@ struct prod_cons : producer : circ_size(static_cast(elems.size())) {} constexpr bool valid() const noexcept { - /// \remark circ_size must be a power of two. + // circ_size must be a power of two. return (circ_size > 1) && ((circ_size & (circ_size - 1)) == 0); } }; diff --git a/include/libconcur/element.h b/include/libconcur/element.h index 8216a68..e2e4823 100644 --- a/include/libconcur/element.h +++ b/include/libconcur/element.h @@ -8,32 +8,50 @@ #include #include -#include // std::numeric_limits #include #include #include "libimp/detect_plat.h" #include "libimp/log.h" +#include "libimp/byte.h" +#include "libimp/generic.h" #include "libconcur/def.h" LIBCONCUR_NAMESPACE_BEG_ namespace state { -/// \brief The state flag type for the queue element. +/// \typedef The state flag type for the queue element. using flag_t = std::uint64_t; enum : flag_t { /// \brief The invalid state value. - invalid_value = (std::numeric_limits::max)(), + invalid_value = ~flag_t(0), }; } // namespace state +/// \brief Define the padding type. +template +using padding = std::array<::LIBIMP::byte, (cache_line_size - sizeof(T))>; + +/** + * \class template element + * \brief User-defined type element wrapper. + * Wrapper for wrapping user-defined types as elements. + * + * @tparam T - User-defined type. + */ template class element { + + template + friend auto get(E &&elem) noexcept; + /// \brief Committed flag. - alignas(cache_line_size) std::atomic f_ct_; + std::atomic f_ct_; + padding ___; + /// \brief The user data segment. T data_; @@ -42,6 +60,8 @@ class element { element &operator=(element const &) = delete; public: + using value_type = T; + template element(A &&... args) noexcept(noexcept(T{std::forward(args)...})) @@ -60,10 +80,6 @@ public: } } - T &&get_data() noexcept { - return std::move(data_); - } - void set_flag(state::flag_t flag) noexcept { f_ct_.store(flag, std::memory_order_release); } @@ -73,4 +89,9 @@ public: } }; +template +auto get(E &&elem) noexcept { + return static_cast::type::value_type>>(elem.data_); +} + LIBCONCUR_NAMESPACE_END_