/* * 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 namespace unifex { namespace _let_v_w_stop_src { template struct _stop_source_receiver { class type; }; template struct _stop_source_operation { struct type; }; template using operation = typename _stop_source_operation>::type; template using stop_source_receiver = typename _stop_source_receiver::type; template class _stop_source_receiver::type { public: explicit type(Operation& op, Receiver&& r) : op_(op), receiver_{std::forward(r)} {} template(typename... Values) (requires receiver_of) void set_value(Values&&... values) noexcept(is_nothrow_receiver_of_v) { unifex::set_value(std::move(receiver_), (Values&&)values...); } template(typename Error) (requires receiver) void set_error(Error&& error) noexcept { unifex::set_error(std::move(receiver_), (Error&&)error); } void set_done() noexcept { unifex::set_done(std::move(receiver_)); } friend inplace_stop_token tag_invoke(tag_t, const type& r) noexcept { return r.op_.stop_source_.get_token(); } template(typename CPO, typename Self) (requires is_receiver_query_cpo_v AND same_as) friend auto tag_invoke(CPO cpo, const Self& self) noexcept(is_nothrow_callable_v) -> callable_result_t { return cpo(self.receiver_); } private: UNIFEX_NO_UNIQUE_ADDRESS Operation& op_; UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_; }; template struct _stop_source_sender { class type; }; template using stop_source_sender = typename _stop_source_sender::type; template class _stop_source_sender::type { template using additional_arguments = type_list>; public: using InnerOp = std::invoke_result_t; template class Variant, template class Tuple> using value_types = sender_value_types_t; template class Variant> using error_types = sender_error_types_t; static constexpr bool sends_done = sender_traits::sends_done; template explicit type(SuccessorFactory2&& func) : func_((SuccessorFactory2&&)func) {} template(typename Self, typename Receiver) (requires same_as, type> AND receiver) friend auto tag_invoke(tag_t, Self&& self, Receiver&& r) noexcept( std::is_nothrow_invocable_v, inplace_stop_source&> && std::is_nothrow_constructible_v, Receiver>) -> operation, Receiver> { return operation, Receiver>( static_cast(self).func_, static_cast(r)); } private: UNIFEX_NO_UNIQUE_ADDRESS SuccessorFactory func_; }; struct _stop_source_operation_callback { explicit _stop_source_operation_callback(inplace_stop_source& source) noexcept : source_{source} {} void operator()() noexcept { source_.request_stop(); } inplace_stop_source& source_; }; template struct _stop_source_operation::type { template type(SuccessorFactory2&& func, Receiver2&& r) : func_{(SuccessorFactory2&&)func}, stop_source_{}, // Chain the stop token so that downstream cancellation also affects this // operation stop_callback_( unifex::get_stop_token(r), _stop_source_operation_callback(stop_source_)), innerOp_( unifex::connect( ((SuccessorFactory&&)func_)(stop_source_), stop_source_receiver, remove_cvref_t>{ *this, static_cast(r)})) { } void start() noexcept { unifex::start(innerOp_); } template using callback_type = typename stop_token_type_t::template callback_type; UNIFEX_NO_UNIQUE_ADDRESS SuccessorFactory func_; UNIFEX_NO_UNIQUE_ADDRESS unifex::inplace_stop_source stop_source_; UNIFEX_NO_UNIQUE_ADDRESS callback_type<_stop_source_operation_callback> stop_callback_; connect_result_t< callable_result_t, stop_source_receiver, remove_cvref_t>> innerOp_; }; namespace _cpo { struct _fn { template auto operator()(SuccessorFactory&& factory) const noexcept(std::is_nothrow_constructible_v, SuccessorFactory>) -> stop_source_sender> { return stop_source_sender>{(SuccessorFactory&&)factory}; } }; } // namespace _cpo } // namespace _let_v_w_stop_src inline constexpr _let_v_w_stop_src::_cpo::_fn let_value_with_stop_source{}; } // namespace unifex #include