diff --git a/include/libconcur/concurrent.h b/include/libconcur/concurrent.h index cbc7169..23b330d 100644 --- a/include/libconcur/concurrent.h +++ b/include/libconcur/concurrent.h @@ -12,6 +12,7 @@ #include #include "libimp/span.h" +#include "libimp/generic.h" #include "libconcur/def.h" #include "libconcur/element.h" @@ -21,6 +22,71 @@ LIBCONCUR_NAMESPACE_BEG_ /// \typedef The queue index type. using index_t = std::uint32_t; +namespace detail_concurrent { + +template +struct has_header : std::false_type {}; +template +struct has_header> + : std::true_type {}; + +template +struct has_header_impl : std::false_type {}; +template +struct has_header_impl> + : std::true_type {}; + +template +struct has_context : std::false_type {}; +template +struct has_context> + : std::true_type {}; + +template +struct has_context_impl : std::false_type {}; +template +struct has_context_impl> + : std::true_type {}; + +template {} + , bool = has_header_impl{}> +struct traits_header { + struct header {}; +}; + +template +struct traits_header { + using header = typename T::header; +}; + +template +struct traits_header { + using header = typename T::header_impl; +}; + +template {} + , bool = has_context_impl{}> +struct traits_context { + struct context {}; +}; + +template +struct traits_context { + using context = typename T::context; +}; + +template +struct traits_context { + using context = typename T::context_impl; +}; + +} // namespace detail_concurrent + +/// \typedef Utility template for extracting object type internal traits. +template +struct traits : detail_concurrent::traits_header + , detail_concurrent::traits_context {}; + /// \brief Multiplicity of the relationship. namespace relation { @@ -91,10 +157,10 @@ struct producer { private: padding ___; }; - template = true, is_convertible = true> - static bool enqueue(::LIBIMP::span> elems, H &hdr, U &&src) noexcept { + 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); auto &elem = elems[w_cur]; @@ -122,10 +188,10 @@ struct producer { private: padding ___; }; - template = true, is_convertible = true> - static bool enqueue(::LIBIMP::span> elems, H &hdr, U &&src) noexcept { + 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 (;;) { auto w_cur = trunc_index(hdr, w_idx); @@ -157,10 +223,10 @@ struct consumer { private: padding ___; }; - template = true, is_convertible = true> - static bool dequeue(::LIBIMP::span> elems, H &hdr, U &des) noexcept { + static bool dequeue(::LIBIMP::span> elems, H &hdr, C &/*ctx*/, U &des) noexcept { auto r_idx = hdr.r_idx; auto r_cur = trunc_index(hdr, r_idx); auto &elem = elems[r_cur]; @@ -187,10 +253,10 @@ struct consumer { private: padding ___; }; - template = true, is_convertible = true> - static bool dequeue(::LIBIMP::span> elems, H &hdr, U &des) noexcept { + static bool dequeue(::LIBIMP::span> elems, H &hdr, C &/*ctx*/, U &des) noexcept { auto r_idx = hdr.r_idx.load(std::memory_order_acquire); for (;;) { auto r_cur = trunc_index(hdr, r_idx); @@ -252,7 +318,7 @@ struct prod_cons : producer : circ_size(cs) {} template - constexpr header(::LIBIMP::span> elems) noexcept + constexpr header(::LIBIMP::span> const &elems) noexcept : circ_size(static_cast(elems.size())) {} constexpr bool valid() const noexcept { diff --git a/test/concur/test_concur_concurrent.cpp b/test/concur/test_concur_concurrent.cpp index e32d7a8..ac6446b 100644 --- a/test/concur/test_concur_concurrent.cpp +++ b/test/concur/test_concur_concurrent.cpp @@ -99,8 +99,9 @@ void test_concur(std::size_t np, std::size_t nc, std::size_t k) { concur::element circ[32] {}; PC pc; - typename PC::header ctx {imp::make_span(circ)}; - ASSERT_TRUE(ctx.valid()); + typename concur::traits::header hdr {imp::make_span(circ)}; + typename concur::traits::context ctx {}; + ASSERT_TRUE(hdr.valid()); std::atomic sum {0}; std::atomic running {np}; @@ -108,7 +109,7 @@ void test_concur(std::size_t np, std::size_t nc, std::size_t k) { auto prod_call = [&](std::size_t n) { for (std::uint32_t i = 1; i <= loop_size; ++i) { std::this_thread::yield(); - while (!pc.enqueue(imp::make_span(circ), ctx, i)) { + while (!pc.enqueue(imp::make_span(circ), hdr, ctx, i)) { std::this_thread::yield(); } if (i % (loop_size / 10) == 0) { @@ -121,7 +122,7 @@ void test_concur(std::size_t np, std::size_t nc, std::size_t k) { for (;;) { std::this_thread::yield(); std::uint64_t i; - while (!pc.dequeue(imp::make_span(circ), ctx, i)) { + while (!pc.dequeue(imp::make_span(circ), hdr, ctx, i)) { if (running == 0) return; std::this_thread::yield(); }