Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:58

0001 //
0002 // impl/use_awaitable.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // defined(_MSC_VER) && (_MSC_VER >= 1200)
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   // Construct from the entry point of a new thread of execution.
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   // Transfer ownership from another awaitable_thread.
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 } // namespace detail
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 // defined(_MSC_VER)
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 // defined(__APPLE_CC__) && (__clang_major__ == 13)
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 (;;) {} // Never reached.
0290 #if defined(_MSC_VER)
0291     co_return dummy_return<typename return_type::value_type>();
0292 #endif // defined(_MSC_VER)
0293   }
0294 };
0295 
0296 #endif // !defined(GENERATING_DOCUMENTATION)
0297 
0298 } // namespace asio
0299 } // namespace boost
0300 
0301 #include <boost/asio/detail/pop_options.hpp>
0302 
0303 #endif // BOOST_ASIO_IMPL_USE_AWAITABLE_HPP