// Copyright (c) 2022 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_COBALT_CONCEPTS_HPP #define BOOST_COBALT_CONCEPTS_HPP #include #include #include #include #include #include #include #include namespace boost::cobalt { // tag::outline[] template concept awaitable_type = requires (Awaitable aw, std::coroutine_handle h) { {aw.await_ready()} -> std::convertible_to; {aw.await_suspend(h)}; {aw.await_resume()}; }; template concept awaitable = awaitable_type || requires (Awaitable && aw) { {std::forward(aw).operator co_await()} -> awaitable_type;} || requires (Awaitable && aw) { {operator co_await(std::forward(aw))} -> awaitable_type;}; //end::outline[] struct promise_throw_if_cancelled_base; template struct enable_awaitables { template Aw> Aw && await_transform(Aw && aw, const boost::source_location & loc = BOOST_CURRENT_LOCATION) { if constexpr (std::derived_from) { auto p = static_cast(this); // a promise inheriting promise_throw_if_cancelled_base needs to also have a .cancelled() function if (!!p->cancelled() && p->throw_if_cancelled()) { constexpr boost::source_location here{BOOST_CURRENT_LOCATION}; boost::throw_exception(system::system_error( {asio::error::operation_aborted, &here}, "throw_if_cancelled"), loc); } } return static_cast(aw); } }; template concept with_get_executor = requires (T& t) { {t.get_executor()} -> asio::execution::executor; }; } #endif //BOOST_COBALT_CONCEPTS_HPP