#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace unifex { namespace _upon_done { namespace detail { template struct result_overload { using type = type_list; }; template <> struct result_overload { using type = type_list<>; }; template using result_overload_t = typename result_overload::type; } // namespace detail template struct _receiver { struct type; }; template using receiver_t = typename _receiver::type; template struct _receiver::type { UNIFEX_NO_UNIQUE_ADDRESS Func func_; UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_; template(typename... Values) (requires receiver_of< Receiver, Values...>) void set_value(Values&&... values) && { unifex::set_value((Receiver &&)(receiver_), (Values &&)(values)...); } template(typename Error) (requires receiver) void set_error(Error&& error) && noexcept { unifex::set_error((Receiver &&)(receiver_), (Error &&)(error)); } void set_done() && noexcept { using result_t = std::invoke_result_t; if constexpr (std::is_void_v) { if constexpr (noexcept(std::invoke((Func &&) func_))) { std::invoke((Func &&) func_); unifex::set_value((Receiver &&) receiver_); } else { UNIFEX_TRY { std::invoke((Func &&) func_); unifex::set_value((Receiver &&) receiver_); } UNIFEX_CATCH(...) { unifex::set_error((Receiver &&) receiver_, std::current_exception()); } } } else { if constexpr (noexcept(std::invoke((Func &&) func_))) { unifex::set_value( (Receiver &&) receiver_, std::invoke((Func &&) func_)); } else { UNIFEX_TRY { unifex::set_value( (Receiver &&) receiver_, std::invoke((Func &&) func_)); } UNIFEX_CATCH(...) { unifex::set_error((Receiver &&) receiver_, std::current_exception()); } } } } template(typename CPO) (requires is_receiver_query_cpo_v) friend auto tag_invoke( CPO cpo, const type& r) noexcept( is_nothrow_callable_v) -> callable_result_t { return (CPO &&)(cpo)(std::as_const(r.receiver_)); } template friend void tag_invoke(tag_t, const type& self, Visit&& visit) { std::invoke(visit, self.receiver_); } }; template struct _sender { struct type; }; template using sender = typename _sender, std::decay_t>::type; template struct _sender::type { UNIFEX_NO_UNIQUE_ADDRESS Predecessor pred_; UNIFEX_NO_UNIQUE_ADDRESS Func func_; private: /* * This helper returns type_list> if func returns Result * else if func returns void then helper returns type_list> */ using invoked_result_t = type_list>>; template < template class Variant, template class Tuple> using sets_done_predecessor_value_type_t = type_list_nested_apply_t< concat_type_lists_unique_t< sender_value_types_t, invoked_result_t>, Variant, Tuple>; template < template class Variant, template class Tuple> using no_sets_done_predecessor_value_type_t = type_list_nested_apply_t< sender_value_types_t, Variant, Tuple>; public: template < template class Variant, template class Tuple> using value_types = std::conditional_t< Predecessor::sends_done, sets_done_predecessor_value_type_t, no_sets_done_predecessor_value_type_t>; template