Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:43:20

0001 //
0002 // experimental/detail/coro_traits.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2021-2023 Klemens D. Morgenstern
0006 //                         (klemens dot morgenstern at gmx dot net)
0007 //
0008 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0009 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 
0012 #ifndef BOOST_ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP
0013 #define BOOST_ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP
0014 
0015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0016 # pragma once
0017 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0018 
0019 #include <boost/asio/detail/config.hpp>
0020 #include <optional>
0021 #include <variant>
0022 #include <boost/asio/any_io_executor.hpp>
0023 
0024 namespace boost {
0025 namespace asio {
0026 namespace experimental {
0027 namespace detail {
0028 
0029 template <class From, class To>
0030 concept convertible_to = std::is_convertible_v<From, To>;
0031 
0032 template <typename T>
0033 concept decays_to_executor = execution::executor<std::decay_t<T>>;
0034 
0035 template <typename T, typename Executor = any_io_executor>
0036 concept execution_context = requires (T& t)
0037 {
0038   {t.get_executor()} -> convertible_to<Executor>;
0039 };
0040 
0041 template <typename Yield, typename Return>
0042 struct coro_result
0043 {
0044   using type = std::variant<Yield, Return>;
0045 };
0046 
0047 template <typename Yield>
0048 struct coro_result<Yield, void>
0049 {
0050   using type = std::optional<Yield>;
0051 };
0052 
0053 template <typename Return>
0054 struct coro_result<void, Return>
0055 {
0056   using type = Return;
0057 };
0058 
0059 template <typename YieldReturn>
0060 struct coro_result<YieldReturn, YieldReturn>
0061 {
0062   using type = YieldReturn;
0063 };
0064 
0065 template <>
0066 struct coro_result<void, void>
0067 {
0068   using type = void;
0069 };
0070 
0071 template <typename Yield, typename Return>
0072 using coro_result_t = typename coro_result<Yield, Return>::type;
0073 
0074 template <typename Result, bool IsNoexcept>
0075 struct coro_handler;
0076 
0077 template <>
0078 struct coro_handler<void, false>
0079 {
0080   using type = void(std::exception_ptr);
0081 };
0082 
0083 template <>
0084 struct coro_handler<void, true>
0085 {
0086   using type = void();
0087 };
0088 
0089 template <typename T>
0090 struct coro_handler<T, false>
0091 {
0092   using type = void(std::exception_ptr, T);
0093 };
0094 
0095 template <typename T>
0096 struct coro_handler<T, true>
0097 {
0098   using type = void(T);
0099 };
0100 
0101 template <typename Result, bool IsNoexcept>
0102 using coro_handler_t = typename coro_handler<Result, IsNoexcept>::type;
0103 
0104 } // namespace detail
0105 
0106 #if defined(GENERATING_DOCUMENTATION)
0107 
0108 /// The traits describing the resumable coroutine behaviour.
0109 /**
0110  * Template parameter @c Yield specifies type or signature used by co_yield,
0111  * @c Return specifies the type used for co_return, and @c Executor specifies
0112  * the underlying executor type.
0113  */
0114 template <typename Yield, typename Return, typename Executor>
0115 struct coro_traits
0116 {
0117   /// The value that can be passed into a symmetrical cororoutine. @c void if
0118   /// asymmetrical.
0119   using input_type = argument_dependent;
0120 
0121   /// The type that can be passed out through a co_yield.
0122   using yield_type = argument_dependent;
0123 
0124   /// The type that can be passed out through a co_return.
0125   using return_type = argument_dependent;
0126 
0127   /// The type received by a co_await or async_resume. It's a combination of
0128   /// yield and return.
0129   using result_type = argument_dependent;
0130 
0131   /// The signature used by the async_resume.
0132   using signature_type = argument_dependent;
0133 
0134   /// Whether or not the coroutine is noexcept.
0135   constexpr static bool is_noexcept = argument_dependent;
0136 
0137   /// The error type of the coroutine. @c void for noexcept.
0138   using error_type = argument_dependent;
0139 
0140   /// Completion handler type used by async_resume.
0141   using completion_handler = argument_dependent;
0142 };
0143 
0144 #else // defined(GENERATING_DOCUMENTATION)
0145 
0146 template <typename Yield, typename Return, typename Executor>
0147 struct coro_traits
0148 {
0149   using input_type  = void;
0150   using yield_type  = Yield;
0151   using return_type = Return;
0152   using result_type = detail::coro_result_t<yield_type, return_type>;
0153   using signature_type = result_type();
0154   constexpr static bool is_noexcept = false;
0155   using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
0156   using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
0157 };
0158 
0159 template <typename T, typename Return, typename Executor>
0160 struct coro_traits<T(), Return, Executor>
0161 {
0162   using input_type = void;
0163   using yield_type = T;
0164   using return_type = Return;
0165   using result_type = detail::coro_result_t<yield_type, return_type>;
0166   using signature_type = result_type();
0167   constexpr static bool is_noexcept = false;
0168   using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
0169   using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
0170 };
0171 
0172 template <typename T, typename Return, typename Executor>
0173 struct coro_traits<T() noexcept, Return, Executor>
0174 {
0175   using input_type = void;
0176   using yield_type = T;
0177   using return_type = Return;
0178   using result_type = detail::coro_result_t<yield_type, return_type>;
0179   using signature_type = result_type();
0180   constexpr static bool is_noexcept = true;
0181   using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
0182   using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
0183 };
0184 
0185 template <typename T, typename U, typename Return, typename Executor>
0186 struct coro_traits<T(U), Return, Executor>
0187 {
0188   using input_type = U;
0189   using yield_type = T;
0190   using return_type = Return;
0191   using result_type = detail::coro_result_t<yield_type, return_type>;
0192   using signature_type = result_type(input_type);
0193   constexpr static bool is_noexcept = false;
0194   using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
0195   using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
0196 };
0197 
0198 template <typename T, typename U, typename Return, typename Executor>
0199 struct coro_traits<T(U) noexcept, Return, Executor>
0200 {
0201   using input_type = U;
0202   using yield_type = T;
0203   using return_type = Return;
0204   using result_type = detail::coro_result_t<yield_type, return_type>;
0205   using signature_type = result_type(input_type);
0206   constexpr static bool is_noexcept = true;
0207   using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
0208   using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
0209 };
0210 
0211 template <typename Executor>
0212 struct coro_traits<void() noexcept, void, Executor>
0213 {
0214   using input_type = void;
0215   using yield_type = void;
0216   using return_type = void;
0217   using result_type = detail::coro_result_t<yield_type, return_type>;
0218   using signature_type = result_type(input_type);
0219   constexpr static bool is_noexcept = true;
0220   using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;
0221   using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;
0222 };
0223 
0224 #endif // defined(GENERATING_DOCUMENTATION)
0225 
0226 } // namespace experimental
0227 } // namespace asio
0228 } // namespace boost
0229 
0230 #endif // BOOST_ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP