coro_traits.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. //
  2. // experimental/detail/coro_traits.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2021-2023 Klemens D. Morgenstern
  6. // (klemens dot morgenstern at gmx dot net)
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. #ifndef BOOST_ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP
  12. #define BOOST_ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  14. # pragma once
  15. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #include <boost/asio/detail/config.hpp>
  17. #include <optional>
  18. #include <variant>
  19. #include <boost/asio/any_io_executor.hpp>
  20. namespace boost {
  21. namespace asio {
  22. namespace experimental {
  23. namespace detail {
  24. template <class From, class To>
  25. concept convertible_to = std::is_convertible_v<From, To>;
  26. template <typename T>
  27. concept decays_to_executor = execution::executor<std::decay_t<T>>;
  28. template <typename T, typename Executor = any_io_executor>
  29. concept execution_context = requires (T& t)
  30. {
  31. {t.get_executor()} -> convertible_to<Executor>;
  32. };
  33. template <typename Yield, typename Return>
  34. struct coro_result
  35. {
  36. using type = std::variant<Yield, Return>;
  37. };
  38. template <typename Yield>
  39. struct coro_result<Yield, void>
  40. {
  41. using type = std::optional<Yield>;
  42. };
  43. template <typename Return>
  44. struct coro_result<void, Return>
  45. {
  46. using type = Return;
  47. };
  48. template <typename YieldReturn>
  49. struct coro_result<YieldReturn, YieldReturn>
  50. {
  51. using type = YieldReturn;
  52. };
  53. template <>
  54. struct coro_result<void, void>
  55. {
  56. using type = void;
  57. };
  58. template <typename Yield, typename Return>
  59. using coro_result_t = typename coro_result<Yield, Return>::type;
  60. template <typename Result, bool IsNoexcept>
  61. struct coro_handler;
  62. template <>
  63. struct coro_handler<void, false>
  64. {
  65. using type = void(std::exception_ptr);
  66. };
  67. template <>
  68. struct coro_handler<void, true>
  69. {
  70. using type = void();
  71. };
  72. template <typename T>
  73. struct coro_handler<T, false>
  74. {
  75. using type = void(std::exception_ptr, T);
  76. };
  77. template <typename T>
  78. struct coro_handler<T, true>
  79. {
  80. using type = void(T);
  81. };
  82. template <typename Result, bool IsNoexcept>
  83. using coro_handler_t = typename coro_handler<Result, IsNoexcept>::type;
  84. } // namespace detail
  85. #if defined(GENERATING_DOCUMENTATION)
  86. /// The traits describing the resumable coroutine behaviour.
  87. /**
  88. * Template parameter @c Yield specifies type or signature used by co_yield,
  89. * @c Return specifies the type used for co_return, and @c Executor specifies
  90. * the underlying executor type.
  91. */
  92. template <typename Yield, typename Return, typename Executor>
  93. struct coro_traits
  94. {
  95. /// The value that can be passed into a symmetrical cororoutine. @c void if
  96. /// asymmetrical.
  97. using input_type = argument_dependent;
  98. /// The type that can be passed out through a co_yield.
  99. using yield_type = argument_dependent;
  100. /// The type that can be passed out through a co_return.
  101. using return_type = argument_dependent;
  102. /// The type received by a co_await or async_resume. It's a combination of
  103. /// yield and return.
  104. using result_type = argument_dependent;
  105. /// The signature used by the async_resume.
  106. using signature_type = argument_dependent;
  107. /// Whether or not the coroutine is noexcept.
  108. constexpr static bool is_noexcept = argument_dependent;
  109. /// The error type of the coroutine. @c void for noexcept.
  110. using error_type = argument_dependent;
  111. /// Completion handler type used by async_resume.
  112. using completion_handler = argument_dependent;
  113. };
  114. #else // defined(GENERATING_DOCUMENTATION)
  115. template <typename Yield, typename Return, typename Executor>
  116. struct coro_traits
  117. {
  118. using input_type = void;
  119. using yield_type = Yield;
  120. using return_type = Return;
  121. using result_type = detail::coro_result_t<yield_type, return_type>;
  122. using signature_type = result_type();
  123. constexpr static bool is_noexcept = false;
  124. using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
  125. using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
  126. };
  127. template <typename T, typename Return, typename Executor>
  128. struct coro_traits<T(), Return, Executor>
  129. {
  130. using input_type = void;
  131. using yield_type = T;
  132. using return_type = Return;
  133. using result_type = detail::coro_result_t<yield_type, return_type>;
  134. using signature_type = result_type();
  135. constexpr static bool is_noexcept = false;
  136. using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
  137. using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
  138. };
  139. template <typename T, typename Return, typename Executor>
  140. struct coro_traits<T() noexcept, Return, Executor>
  141. {
  142. using input_type = void;
  143. using yield_type = T;
  144. using return_type = Return;
  145. using result_type = detail::coro_result_t<yield_type, return_type>;
  146. using signature_type = result_type();
  147. constexpr static bool is_noexcept = true;
  148. using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
  149. using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
  150. };
  151. template <typename T, typename U, typename Return, typename Executor>
  152. struct coro_traits<T(U), Return, Executor>
  153. {
  154. using input_type = U;
  155. using yield_type = T;
  156. using return_type = Return;
  157. using result_type = detail::coro_result_t<yield_type, return_type>;
  158. using signature_type = result_type(input_type);
  159. constexpr static bool is_noexcept = false;
  160. using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
  161. using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
  162. };
  163. template <typename T, typename U, typename Return, typename Executor>
  164. struct coro_traits<T(U) noexcept, Return, Executor>
  165. {
  166. using input_type = U;
  167. using yield_type = T;
  168. using return_type = Return;
  169. using result_type = detail::coro_result_t<yield_type, return_type>;
  170. using signature_type = result_type(input_type);
  171. constexpr static bool is_noexcept = true;
  172. using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
  173. using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
  174. };
  175. template <typename Executor>
  176. struct coro_traits<void() noexcept, void, Executor>
  177. {
  178. using input_type = void;
  179. using yield_type = void;
  180. using return_type = void;
  181. using result_type = detail::coro_result_t<yield_type, return_type>;
  182. using signature_type = result_type(input_type);
  183. constexpr static bool is_noexcept = true;
  184. using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
  185. using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
  186. };
  187. #endif // defined(GENERATING_DOCUMENTATION)
  188. } // namespace experimental
  189. } // namespace asio
  190. } // namespace boost
  191. #endif // BOOST_ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP