]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/impl/use_awaitable.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / asio / impl / use_awaitable.hpp
CommitLineData
92f5a8d4
TL
1//
2// impl/use_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_IMPL_USE_AWAITABLE_HPP
12#define BOOST_ASIO_IMPL_USE_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#include <boost/asio/async_result.hpp>
20
21#include <boost/asio/detail/push_options.hpp>
22
23namespace boost {
24namespace asio {
25namespace detail {
26
27template <typename Executor, typename T>
28class awaitable_handler_base
29 : public awaitable_thread<Executor>
30{
31public:
32 typedef void result_type;
33 typedef awaitable<T, Executor> awaitable_type;
34
35 // Construct from the entry point of a new thread of execution.
36 awaitable_handler_base(awaitable<void, Executor> a, const Executor& ex)
37 : awaitable_thread<Executor>(std::move(a), ex)
38 {
39 }
40
41 // Transfer ownership from another awaitable_thread.
42 explicit awaitable_handler_base(awaitable_thread<Executor>* h)
43 : awaitable_thread<Executor>(std::move(*h))
44 {
45 }
46
47protected:
48 awaitable_frame<T, Executor>* frame() noexcept
49 {
50 return static_cast<awaitable_frame<T, Executor>*>(this->top_of_stack_);
51 }
52};
53
54template <typename, typename...>
55class awaitable_handler;
56
57template <typename Executor>
58class awaitable_handler<Executor, void>
59 : public awaitable_handler_base<Executor, void>
60{
61public:
62 using awaitable_handler_base<Executor, void>::awaitable_handler_base;
63
64 void operator()()
65 {
66 this->frame()->attach_thread(this);
67 this->frame()->return_void();
68 this->frame()->pop_frame();
69 this->pump();
70 }
71};
72
73template <typename Executor>
74class awaitable_handler<Executor, boost::system::error_code>
75 : public awaitable_handler_base<Executor, void>
76{
77public:
78 using awaitable_handler_base<Executor, void>::awaitable_handler_base;
79
80 void operator()(const boost::system::error_code& ec)
81 {
82 this->frame()->attach_thread(this);
83 if (ec)
84 this->frame()->set_error(ec);
85 else
86 this->frame()->return_void();
87 this->frame()->pop_frame();
88 this->pump();
89 }
90};
91
92template <typename Executor>
93class awaitable_handler<Executor, std::exception_ptr>
94 : public awaitable_handler_base<Executor, void>
95{
96public:
97 using awaitable_handler_base<Executor, void>::awaitable_handler_base;
98
99 void operator()(std::exception_ptr ex)
100 {
101 this->frame()->attach_thread(this);
102 if (ex)
103 this->frame()->set_except(ex);
104 else
105 this->frame()->return_void();
106 this->frame()->pop_frame();
107 this->pump();
108 }
109};
110
111template <typename Executor, typename T>
112class awaitable_handler<Executor, T>
113 : public awaitable_handler_base<Executor, T>
114{
115public:
116 using awaitable_handler_base<Executor, T>::awaitable_handler_base;
117
118 template <typename Arg>
119 void operator()(Arg&& arg)
120 {
121 this->frame()->attach_thread(this);
122 this->frame()->return_value(std::forward<Arg>(arg));
123 this->frame()->pop_frame();
124 this->pump();
125 }
126};
127
128template <typename Executor, typename T>
129class awaitable_handler<Executor, boost::system::error_code, T>
130 : public awaitable_handler_base<Executor, T>
131{
132public:
133 using awaitable_handler_base<Executor, T>::awaitable_handler_base;
134
135 template <typename Arg>
136 void operator()(const boost::system::error_code& ec, Arg&& arg)
137 {
138 this->frame()->attach_thread(this);
139 if (ec)
140 this->frame()->set_error(ec);
141 else
142 this->frame()->return_value(std::forward<Arg>(arg));
143 this->frame()->pop_frame();
144 this->pump();
145 }
146};
147
148template <typename Executor, typename T>
149class awaitable_handler<Executor, std::exception_ptr, T>
150 : public awaitable_handler_base<Executor, T>
151{
152public:
153 using awaitable_handler_base<Executor, T>::awaitable_handler_base;
154
155 template <typename Arg>
156 void operator()(std::exception_ptr ex, Arg&& arg)
157 {
158 this->frame()->attach_thread(this);
159 if (ex)
160 this->frame()->set_except(ex);
161 else
162 this->frame()->return_value(std::forward<Arg>(arg));
163 this->frame()->pop_frame();
164 this->pump();
165 }
166};
167
168template <typename Executor, typename... Ts>
169class awaitable_handler
170 : public awaitable_handler_base<Executor, std::tuple<Ts...>>
171{
172public:
173 using awaitable_handler_base<Executor,
174 std::tuple<Ts...>>::awaitable_handler_base;
175
176 template <typename... Args>
177 void operator()(Args&&... args)
178 {
179 this->frame()->attach_thread(this);
180 this->frame()->return_values(std::forward<Args>(args)...);
181 this->frame()->pop_frame();
182 this->pump();
183 }
184};
185
186template <typename Executor, typename... Ts>
187class awaitable_handler<Executor, boost::system::error_code, Ts...>
188 : public awaitable_handler_base<Executor, std::tuple<Ts...>>
189{
190public:
191 using awaitable_handler_base<Executor,
192 std::tuple<Ts...>>::awaitable_handler_base;
193
194 template <typename... Args>
195 void operator()(const boost::system::error_code& ec, Args&&... args)
196 {
197 this->frame()->attach_thread(this);
198 if (ec)
199 this->frame()->set_error(ec);
200 else
201 this->frame()->return_values(std::forward<Args>(args)...);
202 this->frame()->pop_frame();
203 this->pump();
204 }
205};
206
207template <typename Executor, typename... Ts>
208class awaitable_handler<Executor, std::exception_ptr, Ts...>
209 : public awaitable_handler_base<Executor, std::tuple<Ts...>>
210{
211public:
212 using awaitable_handler_base<Executor,
213 std::tuple<Ts...>>::awaitable_handler_base;
214
215 template <typename... Args>
216 void operator()(std::exception_ptr ex, Args&&... args)
217 {
218 this->frame()->attach_thread(this);
219 if (ex)
220 this->frame()->set_except(ex);
221 else
222 this->frame()->return_values(std::forward<Args>(args)...);
223 this->frame()->pop_frame();
224 this->pump();
225 }
226};
227
228} // namespace detail
229
230#if !defined(GENERATING_DOCUMENTATION)
231
232template <typename Executor, typename R, typename... Args>
233class async_result<use_awaitable_t<Executor>, R(Args...)>
234{
235public:
236 typedef typename detail::awaitable_handler<
237 Executor, typename decay<Args>::type...> handler_type;
238 typedef typename handler_type::awaitable_type return_type;
239
240#if defined(_MSC_VER)
241 template <typename T>
242 static T dummy_return()
243 {
244 return std::move(*static_cast<T*>(nullptr));
245 }
246
247 template <>
248 static void dummy_return()
249 {
250 }
251#endif // defined(_MSC_VER)
252
253 template <typename Initiation, typename... InitArgs>
254 static return_type initiate(Initiation initiation,
255 use_awaitable_t<Executor>, InitArgs... args)
256 {
257 co_await [&](auto* frame)
258 {
259 handler_type handler(frame->detach_thread());
260 std::move(initiation)(std::move(handler), std::move(args)...);
261 return static_cast<handler_type*>(nullptr);
262 };
263
264 for (;;) {} // Never reached.
265#if defined(_MSC_VER)
266 co_return dummy_return<typename return_type::value_type>();
267#endif // defined(_MSC_VER)
268 }
269};
270
271#endif // !defined(GENERATING_DOCUMENTATION)
272
273} // namespace asio
274} // namespace boost
275
276#include <boost/asio/detail/pop_options.hpp>
277
278#endif // BOOST_ASIO_IMPL_USE_AWAITABLE_HPP