File indexing completed on 2025-01-18 09:28:58
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
0022 #include <boost/asio/detail/push_options.hpp>
0023
0024 namespace boost {
0025 namespace asio {
0026 namespace detail {
0027
0028 template <typename Executor, typename T>
0029 class awaitable_handler_base
0030 : public awaitable_thread<Executor>
0031 {
0032 public:
0033 typedef void result_type;
0034 typedef awaitable<T, Executor> awaitable_type;
0035
0036
0037 awaitable_handler_base(awaitable<awaitable_thread_entry_point, Executor> a,
0038 const Executor& ex, cancellation_slot pcs, cancellation_state cs)
0039 : awaitable_thread<Executor>(std::move(a), ex, pcs, cs)
0040 {
0041 }
0042
0043
0044 explicit awaitable_handler_base(awaitable_thread<Executor>* h)
0045 : awaitable_thread<Executor>(std::move(*h))
0046 {
0047 }
0048
0049 protected:
0050 awaitable_frame<T, Executor>* frame() noexcept
0051 {
0052 return static_cast<awaitable_frame<T, Executor>*>(
0053 this->entry_point()->top_of_stack_);
0054 }
0055 };
0056
0057 template <typename, typename...>
0058 class awaitable_handler;
0059
0060 template <typename Executor>
0061 class awaitable_handler<Executor>
0062 : public awaitable_handler_base<Executor, void>
0063 {
0064 public:
0065 using awaitable_handler_base<Executor, void>::awaitable_handler_base;
0066
0067 void operator()()
0068 {
0069 this->frame()->attach_thread(this);
0070 this->frame()->return_void();
0071 this->frame()->clear_cancellation_slot();
0072 this->frame()->pop_frame();
0073 this->pump();
0074 }
0075 };
0076
0077 template <typename Executor>
0078 class awaitable_handler<Executor, boost::system::error_code>
0079 : public awaitable_handler_base<Executor, void>
0080 {
0081 public:
0082 using awaitable_handler_base<Executor, void>::awaitable_handler_base;
0083
0084 void operator()(const boost::system::error_code& ec)
0085 {
0086 this->frame()->attach_thread(this);
0087 if (ec)
0088 this->frame()->set_error(ec);
0089 else
0090 this->frame()->return_void();
0091 this->frame()->clear_cancellation_slot();
0092 this->frame()->pop_frame();
0093 this->pump();
0094 }
0095 };
0096
0097 template <typename Executor>
0098 class awaitable_handler<Executor, std::exception_ptr>
0099 : public awaitable_handler_base<Executor, void>
0100 {
0101 public:
0102 using awaitable_handler_base<Executor, void>::awaitable_handler_base;
0103
0104 void operator()(std::exception_ptr ex)
0105 {
0106 this->frame()->attach_thread(this);
0107 if (ex)
0108 this->frame()->set_except(ex);
0109 else
0110 this->frame()->return_void();
0111 this->frame()->clear_cancellation_slot();
0112 this->frame()->pop_frame();
0113 this->pump();
0114 }
0115 };
0116
0117 template <typename Executor, typename T>
0118 class awaitable_handler<Executor, T>
0119 : public awaitable_handler_base<Executor, T>
0120 {
0121 public:
0122 using awaitable_handler_base<Executor, T>::awaitable_handler_base;
0123
0124 template <typename Arg>
0125 void operator()(Arg&& arg)
0126 {
0127 this->frame()->attach_thread(this);
0128 this->frame()->return_value(std::forward<Arg>(arg));
0129 this->frame()->clear_cancellation_slot();
0130 this->frame()->pop_frame();
0131 this->pump();
0132 }
0133 };
0134
0135 template <typename Executor, typename T>
0136 class awaitable_handler<Executor, boost::system::error_code, T>
0137 : public awaitable_handler_base<Executor, T>
0138 {
0139 public:
0140 using awaitable_handler_base<Executor, T>::awaitable_handler_base;
0141
0142 template <typename Arg>
0143 void operator()(const boost::system::error_code& ec, Arg&& arg)
0144 {
0145 this->frame()->attach_thread(this);
0146 if (ec)
0147 this->frame()->set_error(ec);
0148 else
0149 this->frame()->return_value(std::forward<Arg>(arg));
0150 this->frame()->clear_cancellation_slot();
0151 this->frame()->pop_frame();
0152 this->pump();
0153 }
0154 };
0155
0156 template <typename Executor, typename T>
0157 class awaitable_handler<Executor, std::exception_ptr, T>
0158 : public awaitable_handler_base<Executor, T>
0159 {
0160 public:
0161 using awaitable_handler_base<Executor, T>::awaitable_handler_base;
0162
0163 template <typename Arg>
0164 void operator()(std::exception_ptr ex, Arg&& arg)
0165 {
0166 this->frame()->attach_thread(this);
0167 if (ex)
0168 this->frame()->set_except(ex);
0169 else
0170 this->frame()->return_value(std::forward<Arg>(arg));
0171 this->frame()->clear_cancellation_slot();
0172 this->frame()->pop_frame();
0173 this->pump();
0174 }
0175 };
0176
0177 template <typename Executor, typename... Ts>
0178 class awaitable_handler
0179 : public awaitable_handler_base<Executor, std::tuple<Ts...>>
0180 {
0181 public:
0182 using awaitable_handler_base<Executor,
0183 std::tuple<Ts...>>::awaitable_handler_base;
0184
0185 template <typename... Args>
0186 void operator()(Args&&... args)
0187 {
0188 this->frame()->attach_thread(this);
0189 this->frame()->return_values(std::forward<Args>(args)...);
0190 this->frame()->clear_cancellation_slot();
0191 this->frame()->pop_frame();
0192 this->pump();
0193 }
0194 };
0195
0196 template <typename Executor, typename... Ts>
0197 class awaitable_handler<Executor, boost::system::error_code, Ts...>
0198 : public awaitable_handler_base<Executor, std::tuple<Ts...>>
0199 {
0200 public:
0201 using awaitable_handler_base<Executor,
0202 std::tuple<Ts...>>::awaitable_handler_base;
0203
0204 template <typename... Args>
0205 void operator()(const boost::system::error_code& ec, Args&&... args)
0206 {
0207 this->frame()->attach_thread(this);
0208 if (ec)
0209 this->frame()->set_error(ec);
0210 else
0211 this->frame()->return_values(std::forward<Args>(args)...);
0212 this->frame()->clear_cancellation_slot();
0213 this->frame()->pop_frame();
0214 this->pump();
0215 }
0216 };
0217
0218 template <typename Executor, typename... Ts>
0219 class awaitable_handler<Executor, std::exception_ptr, Ts...>
0220 : public awaitable_handler_base<Executor, std::tuple<Ts...>>
0221 {
0222 public:
0223 using awaitable_handler_base<Executor,
0224 std::tuple<Ts...>>::awaitable_handler_base;
0225
0226 template <typename... Args>
0227 void operator()(std::exception_ptr ex, Args&&... args)
0228 {
0229 this->frame()->attach_thread(this);
0230 if (ex)
0231 this->frame()->set_except(ex);
0232 else
0233 this->frame()->return_values(std::forward<Args>(args)...);
0234 this->frame()->clear_cancellation_slot();
0235 this->frame()->pop_frame();
0236 this->pump();
0237 }
0238 };
0239
0240 }
0241
0242 #if !defined(GENERATING_DOCUMENTATION)
0243
0244 #if defined(_MSC_VER)
0245 template <typename T>
0246 T dummy_return()
0247 {
0248 return std::move(*static_cast<T*>(nullptr));
0249 }
0250
0251 template <>
0252 inline void dummy_return()
0253 {
0254 }
0255 #endif
0256
0257 template <typename Executor, typename R, typename... Args>
0258 class async_result<use_awaitable_t<Executor>, R(Args...)>
0259 {
0260 public:
0261 typedef typename detail::awaitable_handler<
0262 Executor, decay_t<Args>...> handler_type;
0263 typedef typename handler_type::awaitable_type return_type;
0264
0265 template <typename Initiation, typename... InitArgs>
0266 #if defined(__APPLE_CC__) && (__clang_major__ == 13)
0267 __attribute__((noinline))
0268 #endif
0269 static handler_type* do_init(
0270 detail::awaitable_frame_base<Executor>* frame, Initiation& initiation,
0271 use_awaitable_t<Executor> u, InitArgs&... args)
0272 {
0273 (void)u;
0274 BOOST_ASIO_HANDLER_LOCATION((u.file_name_, u.line_, u.function_name_));
0275 handler_type handler(frame->detach_thread());
0276 std::move(initiation)(std::move(handler), std::move(args)...);
0277 return nullptr;
0278 }
0279
0280 template <typename Initiation, typename... InitArgs>
0281 static return_type initiate(Initiation initiation,
0282 use_awaitable_t<Executor> u, InitArgs... args)
0283 {
0284 co_await [&] (auto* frame)
0285 {
0286 return do_init(frame, initiation, u, args...);
0287 };
0288
0289 for (;;) {}
0290 #if defined(_MSC_VER)
0291 co_return dummy_return<typename return_type::value_type>();
0292 #endif
0293 }
0294 };
0295
0296 #endif
0297
0298 }
0299 }
0300
0301 #include <boost/asio/detail/pop_options.hpp>
0302
0303 #endif