1// Copyright (c) 2022 Klemens D. Morgenstern
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5#ifndef BOOST_COBALT_CONCEPTS_HPP
6#define BOOST_COBALT_CONCEPTS_HPP
7
8#include <coroutine>
9#include <concepts>
10#include <utility>
11
12#include <boost/asio/error.hpp>
13#include <boost/asio/is_executor.hpp>
14#include <boost/asio/execution/executor.hpp>
15#include <boost/system/system_error.hpp>
16#include <boost/throw_exception.hpp>
17
18namespace boost::cobalt
19{
20
21// tag::outline[]
22template<typename Awaitable, typename Promise = void>
23concept awaitable_type = requires (Awaitable aw, std::coroutine_handle<Promise> h)
24{
25 {aw.await_ready()} -> std::convertible_to<bool>;
26 {aw.await_suspend(h)};
27 {aw.await_resume()};
28};
29
30template<typename Awaitable, typename Promise = void>
31concept awaitable =
32 awaitable_type<Awaitable, Promise>
33 || requires (Awaitable && aw) { {std::forward<Awaitable>(aw).operator co_await()} -> awaitable_type<Promise>;}
34 || requires (Awaitable && aw) { {operator co_await(std::forward<Awaitable>(aw))} -> awaitable_type<Promise>;};
35//end::outline[]
36
37struct promise_throw_if_cancelled_base;
38template<typename Promise = void>
39struct enable_awaitables
40{
41 template<awaitable<Promise> Aw>
42 Aw && await_transform(Aw && aw,
43 const boost::source_location & loc = BOOST_CURRENT_LOCATION)
44 {
45 if constexpr (std::derived_from<Promise, promise_throw_if_cancelled_base>)
46 {
47 auto p = static_cast<Promise*>(this);
48 // a promise inheriting promise_throw_if_cancelled_base needs to also have a .cancelled() function
49 if (!!p->cancelled() && p->throw_if_cancelled())
50 {
51 constexpr boost::source_location here{BOOST_CURRENT_LOCATION};
52 boost::throw_exception(e: system::system_error(
53 {asio::error::operation_aborted, &here},
54 "throw_if_cancelled"), loc);
55 }
56
57 }
58 return static_cast<Aw&&>(aw);
59 }
60};
61
62template <typename T>
63concept with_get_executor = requires (T& t)
64{
65 {t.get_executor()} -> asio::execution::executor;
66};
67
68
69}
70
71#endif //BOOST_COBALT_CONCEPTS_HPP
72

source code of boost/libs/cobalt/include/boost/cobalt/concepts.hpp