/* * 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 namespace unifex { namespace _mat { template struct _receiver { class type; }; template using receiver_t = typename _receiver>::type; template class _receiver::type { public: template(typename Receiver2) (requires constructible_from) explicit type(Receiver2&& receiver) noexcept( std::is_nothrow_constructible_v) : receiver_(static_cast(receiver)) {} template(typename... Values) (requires receiver_of, Values...>) void set_value(Values&&... values) && noexcept( is_nothrow_receiver_of_v, Values...>) { unifex::set_value( static_cast(receiver_), unifex::set_value, static_cast(values)...); } template(typename Error) (requires receiver_of, Error>) void set_error(Error&& error) && noexcept { if constexpr (is_nothrow_receiver_of_v< Receiver, tag_t, Error>) { unifex::set_value( static_cast(receiver_), unifex::set_error, static_cast(error)); } else { UNIFEX_TRY { unifex::set_value( static_cast(receiver_), unifex::set_error, static_cast(error)); } UNIFEX_CATCH (...) { unifex::set_error( static_cast(receiver_), std::current_exception()); } } } template(typename R = Receiver) (requires receiver_of>) void set_done() && noexcept { if constexpr (is_nothrow_receiver_of_v>) { unifex::set_value( static_cast(receiver_), unifex::set_done); } else { UNIFEX_TRY { unifex::set_value( static_cast(receiver_), unifex::set_done); } UNIFEX_CATCH (...) { unifex::set_error( static_cast(receiver_), std::current_exception()); } } } template(typename CPO, UNIFEX_DECLARE_NON_DEDUCED_TYPE(R, type)) (requires is_receiver_query_cpo_v AND is_callable_v) friend auto tag_invoke( CPO cpo, const UNIFEX_USE_NON_DEDUCED_TYPE(R, type)& r) noexcept(is_nothrow_callable_v< CPO, const Receiver&>) -> callable_result_t { return static_cast(cpo)(std::as_const(r.receiver_)); } template < typename Func, UNIFEX_DECLARE_NON_DEDUCED_TYPE(CPO, tag_t), UNIFEX_DECLARE_NON_DEDUCED_TYPE(R, type)> friend void tag_invoke( UNIFEX_USE_NON_DEDUCED_TYPE(CPO, tag_t), const UNIFEX_USE_NON_DEDUCED_TYPE(R, type)& r, Func&& func) noexcept(std::is_nothrow_invocable_v< Func&, const Receiver&>) { std::invoke(func, std::as_const(r.receiver_)); } private: Receiver receiver_; }; template < template class Variant, template class Tuple, typename... ValueTuples> struct error_variant { template using apply = Variant< ValueTuples..., Tuple, Errors>..., Tuple>>; }; template < typename Source, template class Variant, template class Tuple> struct value_types { template using value_tuple = Tuple, Values...>; template using value_variant = sender_error_types_t< Source, error_variant::template apply>; using type = sender_value_types_t; }; template struct _sender { class type; }; template using sender = typename _sender>::type; template class _sender::type { using sender = type; public: template < template class Variant, template class Tuple> using value_types = typename value_types::type; template