Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:23:35

0001 //
0002 // impl/use_awaitable.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 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 #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   // Construct from the entry point of a new thread of execution.
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   // Transfer ownership from another awaitable_thread.
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 } // namespace detail
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 // defined(_MSC_VER)
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 // defined(__APPLE_CC__) && (__clang_major__ == 13)
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 (;;) {} // Never reached.
0223 #if defined(_MSC_VER)
0224     co_return dummy_return<typename return_type::value_type>();
0225 #endif // defined(_MSC_VER)
0226   }
0227 };
0228 
0229 #endif // !defined(GENERATING_DOCUMENTATION)
0230 
0231 } // namespace asio
0232 } // namespace boost
0233 
0234 #include <boost/asio/detail/pop_options.hpp>
0235 
0236 #endif // BOOST_ASIO_IMPL_USE_AWAITABLE_HPP