diff --git a/include/beman/execution/detail/as_tuple.hpp b/include/beman/execution/detail/as_tuple.hpp index 1b9726c0..1b7baa21 100644 --- a/include/beman/execution/detail/as_tuple.hpp +++ b/include/beman/execution/detail/as_tuple.hpp @@ -9,8 +9,16 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { +/*! + * \brief Turn a completion signatures into a std::tuple type. + * \internal + */ template struct as_tuple; +/*! + * \brief The actual operational partial specialization of as_tuple. + * \internal + */ template struct as_tuple { using type = ::beman::execution::detail::decayed_tuple; diff --git a/include/beman/execution/detail/associate.hpp b/include/beman/execution/detail/associate.hpp index f89adf6d..d8b76717 100644 --- a/include/beman/execution/detail/associate.hpp +++ b/include/beman/execution/detail/associate.hpp @@ -106,13 +106,15 @@ struct impls_for : ::beman::execution::detail::default_impls { struct op_state { using sop_t = op_t; using sscope_token = scope_token; + struct assoc_t { + sscope_token tok; + sop_t op; + }; + bool associated{false}; union { Receiver* rcvr; - struct { - sscope_token tok; - sop_t op; - } assoc; + assoc_t assoc; }; explicit op_state(Receiver& r) noexcept : rcvr(::std::addressof(r)) {} explicit op_state(sscope_token tk, wrap_sender&& sndr, Receiver& r) try diff --git a/include/beman/execution/detail/counting_scope_base.hpp b/include/beman/execution/detail/counting_scope_base.hpp index 56ca4f5e..b902f0b8 100644 --- a/include/beman/execution/detail/counting_scope_base.hpp +++ b/include/beman/execution/detail/counting_scope_base.hpp @@ -13,7 +13,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { -struct counting_scope_base; +class counting_scope_base; } // ---------------------------------------------------------------------------- @@ -71,7 +71,7 @@ class beman::execution::detail::counting_scope_base : ::beman::execution::detail // ---------------------------------------------------------------------------- -beman::execution::detail::counting_scope_base::~counting_scope_base() { +inline beman::execution::detail::counting_scope_base::~counting_scope_base() { ::std::lock_guard kerberos(this->mutex); switch (this->state) { default: @@ -83,7 +83,7 @@ beman::execution::detail::counting_scope_base::~counting_scope_base() { } } -auto beman::execution::detail::counting_scope_base::close() noexcept -> void { +inline auto beman::execution::detail::counting_scope_base::close() noexcept -> void { switch (this->state) { default: break; @@ -99,12 +99,12 @@ auto beman::execution::detail::counting_scope_base::close() noexcept -> void { } } -auto beman::execution::detail::counting_scope_base::add_node(node* n, ::std::lock_guard<::std::mutex>&) noexcept +inline auto beman::execution::detail::counting_scope_base::add_node(node* n, ::std::lock_guard<::std::mutex>&) noexcept -> void { n->next = std::exchange(this->head, n); } -auto beman::execution::detail::counting_scope_base::try_associate() noexcept -> bool { +inline auto beman::execution::detail::counting_scope_base::try_associate() noexcept -> bool { ::std::lock_guard lock(this->mutex); switch (this->state) { default: @@ -118,7 +118,8 @@ auto beman::execution::detail::counting_scope_base::try_associate() noexcept -> return true; } } -auto beman::execution::detail::counting_scope_base::disassociate() noexcept -> void { + +inline auto beman::execution::detail::counting_scope_base::disassociate() noexcept -> void { { ::std::lock_guard lock(this->mutex); if (0u < --this->count) @@ -128,7 +129,7 @@ auto beman::execution::detail::counting_scope_base::disassociate() noexcept -> v this->complete(); } -auto beman::execution::detail::counting_scope_base::complete() noexcept -> void { +inline auto beman::execution::detail::counting_scope_base::complete() noexcept -> void { node* current{[this] { ::std::lock_guard lock(this->mutex); return ::std::exchange(this->head, nullptr); @@ -138,7 +139,7 @@ auto beman::execution::detail::counting_scope_base::complete() noexcept -> void } } -auto beman::execution::detail::counting_scope_base::start_node(node* n) -> void { +inline auto beman::execution::detail::counting_scope_base::start_node(node* n) -> void { ::std::lock_guard kerberos(this->mutex); switch (this->state) { case ::beman::execution::detail::counting_scope_base::state_t::unused: diff --git a/include/beman/execution/detail/schedule_from.hpp b/include/beman/execution/detail/schedule_from.hpp index 1a6fb95a..8dc26d91 100644 --- a/include/beman/execution/detail/schedule_from.hpp +++ b/include/beman/execution/detail/schedule_from.hpp @@ -4,36 +4,37 @@ #ifndef INCLUDED_BEMAN_EXECUTION_DETAIL_SCHEDULE_FROM #define INCLUDED_BEMAN_EXECUTION_DETAIL_SCHEDULE_FROM +#include #include -#include #include #include #include #include #include -#include #include +#include #include #include #include #include #include #include +#include #include #include #include +#include #include #include -#include #include +#include #include -#include #include +#include #include #include #include #include -#include #include #include @@ -43,23 +44,6 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { -/*! - * \brief Turn a completion signatures into a std::tuple type. - * \internal - */ -template -struct as_tuple; -/*! - * \brief The actual operational partial specialization of as_tuple. - * \internal - */ -template -struct as_tuple { - using type = ::beman::execution::detail::decayed_tuple; -}; -template -using as_tuple_t = typename as_tuple::type; - struct schedule_from_t { template <::beman::execution::scheduler Scheduler, ::beman::execution::sender Sender> auto operator()(Scheduler&& scheduler, Sender&& sender) const { diff --git a/include/beman/execution/detail/sender_decompose.hpp b/include/beman/execution/detail/sender_decompose.hpp index ae3258dd..0b8ab53d 100644 --- a/include/beman/execution/detail/sender_decompose.hpp +++ b/include/beman/execution/detail/sender_decompose.hpp @@ -42,7 +42,7 @@ auto get_sender_data(Sender&& sender) { //-dk:TODO should use a dynamic/language approach: auto&& [tag, data, ... children] = sender; return sender_meta>; -#endif +#else using sender_type = ::std::remove_cvref_t; static constexpr ::beman::execution::detail::sender_convert_to_any_t at{}; @@ -68,10 +68,11 @@ auto get_sender_data(Sender&& sender) { return ::beman::execution::detail::sender_data{tag, data, ::std::tie(c0)}; } else if constexpr (requires { sender_type{at, at}; }) { auto&& [tag, data] = sender; - return ::beman::execution::detail::sender_data{tag, data, ::std::tuple<>()}; + return ::beman::execution::detail::sender_data{tag, data, ::std::tuple<>{}}; } else { return ::beman::execution::detail::sender_meta{}; } +#endif } template diff --git a/include/beman/execution/detail/stop_when.hpp b/include/beman/execution/detail/stop_when.hpp index 0ec7937d..cd3ef5b8 100644 --- a/include/beman/execution/detail/stop_when.hpp +++ b/include/beman/execution/detail/stop_when.hpp @@ -29,105 +29,105 @@ namespace beman::execution::detail { inline constexpr struct stop_when_t { template <::beman::execution::sender Sndr, ::beman::execution::stoppable_token Tok> - struct sender { - using sender_concept = ::beman::execution::sender_t; - - std::remove_cvref_t sndr; - std::remove_cvref_t tok; - - template <::beman::execution::receiver Rcvr> - struct state { - using operation_state_concept = ::beman::execution::operation_state_t; - using rcvr_t = ::std::remove_cvref_t; - using token1_t = ::std::remove_cvref_t; - using token2_t = - decltype(::beman::execution::get_stop_token(::beman::execution::get_env(::std::declval()))); - - struct cb_t { - ::beman::execution::inplace_stop_source& source; - auto operator()() const noexcept { this->source.request_stop(); } - }; - struct base_state { - rcvr_t rcvr; - ::beman::execution::inplace_stop_source source{}; - }; - struct env { - base_state* st; - auto query(const ::beman::execution::get_stop_token_t&) const noexcept { - return this->st->source.get_token(); - } - template - requires requires(const Q& q, A&&... a, const rcvr_t& r) { - q(::beman::execution::get_env(r), ::std::forward(a)...); - } - auto query(const Q& q, A&&... a) const noexcept { - return q(::beman::execution::get_env(this->st->rcvr), ::std::forward(a)...); - } - }; - - struct receiver { - using receiver_concept = ::beman::execution::receiver_t; - base_state* st; - - auto get_env() const noexcept -> env { return env{this->st}; } - template - auto set_value(A&&... a) const noexcept -> void { - ::beman::execution::set_value(::std::move(this->st->rcvr), ::std::forward(a)...); - } - template - auto set_error(E&& e) const noexcept -> void { - ::beman::execution::set_error(::std::move(this->st->rcvr), ::std::forward(e)); - } - auto set_stopped() const noexcept -> void { - ::beman::execution::set_stopped(::std::move(this->st->rcvr)); - } - }; - using inner_state_t = - decltype(::beman::execution::connect(::std::declval(), ::std::declval())); - - token1_t tok; - base_state base; - std::optional<::beman::execution::stop_callback_for_t> cb1; - std::optional<::beman::execution::stop_callback_for_t> cb2; - inner_state_t inner_state; - - template <::beman::execution::sender S, - ::beman::execution::stoppable_token T, - ::beman::execution::receiver R> - state(S&& s, T&& t, R&& r) - : tok(::std::forward(t)), - base{::std::forward(r)}, - inner_state(::beman::execution::connect(::std::forward(s), receiver(&this->base))) {} - - auto start() & noexcept { - this->cb1.emplace(this->tok, cb_t(this->base.source)); - this->cb2.emplace(::beman::execution::get_stop_token(::beman::execution::get_env(this->base.rcvr)), - cb_t(this->base.source)); - ::beman::execution::start(this->inner_state); - } - }; - - template - auto get_completion_signatures(const E& e) const noexcept { - return ::beman::execution::get_completion_signatures(this->sndr, e); - } - template <::beman::execution::receiver Rcvr> - auto connect(Rcvr&& rcvr) && -> state { - return state{std::move(this->sndr), ::std::move(this->tok), ::std::forward(rcvr)}; - } - }; + struct sender; template <::beman::execution::sender Sndr, ::beman::execution::stoppable_token Tok> auto operator()(Sndr&& sndr, Tok&& tok) const noexcept { if constexpr (::beman::execution::unstoppable_token) { return ::std::forward(sndr); } else { - return sender(::std::forward(sndr), ::std::forward(tok)); + return sender(*this, ::std::forward(tok), ::std::forward(sndr)); } } } stop_when{}; } // namespace beman::execution::detail +template <::beman::execution::sender Sndr, ::beman::execution::stoppable_token Tok> +struct beman::execution::detail::stop_when_t::sender { + using sender_concept = ::beman::execution::sender_t; + + stop_when_t stop_when{}; + std::remove_cvref_t tok; + std::remove_cvref_t sndr; + + template <::beman::execution::receiver Rcvr> + struct state { + using operation_state_concept = ::beman::execution::operation_state_t; + using rcvr_t = ::std::remove_cvref_t; + using token1_t = ::std::remove_cvref_t; + using token2_t = + decltype(::beman::execution::get_stop_token(::beman::execution::get_env(::std::declval()))); + + struct cb_t { + ::beman::execution::inplace_stop_source& source; + auto operator()() const noexcept { this->source.request_stop(); } + }; + struct base_state { + rcvr_t rcvr; + ::beman::execution::inplace_stop_source source{}; + }; + struct env { + base_state* st; + auto query(const ::beman::execution::get_stop_token_t&) const noexcept { + return this->st->source.get_token(); + } + template + requires requires(const Q& q, A&&... a, const rcvr_t& r) { + q(::beman::execution::get_env(r), ::std::forward(a)...); + } + auto query(const Q& q, A&&... a) const noexcept { + return q(::beman::execution::get_env(this->st->rcvr), ::std::forward(a)...); + } + }; + + struct receiver { + using receiver_concept = ::beman::execution::receiver_t; + base_state* st; + + auto get_env() const noexcept -> env { return env{this->st}; } + template + auto set_value(A&&... a) const noexcept -> void { + ::beman::execution::set_value(::std::move(this->st->rcvr), ::std::forward(a)...); + } + template + auto set_error(E&& e) const noexcept -> void { + ::beman::execution::set_error(::std::move(this->st->rcvr), ::std::forward(e)); + } + auto set_stopped() const noexcept -> void { ::beman::execution::set_stopped(::std::move(this->st->rcvr)); } + }; + using inner_state_t = + decltype(::beman::execution::connect(::std::declval(), ::std::declval())); + + token1_t tok; + base_state base; + std::optional<::beman::execution::stop_callback_for_t> cb1; + std::optional<::beman::execution::stop_callback_for_t> cb2; + inner_state_t inner_state; + + template <::beman::execution::sender S, ::beman::execution::stoppable_token T, ::beman::execution::receiver R> + state(S&& s, T&& t, R&& r) + : tok(::std::forward(t)), + base{::std::forward(r)}, + inner_state(::beman::execution::connect(::std::forward(s), receiver(&this->base))) {} + + auto start() & noexcept { + this->cb1.emplace(this->tok, cb_t(this->base.source)); + this->cb2.emplace(::beman::execution::get_stop_token(::beman::execution::get_env(this->base.rcvr)), + cb_t(this->base.source)); + ::beman::execution::start(this->inner_state); + } + }; + + template + auto get_completion_signatures(const E& e) const noexcept { + return ::beman::execution::get_completion_signatures(this->sndr, e); + } + template <::beman::execution::receiver Rcvr> + auto connect(Rcvr&& rcvr) && -> state { + return state{std::move(this->sndr), ::std::move(this->tok), ::std::forward(rcvr)}; + } +}; + // ---------------------------------------------------------------------------- #endif diff --git a/include/beman/execution/execution.hpp b/include/beman/execution/execution.hpp index b87c5ae0..9619c704 100644 --- a/include/beman/execution/execution.hpp +++ b/include/beman/execution/execution.hpp @@ -54,6 +54,13 @@ #include #include +#include +#include +#include +#include +#include +#include + // ---------------------------------------------------------------------------- #endif