/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License Version 2.0 with LLVM Exceptions * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://llvm.org/LICENSE.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace unifex { namespace _then { namespace detail { template struct result_overload { using type = type_list; }; template struct result_overload>> { using type = type_list<>; }; } 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 void set_value(Values&&... values) && noexcept { using result_type = std::invoke_result_t; if constexpr (std::is_void_v) { if constexpr (noexcept(std::invoke( (Func &&) func_, (Values &&) values...))) { std::invoke((Func &&) func_, (Values &&) values...); unifex::set_value((Receiver &&) receiver_); } else { UNIFEX_TRY { std::invoke((Func &&) func_, (Values &&) values...); unifex::set_value((Receiver &&) receiver_); } UNIFEX_CATCH (...) { unifex::set_error((Receiver &&) receiver_, std::current_exception()); } } } else { if constexpr (noexcept(std::invoke( (Func &&) func_, (Values &&) values...))) { unifex::set_value( (Receiver &&) receiver_, std::invoke((Func &&) func_, (Values &&) values...)); } else { UNIFEX_TRY { unifex::set_value( (Receiver &&) receiver_, std::invoke((Func &&) func_, (Values &&) values...)); } UNIFEX_CATCH (...) { unifex::set_error((Receiver &&) receiver_, std::current_exception()); } } } } template void set_error(Error&& error) && noexcept { unifex::set_error((Receiver &&) receiver_, (Error &&) error); } void set_done() && noexcept { unifex::set_done((Receiver &&) receiver_); } template(typename CPO, typename R) (requires is_receiver_query_cpo_v AND same_as) friend auto tag_invoke(CPO cpo, const R& r) noexcept( is_nothrow_callable_v) -> callable_result_t { return std::move(cpo)(std::as_const(r.receiver_)); } template friend void tag_invoke(tag_t, const type& r, Visit&& visit) { std::invoke(visit, r.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 transforms an argument list into either // - type_list> - if Result is non-void, or // - type_list> - if Result is void template using result = type_list< typename detail::result_overload>::type>; public: template < template class Variant, template class Tuple> using value_types = type_list_nested_apply_t< sender_value_types_t, Variant, Tuple>; template