1 // 2 // awaitable.hpp 3 // ~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2019 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 #include <experimental/coroutine> 23 #include <boost/asio/executor.hpp> 24 25 #include <boost/asio/detail/push_options.hpp> 26 27 namespace boost { 28 namespace asio { 29 namespace detail { 30 31 using std::experimental::coroutine_handle; 32 using std::experimental::suspend_always; 33 34 template <typename> class awaitable_thread; 35 template <typename, typename> class awaitable_frame; 36 37 } // namespace detail 38 39 /// The return type of a coroutine or asynchronous operation. 40 template <typename T, typename Executor = executor> 41 class awaitable 42 { 43 public: 44 /// The type of the awaited value. 45 typedef T value_type; 46 47 /// The executor type that will be used for the coroutine. 48 typedef Executor executor_type; 49 50 /// Default constructor. awaitable()51 constexpr awaitable() noexcept 52 : frame_(nullptr) 53 { 54 } 55 56 /// Move constructor. awaitable(awaitable && other)57 awaitable(awaitable&& other) noexcept 58 : frame_(std::exchange(other.frame_, nullptr)) 59 { 60 } 61 62 /// Destructor ~awaitable()63 ~awaitable() 64 { 65 if (frame_) 66 frame_->destroy(); 67 } 68 69 /// Checks if the awaitable refers to a future result. valid() const70 bool valid() const noexcept 71 { 72 return !!frame_; 73 } 74 75 #if !defined(GENERATING_DOCUMENTATION) 76 77 // Support for co_await keyword. await_ready() const78 bool await_ready() const noexcept 79 { 80 return false; 81 } 82 83 // Support for co_await keyword. 84 template <class U> await_suspend(detail::coroutine_handle<detail::awaitable_frame<U,Executor>> h)85 void await_suspend( 86 detail::coroutine_handle<detail::awaitable_frame<U, Executor>> h) 87 { 88 frame_->push_frame(&h.promise()); 89 } 90 91 // Support for co_await keyword. await_resume()92 T await_resume() 93 { 94 return frame_->get(); 95 } 96 97 #endif // !defined(GENERATING_DOCUMENTATION) 98 99 private: 100 template <typename> friend class detail::awaitable_thread; 101 template <typename, typename> friend class detail::awaitable_frame; 102 103 // Not copy constructible or copy assignable. 104 awaitable(const awaitable&) = delete; 105 awaitable& operator=(const awaitable&) = delete; 106 107 // Construct the awaitable from a coroutine's frame object. awaitable(detail::awaitable_frame<T,Executor> * a)108 explicit awaitable(detail::awaitable_frame<T, Executor>* a) 109 : frame_(a) 110 { 111 } 112 113 detail::awaitable_frame<T, Executor>* frame_; 114 }; 115 116 } // namespace asio 117 } // namespace boost 118 119 #include <boost/asio/detail/pop_options.hpp> 120 121 #include <boost/asio/impl/awaitable.hpp> 122 123 #endif // defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION) 124 125 #endif // BOOST_ASIO_AWAITABLE_HPP 126