]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
11fdf7f2
TL
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
28namespace boost {
29namespace asio {
30namespace experimental {
31namespace detail {
32
33using std::experimental::coroutine_handle;
34
35template <typename> class awaiter;
36template <typename> class awaitee_base;
37template <typename, typename> class awaitee;
38template <typename, typename> class await_handler_base;
39template <typename Executor, typename F, typename CompletionToken>
40auto co_spawn(const Executor& ex, F&& f, CompletionToken&& token);
41
42} // namespace detail
43
44namespace this_coro {
45
46/// Awaitable type that returns a completion token for the current coroutine.
47struct token_t {};
48
49/// Awaitable object that returns a completion token for the current coroutine.
50constexpr inline token_t token() { return {}; }
51
52/// Awaitable type that returns the executor of the current coroutine.
53struct executor_t {};
54
55/// Awaitable object that returns the executor of the current coroutine.
56constexpr 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 */
78template <typename Executor>
79class await_token
80{
81public:
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
103private:
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.
120template <typename T, typename Executor = strand<executor>>
121class awaitable
122{
123public:
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
176private:
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.
191template <typename Executor, typename F, typename CompletionToken,
192 typename = typename enable_if<is_executor<Executor>::value>::type>
193inline 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.
200template <typename ExecutionContext, typename F, typename CompletionToken,
201 typename = typename enable_if<
202 is_convertible<ExecutionContext&, execution_context&>::value>::type>
203inline 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.
210template <typename Executor, typename F, typename CompletionToken>
211inline 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