diff --git a/include/libconcur/concurrent.h b/include/libconcur/concurrent.h index 63719a6..aaea18a 100644 --- a/include/libconcur/concurrent.h +++ b/include/libconcur/concurrent.h @@ -50,8 +50,8 @@ template struct has_context_impl> : std::true_type {}; -template {} - , bool = has_header_impl{}> +template ::value + , bool = has_header_impl::value> struct traits_header { struct header {}; }; @@ -66,8 +66,8 @@ struct traits_header { using header = typename T::header_impl; }; -template {} - , bool = has_context_impl{}> +template ::value + , bool = has_context_impl::value> struct traits_context { struct context {}; }; @@ -112,13 +112,20 @@ class broadcast {}; /// \brief Determines whether type T can be implicitly converted to type U. template -using is_convertible = typename std::enable_if::value, bool>::type; +using convertible = std::enable_if_t::value, bool>; /// \brief Check whether the elems header type is valid. +template +struct is_elems_header : std::false_type {}; template -using is_elems_header = decltype( - std::declval() % std::declval().circ_size, - std::enable_if_t().valid()), bool>::value, bool>{}); +struct is_elems_header() % std::declval().circ_size), + std::enable_if_t().valid()), bool>::value>>> + : std::true_type {}; + +/// \brief Utility template for verifying elems header type. +template +using verify_elems_header = std::enable_if_t::value, bool>; /** * \brief Calculate the corresponding queue position modulo the index value. @@ -128,7 +135,7 @@ using is_elems_header = decltype( * \param idx a elems array index * \return index_t - a corresponding queue position */ -template = true> +template = true> constexpr index_t trunc_index(H const &hdr, index_t idx) noexcept { // `circ_size == 2^N` => `idx & (circ_size - 1)` return hdr.valid() ? (idx % hdr.circ_size) : 0; @@ -160,8 +167,8 @@ struct producer { }; template = true, - is_convertible = true> + verify_elems_header = true, + convertible = true> static bool enqueue(::LIBIMP::span> elems, H &hdr, C &/*ctx*/, U &&src) noexcept { auto w_idx = hdr.w_idx; auto w_cur = trunc_index(hdr, w_idx); @@ -191,8 +198,8 @@ struct producer { }; template = true, - is_convertible = true> + verify_elems_header = true, + convertible = true> static bool enqueue(::LIBIMP::span> elems, H &hdr, C &/*ctx*/, U &&src) noexcept { auto w_idx = hdr.w_idx.load(std::memory_order_acquire); for (;;) { @@ -226,8 +233,8 @@ struct consumer { }; template = true, - is_convertible = true, + verify_elems_header = true, + convertible = true, std::enable_if_t::value, bool> = true> static bool dequeue(::LIBIMP::span> elems, H &hdr, C &/*ctx*/, U &des) noexcept { auto r_idx = hdr.r_idx; @@ -257,8 +264,8 @@ struct consumer { }; template = true, - is_convertible = true, + verify_elems_header = true, + convertible = true, std::enable_if_t::value, bool> = true> static bool dequeue(::LIBIMP::span> elems, H &hdr, C &/*ctx*/, U &des) noexcept { auto r_idx = hdr.r_idx.load(std::memory_order_acquire); @@ -303,8 +310,8 @@ struct producer { }; template = true, - is_convertible = true> + verify_elems_header = true, + convertible = true> static bool enqueue(::LIBIMP::span> elems, H &hdr, C &/*ctx*/, U &&src) noexcept { auto w_idx = hdr.w_idx.load(std::memory_order_acquire); auto w_beg = hdr.w_beg.load(std::memory_order_relaxed); @@ -341,8 +348,8 @@ struct producer { }; template = true, - is_convertible = true> + verify_elems_header = true, + convertible = true> static bool enqueue(::LIBIMP::span> elems, H &hdr, C &/*ctx*/, U &&src) noexcept { auto w_flags = hdr.w_flags.load(std::memory_order_acquire); index_t w_idx; @@ -377,13 +384,11 @@ private: } constexpr static index_t get_begin(state::flag_t flags) noexcept { - constexpr auto index_bits = sizeof(index_t) * CHAR_BIT; - return index_t(flags >> index_bits); + return index_t(flags >> (sizeof(index_t) * CHAR_BIT)); } constexpr static state::flag_t make_flags(index_t idx, index_t beg) noexcept { - constexpr auto index_bits = sizeof(index_t) * CHAR_BIT; - return state::flag_t(idx) | (state::flag_t(beg) << index_bits); + return state::flag_t(idx) | (state::flag_t(beg) << (sizeof(index_t) * CHAR_BIT)); } }; @@ -398,8 +403,8 @@ struct consumer { }; template = true, - is_convertible = true, + verify_elems_header = true, + convertible = true, std::enable_if_t::value, bool> = true> static bool dequeue(::LIBIMP::span> elems, H &hdr, C &ctx, U &des) noexcept { index_t w_idx, w_beg; diff --git a/test/concur/test_concur_concurrent.cpp b/test/concur/test_concur_concurrent.cpp index 8c919b7..995560b 100644 --- a/test/concur/test_concur_concurrent.cpp +++ b/test/concur/test_concur_concurrent.cpp @@ -232,7 +232,7 @@ void test_broadcast(std::size_t np, std::size_t nc) { typename concur::traits::header hdr {imp::make_span(circ)}; ASSERT_TRUE(hdr.valid()); - constexpr static std::uint32_t loop_size = 100'0000; + constexpr static std::uint32_t loop_size = 10'0000; std::atomic sum {0}; std::atomic running {np}; @@ -272,12 +272,12 @@ void test_broadcast(std::size_t np, std::size_t nc) { std::this_thread::yield(); } // The v.i variable always increases. - if (last_i[v.n] >= v.i) { + if (last_i[(std::size_t)v.n] >= v.i) { continue; } - last_i[v.n] = v.i; + last_i[(std::size_t)v.n] = v.i; sum += v.i; - ++counters[v.n]; + ++counters[(std::size_t)v.n]; } };