/* * 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 namespace unifex { namespace _stop_if { struct _fn { private: struct _sender { private: template struct _op { struct type { Receiver rec_; void start() & noexcept { UNIFEX_TRY { if (get_stop_token(std::as_const(rec_)).stop_requested()) { unifex::set_done((Receiver&&) rec_); } else { unifex::set_value((Receiver&&) rec_); } } UNIFEX_CATCH (...) { unifex::set_error((Receiver&&) rec_, std::current_exception()); } } }; }; public: #if !UNIFEX_NO_COROUTINES // Provide an awaiter interface in addition to the sender interface // because as an awaiter we can take advantage of symmetric transfer // to save stack space: bool await_ready() const noexcept { return false; } template coro::coroutine_handle<> await_suspend(coro::coroutine_handle coro) const noexcept { if (get_stop_token(coro.promise()).stop_requested()) { return coro.promise().unhandled_done(); } return coro; // don't suspend } void await_resume() const noexcept { } #endif template< template class Variant, template class Tuple> using value_types = Variant>; template< template class Variant> using error_types = Variant; static constexpr bool sends_done = true; template (typename Receiver) (requires receiver_of) auto connect(Receiver&& rec) const -> typename _op>::type { return typename _op>::type{(Receiver&&) rec}; } }; public: [[nodiscard]] constexpr _sender operator()() const noexcept { return {}; } }; } // namespace _stop_if namespace _stop { struct _fn { [[nodiscard]] constexpr auto operator()() const noexcept { return just_done(); } }; } // namespace _stop // Await this to cancel and unwind if stop has been requested: inline constexpr _stop_if::_fn stop_if_requested {}; // Await this to cancel unconditionally: inline constexpr _stop::_fn stop {}; } // namespace unifex #include