/* * 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 namespace unifex { namespace _via { template struct _value_receiver { struct type; }; template using value_receiver = typename _value_receiver< Receiver, std::decay_t...>::type; template struct _value_receiver::type { using value_receiver = type; UNIFEX_NO_UNIQUE_ADDRESS std::tuple values_; UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_; void set_value() noexcept { std::apply( [&](Values && ... values) noexcept { unifex::set_value( std::forward(receiver_), (Values &&) values...); }, std::move(values_)); } template void set_error(Error&& error) noexcept { unifex::set_error(std::forward(receiver_), (Error &&) error); } void set_done() noexcept { unifex::set_done(std::forward(receiver_)); } template(typename CPO) (requires is_receiver_query_cpo_v) friend auto tag_invoke(CPO cpo, const value_receiver& 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 value_receiver& r, Func&& func) { std::invoke(func, r.receiver_); } }; template struct _error_receiver { struct type; }; template using error_receiver = typename _error_receiver>::type; template struct _error_receiver::type { using error_receiver = type; UNIFEX_NO_UNIQUE_ADDRESS Error error_; UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_; void set_value() noexcept { unifex::set_error(std::forward(receiver_), std::move(error_)); } template void set_error(OtherError&& otherError) noexcept { unifex::set_error( std::forward(receiver_), (OtherError &&) otherError); } void set_done() noexcept { unifex::set_done(std::forward(receiver_)); } template(typename CPO) (requires is_receiver_query_cpo_v) friend auto tag_invoke(CPO cpo, const error_receiver& 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 error_receiver& r, Func&& func) { std::invoke(func, r.receiver_); } }; template struct _done_receiver { struct type; }; template using done_receiver = typename _done_receiver::type; template struct _done_receiver::type { using done_receiver = type; UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_; void set_value() noexcept { unifex::set_done(std::forward(receiver_)); } template void set_error(OtherError&& otherError) noexcept { unifex::set_error( std::forward(receiver_), (OtherError &&) otherError); } void set_done() noexcept { unifex::set_done(std::forward(receiver_)); } template(typename CPO) (requires is_receiver_query_cpo_v) friend auto tag_invoke(CPO cpo, const done_receiver& 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 done_receiver& r, Func&& func) { std::invoke(func, r.receiver_); } }; template struct _predecessor_receiver { struct type; }; template using predecessor_receiver = typename _predecessor_receiver>::type; template struct _predecessor_receiver::type { using predecessor_receiver = type; Successor successor_; Receiver receiver_; template void set_value(Values&&... values) && noexcept { UNIFEX_TRY { submit( (Successor &&) successor_, value_receiver{ {(Values &&) values...}, (Receiver &&) receiver_}); } UNIFEX_CATCH (...) { unifex::set_error( static_cast(receiver_), std::current_exception()); } } template void set_error(Error&& error) && noexcept { UNIFEX_TRY { submit( (Successor &&) successor_, error_receiver{ (Error &&) error, (Receiver &&) receiver_}); } UNIFEX_CATCH (...) { unifex::set_error( static_cast(receiver_), std::current_exception()); } } void set_done() && noexcept { UNIFEX_TRY { submit( (Successor &&) successor_, done_receiver{(Receiver &&) receiver_}); } UNIFEX_CATCH (...) { unifex::set_error( static_cast(receiver_), std::current_exception()); } } template(typename CPO) (requires is_receiver_query_cpo_v) friend auto tag_invoke(CPO cpo, const predecessor_receiver& 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 predecessor_receiver& r, Func&& func) { std::invoke(func, r.receiver_); } }; template struct _sender { struct type; }; template using sender = typename _sender< remove_cvref_t, remove_cvref_t>::type; template struct _sender::type { using sender = type; UNIFEX_NO_UNIQUE_ADDRESS Predecessor pred_; UNIFEX_NO_UNIQUE_ADDRESS Successor succ_; template using overload_list = type_list...>>; template < template class Variant, template class Tuple> using value_types = type_list_nested_apply_t< sender_value_types_t, Variant, Tuple>; template