]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/experimental/co_spawn.hpp
Add patch for failing prerm scripts
[ceph.git] / ceph / src / boost / boost / asio / experimental / co_spawn.hpp
1 //
2 // experimental/co_spawn.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2018 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_EXPERIMENTAL_CO_SPAWN_HPP
12 #define BOOST_ASIO_EXPERIMENTAL_CO_SPAWN_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 #include <boost/asio/strand.hpp>
25
26 #include <boost/asio/detail/push_options.hpp>
27
28 namespace boost {
29 namespace asio {
30 namespace experimental {
31 namespace detail {
32
33 using std::experimental::coroutine_handle;
34
35 template <typename> class awaiter;
36 template <typename> class awaitee_base;
37 template <typename, typename> class awaitee;
38 template <typename, typename> class await_handler_base;
39 template <typename Executor, typename F, typename CompletionToken>
40 auto co_spawn(const Executor& ex, F&& f, CompletionToken&& token);
41
42 } // namespace detail
43
44 namespace this_coro {
45
46 /// Awaitable type that returns a completion token for the current coroutine.
47 struct token_t {};
48
49 /// Awaitable object that returns a completion token for the current coroutine.
50 constexpr inline token_t token() { return {}; }
51
52 /// Awaitable type that returns the executor of the current coroutine.
53 struct executor_t {};
54
55 /// Awaitable object that returns the executor of the current coroutine.
56 constexpr inline executor_t executor() { return {}; }
57
58 } // namespace this_coro
59
60 /// A completion token that represents the currently executing coroutine.
61 /**
62 * The await_token class is used to represent the currently executing
63 * coroutine. An await_token may be passed as a handler to an asynchronous
64 * operation. For example:
65 *
66 * @code awaitable<void> my_coroutine()
67 * {
68 * await_token token = co_await this_coro::token();
69 * ...
70 * std::size_t n = co_await my_socket.async_read_some(buffer, token);
71 * ...
72 * } @endcode
73 *
74 * The initiating function (async_read_some in the above example) suspends the
75 * current coroutine. The coroutine is resumed when the asynchronous operation
76 * completes, and the result of the operation is returned.
77 */
78 template <typename Executor>
79 class await_token
80 {
81 public:
82 /// The associated executor type.
83 typedef Executor executor_type;
84
85 /// Copy constructor.
86 await_token(const await_token& other) noexcept
87 : awaiter_(other.awaiter_)
88 {
89 }
90
91 /// Move constructor.
92 await_token(await_token&& other) noexcept
93 : awaiter_(std::exchange(other.awaiter_, nullptr))
94 {
95 }
96
97 /// Get the associated executor.
98 executor_type get_executor() const noexcept
99 {
100 return awaiter_->get_executor();
101 }
102
103 private:
104 // No assignment allowed.
105 await_token& operator=(const await_token&) = delete;
106
107 template <typename> friend class detail::awaitee_base;
108 template <typename, typename> friend class detail::await_handler_base;
109
110 // Private constructor used by awaitee_base.
111 explicit await_token(detail::awaiter<Executor>* a)
112 : awaiter_(a)
113 {
114 }
115
116 detail::awaiter<Executor>* awaiter_;
117 };
118
119 /// The return type of a coroutine or asynchronous operation.
120 template <typename T, typename Executor = strand<executor>>
121 class awaitable
122 {
123 public:
124 /// The type of the awaited value.
125 typedef T value_type;
126
127 /// The executor type that will be used for the coroutine.
128 typedef Executor executor_type;
129
130 /// Move constructor.
131 awaitable(awaitable&& other) noexcept
132 : awaitee_(std::exchange(other.awaitee_, nullptr))
133 {
134 }
135
136 /// Destructor
137 ~awaitable()
138 {
139 if (awaitee_)
140 {
141 detail::coroutine_handle<
142 detail::awaitee<T, Executor>>::from_promise(
143 *awaitee_).destroy();
144 }
145 }
146
147 #if !defined(GENERATING_DOCUMENTATION)
148
149 // Support for co_await keyword.
150 bool await_ready() const noexcept
151 {
152 return awaitee_->ready();
153 }
154
155 // Support for co_await keyword.
156 void await_suspend(detail::coroutine_handle<detail::awaiter<Executor>> h)
157 {
158 awaitee_->attach_caller(h);
159 }
160
161 // Support for co_await keyword.
162 template <class U>
163 void await_suspend(detail::coroutine_handle<detail::awaitee<U, Executor>> h)
164 {
165 awaitee_->attach_caller(h);
166 }
167
168 // Support for co_await keyword.
169 T await_resume()
170 {
171 return awaitee_->get();
172 }
173
174 #endif // !defined(GENERATING_DOCUMENTATION)
175
176 private:
177 template <typename, typename> friend class detail::awaitee;
178 template <typename, typename> friend class detail::await_handler_base;
179
180 // Not copy constructible or copy assignable.
181 awaitable(const awaitable&) = delete;
182 awaitable& operator=(const awaitable&) = delete;
183
184 // Construct the awaitable from a coroutine's promise object.
185 explicit awaitable(detail::awaitee<T, Executor>* a) : awaitee_(a) {}
186
187 detail::awaitee<T, Executor>* awaitee_;
188 };
189
190 /// Spawn a new thread of execution.
191 template <typename Executor, typename F, typename CompletionToken,
192 typename = typename enable_if<is_executor<Executor>::value>::type>
193 inline auto co_spawn(const Executor& ex, F&& f, CompletionToken&& token)
194 {
195 return detail::co_spawn(ex, std::forward<F>(f),
196 std::forward<CompletionToken>(token));
197 }
198
199 /// Spawn a new thread of execution.
200 template <typename ExecutionContext, typename F, typename CompletionToken,
201 typename = typename enable_if<
202 is_convertible<ExecutionContext&, execution_context&>::value>::type>
203 inline auto co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token)
204 {
205 return detail::co_spawn(ctx.get_executor(), std::forward<F>(f),
206 std::forward<CompletionToken>(token));
207 }
208
209 /// Spawn a new thread of execution.
210 template <typename Executor, typename F, typename CompletionToken>
211 inline auto co_spawn(const await_token<Executor>& parent,
212 F&& f, CompletionToken&& token)
213 {
214 return detail::co_spawn(parent.get_executor(), std::forward<F>(f),
215 std::forward<CompletionToken>(token));
216 }
217
218 } // namespace experimental
219 } // namespace asio
220 } // namespace boost
221
222 #include <boost/asio/detail/pop_options.hpp>
223
224 #include <boost/asio/experimental/impl/co_spawn.hpp>
225
226 #endif // defined(BOOST_ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
227
228 #endif // BOOST_ASIO_EXPERIMENTAL_CO_SPAWN_HPP