File indexing completed on 2025-09-17 08:23:35
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_IMPL_USE_AWAITABLE_HPP
0012 #define BOOST_ASIO_IMPL_USE_AWAITABLE_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019 #include <boost/asio/async_result.hpp>
0020 #include <boost/asio/cancellation_signal.hpp>
0021 #include <boost/asio/disposition.hpp>
0022
0023 #include <boost/asio/detail/push_options.hpp>
0024
0025 namespace boost {
0026 namespace asio {
0027 namespace detail {
0028
0029 template <typename Executor, typename T>
0030 class awaitable_handler_base
0031 : public awaitable_thread<Executor>
0032 {
0033 public:
0034 typedef void result_type;
0035 typedef awaitable<T, Executor> awaitable_type;
0036
0037
0038 awaitable_handler_base(awaitable<awaitable_thread_entry_point, Executor> a,
0039 const Executor& ex, cancellation_slot pcs, cancellation_state cs)
0040 : awaitable_thread<Executor>(std::move(a), ex, pcs, cs)
0041 {
0042 }
0043
0044
0045 explicit awaitable_handler_base(awaitable_thread<Executor>* h)
0046 : awaitable_thread<Executor>(std::move(*h))
0047 {
0048 }
0049
0050 protected:
0051 awaitable_frame<T, Executor>* frame() noexcept
0052 {
0053 return static_cast<awaitable_frame<T, Executor>*>(
0054 this->entry_point()->top_of_stack_);
0055 }
0056 };
0057
0058 template <typename, typename...>
0059 class awaitable_handler;
0060
0061 template <typename Executor>
0062 class awaitable_handler<Executor>
0063 : public awaitable_handler_base<Executor, void>
0064 {
0065 public:
0066 using awaitable_handler_base<Executor, void>::awaitable_handler_base;
0067
0068 void operator()()
0069 {
0070 this->frame()->attach_thread(this);
0071 this->frame()->return_void();
0072 this->frame()->clear_cancellation_slot();
0073 this->frame()->pop_frame();
0074 this->pump();
0075 }
0076 };
0077
0078 template <typename Executor, typename T>
0079 class awaitable_handler<Executor, T>
0080 : public awaitable_handler_base<Executor,
0081 conditional_t<is_disposition<T>::value, void, T>>
0082 {
0083 public:
0084 using awaitable_handler_base<Executor,
0085 conditional_t<is_disposition<T>::value, void, T>>
0086 ::awaitable_handler_base;
0087
0088 template <typename Arg>
0089 void operator()(Arg&& arg)
0090 {
0091 this->frame()->attach_thread(this);
0092 if constexpr (is_disposition<T>::value)
0093 {
0094 if (arg == no_error)
0095 this->frame()->return_void();
0096 else
0097 this->frame()->set_disposition(arg);
0098 }
0099 else
0100 this->frame()->return_value(std::forward<Arg>(arg));
0101 this->frame()->clear_cancellation_slot();
0102 this->frame()->pop_frame();
0103 this->pump();
0104 }
0105 };
0106
0107 template <typename Executor, typename T0, typename T1>
0108 class awaitable_handler<Executor, T0, T1>
0109 : public awaitable_handler_base<Executor,
0110 conditional_t<is_disposition<T0>::value, T1, std::tuple<T0, T1>>>
0111 {
0112 public:
0113 using awaitable_handler_base<Executor,
0114 conditional_t<is_disposition<T0>::value, T1, std::tuple<T0, T1>>>
0115 ::awaitable_handler_base;
0116
0117 template <typename Arg0, typename Arg1>
0118 void operator()(Arg0&& arg0, Arg1&& arg1)
0119 {
0120 this->frame()->attach_thread(this);
0121 if constexpr (is_disposition<T0>::value)
0122 {
0123 if (arg0 == no_error)
0124 this->frame()->return_value(std::forward<Arg1>(arg1));
0125 else
0126 this->frame()->set_disposition(std::forward<Arg0>(arg0));
0127 }
0128 else
0129 {
0130 this->frame()->return_values(std::forward<Arg0>(arg0),
0131 std::forward<Arg1>(arg1));
0132 }
0133 this->frame()->clear_cancellation_slot();
0134 this->frame()->pop_frame();
0135 this->pump();
0136 }
0137 };
0138
0139 template <typename Executor, typename T0, typename... Ts>
0140 class awaitable_handler<Executor, T0, Ts...>
0141 : public awaitable_handler_base<Executor,
0142 conditional_t<is_disposition<T0>::value,
0143 std::tuple<Ts...>, std::tuple<T0, Ts...>>>
0144 {
0145 public:
0146 using awaitable_handler_base<Executor,
0147 conditional_t<is_disposition<T0>::value,
0148 std::tuple<Ts...>, std::tuple<T0, Ts...>>>
0149 ::awaitable_handler_base;
0150
0151 template <typename Arg0, typename... Args>
0152 void operator()(Arg0&& arg0, Args&&... args)
0153 {
0154 this->frame()->attach_thread(this);
0155 if constexpr (is_disposition<T0>::value)
0156 {
0157 if (arg0 == no_error)
0158 this->frame()->return_values(std::forward<Args>(args)...);
0159 else
0160 this->frame()->set_disposition(std::forward<Arg0>(arg0));
0161 }
0162 else
0163 {
0164 this->frame()->return_values(std::forward<Arg0>(arg0),
0165 std::forward<Args>(args)...);
0166 }
0167 this->frame()->clear_cancellation_slot();
0168 this->frame()->pop_frame();
0169 this->pump();
0170 }
0171 };
0172
0173 }
0174
0175 #if !defined(GENERATING_DOCUMENTATION)
0176
0177 #if defined(_MSC_VER)
0178 template <typename T>
0179 T dummy_return()
0180 {
0181 return std::move(*static_cast<T*>(nullptr));
0182 }
0183
0184 template <>
0185 inline void dummy_return()
0186 {
0187 }
0188 #endif
0189
0190 template <typename Executor, typename R, typename... Args>
0191 class async_result<use_awaitable_t<Executor>, R(Args...)>
0192 {
0193 public:
0194 typedef typename detail::awaitable_handler<
0195 Executor, decay_t<Args>...> handler_type;
0196 typedef typename handler_type::awaitable_type return_type;
0197
0198 template <typename Initiation, typename... InitArgs>
0199 #if defined(__APPLE_CC__) && (__clang_major__ == 13)
0200 __attribute__((noinline))
0201 #endif
0202 static handler_type* do_init(
0203 detail::awaitable_frame_base<Executor>* frame, Initiation& initiation,
0204 use_awaitable_t<Executor> u, InitArgs&... args)
0205 {
0206 (void)u;
0207 BOOST_ASIO_HANDLER_LOCATION((u.file_name_, u.line_, u.function_name_));
0208 handler_type handler(frame->detach_thread());
0209 std::move(initiation)(std::move(handler), std::move(args)...);
0210 return nullptr;
0211 }
0212
0213 template <typename Initiation, typename... InitArgs>
0214 static return_type initiate(Initiation initiation,
0215 use_awaitable_t<Executor> u, InitArgs... args)
0216 {
0217 co_await [&] (auto* frame)
0218 {
0219 return do_init(frame, initiation, u, args...);
0220 };
0221
0222 for (;;) {}
0223 #if defined(_MSC_VER)
0224 co_return dummy_return<typename return_type::value_type>();
0225 #endif
0226 }
0227 };
0228
0229 #endif
0230
0231 }
0232 }
0233
0234 #include <boost/asio/detail/pop_options.hpp>
0235
0236 #endif