]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/execution/submit.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / asio / execution / submit.hpp
1 //
2 // execution/submit.hpp
3 // ~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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_EXECUTION_SUBMIT_HPP
12 #define BOOST_ASIO_EXECUTION_SUBMIT_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/detail/type_traits.hpp>
20 #include <boost/asio/execution/detail/submit_receiver.hpp>
21 #include <boost/asio/execution/executor.hpp>
22 #include <boost/asio/execution/receiver.hpp>
23 #include <boost/asio/execution/sender.hpp>
24 #include <boost/asio/execution/start.hpp>
25 #include <boost/asio/traits/submit_member.hpp>
26 #include <boost/asio/traits/submit_free.hpp>
27
28 #include <boost/asio/detail/push_options.hpp>
29
30 #if defined(GENERATING_DOCUMENTATION)
31
32 namespace boost {
33 namespace asio {
34 namespace execution {
35
36 /// A customisation point that submits a sender to a receiver.
37 /**
38 * The name <tt>execution::submit</tt> denotes a customisation point object. For
39 * some subexpressions <tt>s</tt> and <tt>r</tt>, let <tt>S</tt> be a type such
40 * that <tt>decltype((s))</tt> is <tt>S</tt> and let <tt>R</tt> be a type such
41 * that <tt>decltype((r))</tt> is <tt>R</tt>. The expression
42 * <tt>execution::submit(s, r)</tt> is ill-formed if <tt>sender_to<S, R></tt> is
43 * not <tt>true</tt>. Otherwise, it is expression-equivalent to:
44 *
45 * @li <tt>s.submit(r)</tt>, if that expression is valid and <tt>S</tt> models
46 * <tt>sender</tt>. If the function selected does not submit the receiver
47 * object <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with
48 * no diagnostic required.
49 *
50 * @li Otherwise, <tt>submit(s, r)</tt>, if that expression is valid and
51 * <tt>S</tt> models <tt>sender</tt>, with overload resolution performed in a
52 * context that includes the declaration <tt>void submit();</tt> and that does
53 * not include a declaration of <tt>execution::submit</tt>. If the function
54 * selected by overload resolution does not submit the receiver object
55 * <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with no
56 * diagnostic required.
57 *
58 * @li Otherwise, <tt>execution::start((new submit_receiver<S,
59 * R>{s,r})->state_)</tt>, where <tt>submit_receiver</tt> is an
60 * implementation-defined class template equivalent to:
61 * @code template<class S, class R>
62 * struct submit_receiver {
63 * struct wrap {
64 * submit_receiver * p_;
65 * template<class...As>
66 * requires receiver_of<R, As...>
67 * void set_value(As&&... as) &&
68 * noexcept(is_nothrow_receiver_of_v<R, As...>) {
69 * execution::set_value(std::move(p_->r_), (As&&) as...);
70 * delete p_;
71 * }
72 * template<class E>
73 * requires receiver<R, E>
74 * void set_error(E&& e) && noexcept {
75 * execution::set_error(std::move(p_->r_), (E&&) e);
76 * delete p_;
77 * }
78 * void set_done() && noexcept {
79 * execution::set_done(std::move(p_->r_));
80 * delete p_;
81 * }
82 * };
83 * remove_cvref_t<R> r_;
84 * connect_result_t<S, wrap> state_;
85 * submit_receiver(S&& s, R&& r)
86 * : r_((R&&) r)
87 * , state_(execution::connect((S&&) s, wrap{this})) {}
88 * };
89 * @endcode
90 */
91 inline constexpr unspecified submit = unspecified;
92
93 /// A type trait that determines whether a @c submit expression is
94 /// well-formed.
95 /**
96 * Class template @c can_submit is a trait that is derived from
97 * @c true_type if the expression <tt>execution::submit(std::declval<R>(),
98 * std::declval<E>())</tt> is well formed; otherwise @c false_type.
99 */
100 template <typename S, typename R>
101 struct can_submit :
102 integral_constant<bool, automatically_determined>
103 {
104 };
105
106 } // namespace execution
107 } // namespace asio
108 } // namespace boost
109
110 #else // defined(GENERATING_DOCUMENTATION)
111
112 namespace asio_execution_submit_fn {
113
114 using boost::asio::declval;
115 using boost::asio::enable_if;
116 using boost::asio::execution::is_sender_to;
117 using boost::asio::traits::submit_free;
118 using boost::asio::traits::submit_member;
119
120 void submit();
121
122 enum overload_type
123 {
124 call_member,
125 call_free,
126 adapter,
127 ill_formed
128 };
129
130 template <typename S, typename R, typename = void>
131 struct call_traits
132 {
133 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
134 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
135 typedef void result_type;
136 };
137
138 template <typename S, typename R>
139 struct call_traits<S, void(R),
140 typename enable_if<
141 (
142 submit_member<S, R>::is_valid
143 &&
144 is_sender_to<S, R>::value
145 )
146 >::type> :
147 submit_member<S, R>
148 {
149 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);
150 };
151
152 template <typename S, typename R>
153 struct call_traits<S, void(R),
154 typename enable_if<
155 (
156 !submit_member<S, R>::is_valid
157 &&
158 submit_free<S, R>::is_valid
159 &&
160 is_sender_to<S, R>::value
161 )
162 >::type> :
163 submit_free<S, R>
164 {
165 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);
166 };
167
168 template <typename S, typename R>
169 struct call_traits<S, void(R),
170 typename enable_if<
171 (
172 !submit_member<S, R>::is_valid
173 &&
174 !submit_free<S, R>::is_valid
175 &&
176 is_sender_to<S, R>::value
177 )
178 >::type>
179 {
180 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);
181 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
182 typedef void result_type;
183 };
184
185 struct impl
186 {
187 #if defined(BOOST_ASIO_HAS_MOVE)
188 template <typename S, typename R>
189 BOOST_ASIO_CONSTEXPR typename enable_if<
190 call_traits<S, void(R)>::overload == call_member,
191 typename call_traits<S, void(R)>::result_type
192 >::type
193 operator()(S&& s, R&& r) const
194 BOOST_ASIO_NOEXCEPT_IF((
195 call_traits<S, void(R)>::is_noexcept))
196 {
197 return BOOST_ASIO_MOVE_CAST(S)(s).submit(BOOST_ASIO_MOVE_CAST(R)(r));
198 }
199
200 template <typename S, typename R>
201 BOOST_ASIO_CONSTEXPR typename enable_if<
202 call_traits<S, void(R)>::overload == call_free,
203 typename call_traits<S, void(R)>::result_type
204 >::type
205 operator()(S&& s, R&& r) const
206 BOOST_ASIO_NOEXCEPT_IF((
207 call_traits<S, void(R)>::is_noexcept))
208 {
209 return submit(BOOST_ASIO_MOVE_CAST(S)(s), BOOST_ASIO_MOVE_CAST(R)(r));
210 }
211
212 template <typename S, typename R>
213 BOOST_ASIO_CONSTEXPR typename enable_if<
214 call_traits<S, void(R)>::overload == adapter,
215 typename call_traits<S, void(R)>::result_type
216 >::type
217 operator()(S&& s, R&& r) const
218 BOOST_ASIO_NOEXCEPT_IF((
219 call_traits<S, void(R)>::is_noexcept))
220 {
221 return boost::asio::execution::start(
222 (new boost::asio::execution::detail::submit_receiver<S, R>(
223 BOOST_ASIO_MOVE_CAST(S)(s), BOOST_ASIO_MOVE_CAST(R)(r)))->state_);
224 }
225 #else // defined(BOOST_ASIO_HAS_MOVE)
226 template <typename S, typename R>
227 BOOST_ASIO_CONSTEXPR typename enable_if<
228 call_traits<S&, void(R&)>::overload == call_member,
229 typename call_traits<S&, void(R&)>::result_type
230 >::type
231 operator()(S& s, R& r) const
232 BOOST_ASIO_NOEXCEPT_IF((
233 call_traits<S&, void(R&)>::is_noexcept))
234 {
235 return s.submit(r);
236 }
237
238 template <typename S, typename R>
239 BOOST_ASIO_CONSTEXPR typename enable_if<
240 call_traits<const S&, void(R&)>::overload == call_member,
241 typename call_traits<const S&, void(R&)>::result_type
242 >::type
243 operator()(const S& s, R& r) const
244 BOOST_ASIO_NOEXCEPT_IF((
245 call_traits<const S&, void(R&)>::is_noexcept))
246 {
247 return s.submit(r);
248 }
249
250 template <typename S, typename R>
251 BOOST_ASIO_CONSTEXPR typename enable_if<
252 call_traits<S&, void(R&)>::overload == call_free,
253 typename call_traits<S&, void(R&)>::result_type
254 >::type
255 operator()(S& s, R& r) const
256 BOOST_ASIO_NOEXCEPT_IF((
257 call_traits<S&, void(R&)>::is_noexcept))
258 {
259 return submit(s, r);
260 }
261
262 template <typename S, typename R>
263 BOOST_ASIO_CONSTEXPR typename enable_if<
264 call_traits<const S&, void(R&)>::overload == call_free,
265 typename call_traits<const S&, void(R&)>::result_type
266 >::type
267 operator()(const S& s, R& r) const
268 BOOST_ASIO_NOEXCEPT_IF((
269 call_traits<const S&, void(R&)>::is_noexcept))
270 {
271 return submit(s, r);
272 }
273
274 template <typename S, typename R>
275 BOOST_ASIO_CONSTEXPR typename enable_if<
276 call_traits<S&, void(R&)>::overload == adapter,
277 typename call_traits<S&, void(R&)>::result_type
278 >::type
279 operator()(S& s, R& r) const
280 BOOST_ASIO_NOEXCEPT_IF((
281 call_traits<S&, void(R&)>::is_noexcept))
282 {
283 return boost::asio::execution::start(
284 (new boost::asio::execution::detail::submit_receiver<
285 S&, R&>(s, r))->state_);
286 }
287
288 template <typename S, typename R>
289 BOOST_ASIO_CONSTEXPR typename enable_if<
290 call_traits<const S&, void(R&)>::overload == adapter,
291 typename call_traits<const S&, void(R&)>::result_type
292 >::type
293 operator()(const S& s, R& r) const
294 BOOST_ASIO_NOEXCEPT_IF((
295 call_traits<const S&, void(R&)>::is_noexcept))
296 {
297 boost::asio::execution::start(
298 (new boost::asio::execution::detail::submit_receiver<
299 const S&, R&>(s, r))->state_);
300 }
301
302 template <typename S, typename R>
303 BOOST_ASIO_CONSTEXPR typename enable_if<
304 call_traits<S&, void(const R&)>::overload == call_member,
305 typename call_traits<S&, void(const R&)>::result_type
306 >::type
307 operator()(S& s, const R& r) const
308 BOOST_ASIO_NOEXCEPT_IF((
309 call_traits<S&, void(const R&)>::is_noexcept))
310 {
311 return s.submit(r);
312 }
313
314 template <typename S, typename R>
315 BOOST_ASIO_CONSTEXPR typename enable_if<
316 call_traits<const S&, void(const R&)>::overload == call_member,
317 typename call_traits<const S&, void(const R&)>::result_type
318 >::type
319 operator()(const S& s, const R& r) const
320 BOOST_ASIO_NOEXCEPT_IF((
321 call_traits<const S&, void(const R&)>::is_noexcept))
322 {
323 return s.submit(r);
324 }
325
326 template <typename S, typename R>
327 BOOST_ASIO_CONSTEXPR typename enable_if<
328 call_traits<S&, void(const R&)>::overload == call_free,
329 typename call_traits<S&, void(const R&)>::result_type
330 >::type
331 operator()(S& s, const R& r) const
332 BOOST_ASIO_NOEXCEPT_IF((
333 call_traits<S&, void(const R&)>::is_noexcept))
334 {
335 return submit(s, r);
336 }
337
338 template <typename S, typename R>
339 BOOST_ASIO_CONSTEXPR typename enable_if<
340 call_traits<const S&, void(const R&)>::overload == call_free,
341 typename call_traits<const S&, void(const R&)>::result_type
342 >::type
343 operator()(const S& s, const R& r) const
344 BOOST_ASIO_NOEXCEPT_IF((
345 call_traits<const S&, void(const R&)>::is_noexcept))
346 {
347 return submit(s, r);
348 }
349
350 template <typename S, typename R>
351 BOOST_ASIO_CONSTEXPR typename enable_if<
352 call_traits<S&, void(const R&)>::overload == adapter,
353 typename call_traits<S&, void(const R&)>::result_type
354 >::type
355 operator()(S& s, const R& r) const
356 BOOST_ASIO_NOEXCEPT_IF((
357 call_traits<S&, void(const R&)>::is_noexcept))
358 {
359 boost::asio::execution::start(
360 (new boost::asio::execution::detail::submit_receiver<
361 S&, const R&>(s, r))->state_);
362 }
363
364 template <typename S, typename R>
365 BOOST_ASIO_CONSTEXPR typename enable_if<
366 call_traits<const S&, void(const R&)>::overload == adapter,
367 typename call_traits<const S&, void(const R&)>::result_type
368 >::type
369 operator()(const S& s, const R& r) const
370 BOOST_ASIO_NOEXCEPT_IF((
371 call_traits<const S&, void(const R&)>::is_noexcept))
372 {
373 boost::asio::execution::start(
374 (new boost::asio::execution::detail::submit_receiver<
375 const S&, const R&>(s, r))->state_);
376 }
377 #endif // defined(BOOST_ASIO_HAS_MOVE)
378 };
379
380 template <typename T = impl>
381 struct static_instance
382 {
383 static const T instance;
384 };
385
386 template <typename T>
387 const T static_instance<T>::instance = {};
388
389 } // namespace asio_execution_submit_fn
390 namespace boost {
391 namespace asio {
392 namespace execution {
393 namespace {
394
395 static BOOST_ASIO_CONSTEXPR const asio_execution_submit_fn::impl&
396 submit = asio_execution_submit_fn::static_instance<>::instance;
397
398 } // namespace
399
400 template <typename S, typename R>
401 struct can_submit :
402 integral_constant<bool,
403 asio_execution_submit_fn::call_traits<S, void(R)>::overload !=
404 asio_execution_submit_fn::ill_formed>
405 {
406 };
407
408 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
409
410 template <typename S, typename R>
411 constexpr bool can_submit_v = can_submit<S, R>::value;
412
413 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
414
415 template <typename S, typename R>
416 struct is_nothrow_submit :
417 integral_constant<bool,
418 asio_execution_submit_fn::call_traits<S, void(R)>::is_noexcept>
419 {
420 };
421
422 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
423
424 template <typename S, typename R>
425 constexpr bool is_nothrow_submit_v
426 = is_nothrow_submit<S, R>::value;
427
428 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
429
430 template <typename S, typename R>
431 struct submit_result
432 {
433 typedef typename asio_execution_submit_fn::call_traits<
434 S, void(R)>::result_type type;
435 };
436
437 namespace detail {
438
439 template <typename S, typename R>
440 void submit_helper(BOOST_ASIO_MOVE_ARG(S) s, BOOST_ASIO_MOVE_ARG(R) r)
441 {
442 execution::submit(BOOST_ASIO_MOVE_CAST(S)(s), BOOST_ASIO_MOVE_CAST(R)(r));
443 }
444
445 } // namespace detail
446 } // namespace execution
447 } // namespace asio
448 } // namespace boost
449
450 #endif // defined(GENERATING_DOCUMENTATION)
451
452 #include <boost/asio/detail/pop_options.hpp>
453
454 #endif // BOOST_ASIO_EXECUTION_SUBMIT_HPP