• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // awaitable.hpp
3 // ~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef BOOST_ASIO_AWAITABLE_HPP
12 #define BOOST_ASIO_AWAITABLE_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include <boost/asio/detail/config.hpp>
19 
20 #if defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
21 
22 #if defined(BOOST_ASIO_HAS_STD_COROUTINE)
23 # include <coroutine>
24 #else // defined(BOOST_ASIO_HAS_STD_COROUTINE)
25 # include <experimental/coroutine>
26 #endif // defined(BOOST_ASIO_HAS_STD_COROUTINE)
27 
28 #include <boost/asio/any_io_executor.hpp>
29 
30 #include <boost/asio/detail/push_options.hpp>
31 
32 namespace boost {
33 namespace asio {
34 namespace detail {
35 
36 #if defined(BOOST_ASIO_HAS_STD_COROUTINE)
37 using std::coroutine_handle;
38 using std::suspend_always;
39 #else // defined(BOOST_ASIO_HAS_STD_COROUTINE)
40 using std::experimental::coroutine_handle;
41 using std::experimental::suspend_always;
42 #endif // defined(BOOST_ASIO_HAS_STD_COROUTINE)
43 
44 template <typename> class awaitable_thread;
45 template <typename, typename> class awaitable_frame;
46 
47 } // namespace detail
48 
49 /// The return type of a coroutine or asynchronous operation.
50 template <typename T, typename Executor = any_io_executor>
51 class awaitable
52 {
53 public:
54   /// The type of the awaited value.
55   typedef T value_type;
56 
57   /// The executor type that will be used for the coroutine.
58   typedef Executor executor_type;
59 
60   /// Default constructor.
awaitable()61   constexpr awaitable() noexcept
62     : frame_(nullptr)
63   {
64   }
65 
66   /// Move constructor.
awaitable(awaitable && other)67   awaitable(awaitable&& other) noexcept
68     : frame_(std::exchange(other.frame_, nullptr))
69   {
70   }
71 
72   /// Destructor
~awaitable()73   ~awaitable()
74   {
75     if (frame_)
76       frame_->destroy();
77   }
78 
79   /// Checks if the awaitable refers to a future result.
valid() const80   bool valid() const noexcept
81   {
82     return !!frame_;
83   }
84 
85 #if !defined(GENERATING_DOCUMENTATION)
86 
87   // Support for co_await keyword.
await_ready() const88   bool await_ready() const noexcept
89   {
90     return false;
91   }
92 
93   // Support for co_await keyword.
94   template <class U>
await_suspend(detail::coroutine_handle<detail::awaitable_frame<U,Executor>> h)95   void await_suspend(
96       detail::coroutine_handle<detail::awaitable_frame<U, Executor>> h)
97   {
98     frame_->push_frame(&h.promise());
99   }
100 
101   // Support for co_await keyword.
await_resume()102   T await_resume()
103   {
104     return awaitable(static_cast<awaitable&&>(*this)).frame_->get();
105   }
106 
107 #endif // !defined(GENERATING_DOCUMENTATION)
108 
109 private:
110   template <typename> friend class detail::awaitable_thread;
111   template <typename, typename> friend class detail::awaitable_frame;
112 
113   // Not copy constructible or copy assignable.
114   awaitable(const awaitable&) = delete;
115   awaitable& operator=(const awaitable&) = delete;
116 
117   // Construct the awaitable from a coroutine's frame object.
awaitable(detail::awaitable_frame<T,Executor> * a)118   explicit awaitable(detail::awaitable_frame<T, Executor>* a)
119     : frame_(a)
120   {
121   }
122 
123   detail::awaitable_frame<T, Executor>* frame_;
124 };
125 
126 } // namespace asio
127 } // namespace boost
128 
129 #include <boost/asio/detail/pop_options.hpp>
130 
131 #include <boost/asio/impl/awaitable.hpp>
132 
133 #endif // defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
134 
135 #endif // BOOST_ASIO_AWAITABLE_HPP
136