]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/experimental/deferred.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / asio / experimental / deferred.hpp
CommitLineData
1e59de90
TL
1//
2// experimental/deferred.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2022 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_DEFERRED_HPP
12#define BOOST_ASIO_EXPERIMENTAL_DEFERRED_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 <tuple>
20#include <boost/asio/associator.hpp>
21#include <boost/asio/async_result.hpp>
22#include <boost/asio/detail/type_traits.hpp>
23
24#include <boost/asio/detail/push_options.hpp>
25
26namespace boost {
27namespace asio {
28namespace experimental {
29
30/// Trait for detecting objects that are usable as deferred operations.
31template <typename T>
32struct is_deferred : false_type
33{
34};
35
36namespace detail {
37
38// Helper trait for getting the completion signature from an async operation.
39
40struct deferred_signature_probe {};
41
42template <typename T>
43struct deferred_signature_probe_result
44{
45 typedef T type;
46};
47
48template <typename T>
49struct deferred_signature
50{
51 typedef typename decltype(
52 declval<T>()(declval<deferred_signature_probe>()))::type type;
53};
54
55// Helper trait for getting the completion signature of the tail in a sequence
56// when invoked with the specified arguments.
57
58template <typename HeadSignature, typename Tail>
59struct deferred_sequence_signature;
60
61template <typename R, typename... Args, typename Tail>
62struct deferred_sequence_signature<R(Args...), Tail>
63{
64 static_assert(
65 !is_same<decltype(declval<Tail>()(declval<Args>()...)), void>::value,
66 "deferred functions must produce a deferred return type");
67
68 typedef typename decltype(
69 declval<Tail>()(declval<Args>()...)(
70 declval<deferred_signature_probe>()))::type type;
71};
72
73// Completion handler for the head component of a deferred sequence.
74template <typename Handler, typename Tail>
75class deferred_sequence_handler
76{
77public:
78 template <typename H, typename T>
79 explicit deferred_sequence_handler(
80 BOOST_ASIO_MOVE_ARG(H) handler, BOOST_ASIO_MOVE_ARG(T) tail)
81 : handler_(BOOST_ASIO_MOVE_CAST(H)(handler)),
82 tail_(BOOST_ASIO_MOVE_CAST(T)(tail))
83 {
84 }
85
86 template <typename... Args>
87 void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
88 {
89 BOOST_ASIO_MOVE_OR_LVALUE(Tail)(tail_)(
90 BOOST_ASIO_MOVE_CAST(Args)(args)...)(
91 BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler_));
92 }
93
94//private:
95 Handler handler_;
96 Tail tail_;
97};
98
99} // namespace detail
100
101/// Used to represent an empty deferred action.
102struct deferred_noop
103{
104 /// No effect.
105 template <typename... Args>
106 void operator()(BOOST_ASIO_MOVE_ARG(Args)...) BOOST_ASIO_RVALUE_REF_QUAL
107 {
108 }
109
110#if defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
111 /// No effect.
112 template <typename... Args>
113 decltype(auto) operator()(BOOST_ASIO_MOVE_ARG(Args)...) const &
114 {
115 }
116#endif // defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
117};
118
119#if !defined(GENERATING_DOCUMENTATION)
120template <>
121struct is_deferred<deferred_noop> : true_type
122{
123};
124#endif // !defined(GENERATING_DOCUMENTATION)
125
126/// Tag type to disambiguate deferred constructors.
127struct deferred_init_tag {};
128
129/// Wraps a function object so that it may be used as an element in a deferred
130/// composition.
131template <typename Function>
132class deferred_function
133{
134public:
135 /// Constructor.
136 template <typename F>
137 BOOST_ASIO_CONSTEXPR explicit deferred_function(
138 deferred_init_tag, BOOST_ASIO_MOVE_ARG(F) function)
139 : function_(BOOST_ASIO_MOVE_CAST(F)(function))
140 {
141 }
142
143 template <typename... Args>
144 decltype(auto) operator()(
145 BOOST_ASIO_MOVE_ARG(Args)... args) BOOST_ASIO_RVALUE_REF_QUAL
146 {
147 return BOOST_ASIO_MOVE_CAST(Function)(function_)(
148 BOOST_ASIO_MOVE_CAST(Args)(args)...);
149 }
150
151#if defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
152 template <typename... Args>
153 decltype(auto) operator()(
154 BOOST_ASIO_MOVE_ARG(Args)... args) const &
155 {
156 return deferred_function(*this)(
157 BOOST_ASIO_MOVE_CAST(Args)(args)...);
158 }
159#endif // defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
160
161//private:
162 Function function_;
163};
164
165#if !defined(GENERATING_DOCUMENTATION)
166template <typename Function>
167struct is_deferred<deferred_function<Function> > : true_type
168{
169};
170#endif // !defined(GENERATING_DOCUMENTATION)
171
172/// Encapsulates deferred values.
173template <typename... Values>
174class BOOST_ASIO_NODISCARD deferred_values
175{
176private:
177 std::tuple<Values...> values_;
178
179 struct initiate
180 {
181 template <typename Handler, typename... V>
182 void operator()(Handler handler, BOOST_ASIO_MOVE_ARG(V)... values)
183 {
184 BOOST_ASIO_MOVE_OR_LVALUE(Handler)(handler)(
185 BOOST_ASIO_MOVE_CAST(V)(values)...);
186 }
187 };
188
189 template <typename CompletionToken, std::size_t... I>
190 decltype(auto) invoke_helper(
191 BOOST_ASIO_MOVE_ARG(CompletionToken) token,
192 std::index_sequence<I...>)
193 {
194 return boost::asio::async_initiate<CompletionToken, void(Values...)>(
195 initiate(), token,
196 std::get<I>(BOOST_ASIO_MOVE_CAST(std::tuple<Values...>)(values_))...);
197 }
198
199public:
200 /// Construct a deferred asynchronous operation from the arguments to an
201 /// initiation function object.
202 template <typename... V>
203 BOOST_ASIO_CONSTEXPR explicit deferred_values(
204 deferred_init_tag, BOOST_ASIO_MOVE_ARG(V)... values)
205 : values_(BOOST_ASIO_MOVE_CAST(V)(values)...)
206 {
207 }
208
209 /// Initiate the deferred operation using the supplied completion token.
210 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>
211 decltype(auto) operator()(
212 BOOST_ASIO_MOVE_ARG(CompletionToken) token) BOOST_ASIO_RVALUE_REF_QUAL
213 {
214 return this->invoke_helper(
215 BOOST_ASIO_MOVE_CAST(CompletionToken)(token),
216 std::index_sequence_for<Values...>());
217 }
218
219#if defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
220 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>
221 decltype(auto) operator()(
222 BOOST_ASIO_MOVE_ARG(CompletionToken) token) const &
223 {
224 return deferred_values(*this)(
225 BOOST_ASIO_MOVE_CAST(CompletionToken)(token));
226 }
227#endif // defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
228};
229
230#if !defined(GENERATING_DOCUMENTATION)
231template <typename... Values>
232struct is_deferred<deferred_values<Values...> > : true_type
233{
234};
235#endif // !defined(GENERATING_DOCUMENTATION)
236
237/// Encapsulates a deferred asynchronous operation.
238template <typename Signature, typename Initiation, typename... InitArgs>
239class BOOST_ASIO_NODISCARD deferred_async_operation
240{
241private:
242 typename decay<Initiation>::type initiation_;
243 typedef std::tuple<typename decay<InitArgs>::type...> init_args_t;
244 init_args_t init_args_;
245
246 template <typename CompletionToken, std::size_t... I>
247 decltype(auto) invoke_helper(
248 BOOST_ASIO_MOVE_ARG(CompletionToken) token,
249 std::index_sequence<I...>)
250 {
251 return boost::asio::async_initiate<CompletionToken, Signature>(
252 BOOST_ASIO_MOVE_CAST(typename decay<Initiation>::type)(initiation_),
253 token, std::get<I>(BOOST_ASIO_MOVE_CAST(init_args_t)(init_args_))...);
254 }
255
256public:
257 /// Construct a deferred asynchronous operation from the arguments to an
258 /// initiation function object.
259 template <typename I, typename... A>
260 BOOST_ASIO_CONSTEXPR explicit deferred_async_operation(
261 deferred_init_tag, BOOST_ASIO_MOVE_ARG(I) initiation,
262 BOOST_ASIO_MOVE_ARG(A)... init_args)
263 : initiation_(BOOST_ASIO_MOVE_CAST(I)(initiation)),
264 init_args_(BOOST_ASIO_MOVE_CAST(A)(init_args)...)
265 {
266 }
267
268 /// Initiate the asynchronous operation using the supplied completion token.
269 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
270 decltype(auto) operator()(
271 BOOST_ASIO_MOVE_ARG(CompletionToken) token) BOOST_ASIO_RVALUE_REF_QUAL
272 {
273 return this->invoke_helper(
274 BOOST_ASIO_MOVE_CAST(CompletionToken)(token),
275 std::index_sequence_for<InitArgs...>());
276 }
277
278#if defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
279 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
280 decltype(auto) operator()(
281 BOOST_ASIO_MOVE_ARG(CompletionToken) token) const &
282 {
283 return deferred_async_operation(*this)(
284 BOOST_ASIO_MOVE_CAST(CompletionToken)(token));
285 }
286#endif // defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
287};
288
289#if !defined(GENERATING_DOCUMENTATION)
290template <typename Signature, typename Initiation, typename... InitArgs>
291struct is_deferred<
292 deferred_async_operation<Signature, Initiation, InitArgs...> > : true_type
293{
294};
295#endif // !defined(GENERATING_DOCUMENTATION)
296
297/// Defines a link between two consecutive operations in a sequence.
298template <typename Head, typename Tail>
299class BOOST_ASIO_NODISCARD deferred_sequence
300{
301private:
302 typedef typename detail::deferred_sequence_signature<
303 typename detail::deferred_signature<Head>::type, Tail>::type
304 signature;
305
306public:
307 template <typename H, typename T>
308 BOOST_ASIO_CONSTEXPR explicit deferred_sequence(deferred_init_tag,
309 BOOST_ASIO_MOVE_ARG(H) head, BOOST_ASIO_MOVE_ARG(T) tail)
310 : head_(BOOST_ASIO_MOVE_CAST(H)(head)),
311 tail_(BOOST_ASIO_MOVE_CAST(T)(tail))
312 {
313 }
314
315 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken>
316 decltype(auto) operator()(
317 BOOST_ASIO_MOVE_ARG(CompletionToken) token) BOOST_ASIO_RVALUE_REF_QUAL
318 {
319 return boost::asio::async_initiate<CompletionToken, signature>(
320 initiate(), token, BOOST_ASIO_MOVE_OR_LVALUE(Head)(head_),
321 BOOST_ASIO_MOVE_OR_LVALUE(Tail)(tail_));
322 }
323
324#if defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
325 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken>
326 decltype(auto) operator()(
327 BOOST_ASIO_MOVE_ARG(CompletionToken) token) const &
328 {
329 return deferred_sequence(*this)(
330 BOOST_ASIO_MOVE_CAST(CompletionToken)(token));
331 }
332#endif // defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
333
334private:
335 struct initiate
336 {
337 template <typename Handler>
338 void operator()(BOOST_ASIO_MOVE_ARG(Handler) handler,
339 Head head, BOOST_ASIO_MOVE_ARG(Tail) tail)
340 {
341 BOOST_ASIO_MOVE_OR_LVALUE(Head)(head)(
342 detail::deferred_sequence_handler<
343 typename decay<Handler>::type,
344 typename decay<Tail>::type>(
345 BOOST_ASIO_MOVE_CAST(Handler)(handler),
346 BOOST_ASIO_MOVE_CAST(Tail)(tail)));
347 }
348 };
349
350 Head head_;
351 Tail tail_;
352};
353
354#if !defined(GENERATING_DOCUMENTATION)
355template <typename Head, typename Tail>
356struct is_deferred<deferred_sequence<Head, Tail> > : true_type
357{
358};
359#endif // !defined(GENERATING_DOCUMENTATION)
360
361/// Used to represent a deferred conditional branch.
362template <typename OnTrue = deferred_noop,
363 typename OnFalse = deferred_noop>
364class BOOST_ASIO_NODISCARD deferred_conditional
365{
366public:
367 /// Construct a deferred conditional with the value to determine which branch
368 /// will be executed.
369 BOOST_ASIO_CONSTEXPR explicit deferred_conditional(bool b)
370 : on_true_(),
371 on_false_(),
372 bool_(b)
373 {
374 }
375
376 /// Invoke the conditional branch bsaed on the stored alue.
377 template <typename... Args>
378 auto operator()(BOOST_ASIO_MOVE_ARG(Args)... args) BOOST_ASIO_RVALUE_REF_QUAL
379 {
380 if (bool_)
381 {
382 return BOOST_ASIO_MOVE_OR_LVALUE(OnTrue)(on_true_)(
383 BOOST_ASIO_MOVE_CAST(Args)(args)...);
384 }
385 else
386 {
387 return BOOST_ASIO_MOVE_OR_LVALUE(OnFalse)(on_false_)(
388 BOOST_ASIO_MOVE_CAST(Args)(args)...);
389 }
390 }
391
392#if defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
393 template <typename... Args>
394 auto operator()(BOOST_ASIO_MOVE_ARG(Args)... args) const &
395 {
396 return deferred_conditional(*this)(
397 BOOST_ASIO_MOVE_CAST(Args)(args)...);
398 }
399#endif // defined(BOOST_ASIO_HAS_REF_QUALIFIED_FUNCTIONS)
400
401 /// Set the true branch of the conditional.
402 template <typename T>
403 deferred_conditional<T, OnFalse> then(T on_true,
404 typename constraint<
405 is_deferred<T>::value
406 >::type* = 0,
407 typename constraint<
408 is_same<
409 typename conditional<true, OnTrue, T>::type,
410 deferred_noop
411 >::value
412 >::type* = 0) BOOST_ASIO_RVALUE_REF_QUAL
413 {
414 return deferred_conditional<T, OnFalse>(
415 bool_, BOOST_ASIO_MOVE_CAST(T)(on_true),
416 BOOST_ASIO_MOVE_CAST(OnFalse)(on_false_));
417 }
418
419 /// Set the false branch of the conditional.
420 template <typename T>
421 deferred_conditional<OnTrue, T> otherwise(T on_false,
422 typename constraint<
423 is_deferred<T>::value
424 >::type* = 0,
425 typename constraint<
426 !is_same<
427 typename conditional<true, OnTrue, T>::type,
428 deferred_noop
429 >::value
430 >::type* = 0,
431 typename constraint<
432 is_same<
433 typename conditional<true, OnFalse, T>::type,
434 deferred_noop
435 >::value
436 >::type* = 0) BOOST_ASIO_RVALUE_REF_QUAL
437 {
438 return deferred_conditional<OnTrue, T>(
439 bool_, BOOST_ASIO_MOVE_CAST(OnTrue)(on_true_),
440 BOOST_ASIO_MOVE_CAST(T)(on_false));
441 }
442
443private:
444 template <typename T, typename F> friend class deferred_conditional;
445
446 // Helper constructor.
447 template <typename T, typename F>
448 explicit deferred_conditional(bool b, BOOST_ASIO_MOVE_ARG(T) on_true,
449 BOOST_ASIO_MOVE_ARG(F) on_false)
450 : on_true_(BOOST_ASIO_MOVE_CAST(T)(on_true)),
451 on_false_(BOOST_ASIO_MOVE_CAST(F)(on_false)),
452 bool_(b)
453 {
454 }
455
456 OnTrue on_true_;
457 OnFalse on_false_;
458 bool bool_;
459};
460
461#if !defined(GENERATING_DOCUMENTATION)
462template <typename OnTrue, typename OnFalse>
463struct is_deferred<deferred_conditional<OnTrue, OnFalse> > : true_type
464{
465};
466#endif // !defined(GENERATING_DOCUMENTATION)
467
468/// Class used to specify that an asynchronous operation should return a
469/// function object to lazily launch the operation.
470/**
471 * The deferred_t class is used to indicate that an asynchronous operation
472 * should return a function object which is itself an initiation function. A
473 * deferred_t object may be passed as a completion token to an asynchronous
474 * operation, typically using the special value @c boost::asio::deferred. For
475 * example:
476 *
477 * @code auto my_deferred_op
478 * = my_socket.async_read_some(my_buffer,
479 * boost::asio::experimental::deferred); @endcode
480 *
481 * The initiating function (async_read_some in the above example) returns a
482 * function object that will lazily initiate the operation.
483 */
484class deferred_t
485{
486public:
487 /// Default constructor.
488 BOOST_ASIO_CONSTEXPR deferred_t()
489 {
490 }
491
492 /// Adapts an executor to add the @c deferred_t completion token as the
493 /// default.
494 template <typename InnerExecutor>
495 struct executor_with_default : InnerExecutor
496 {
497 /// Specify @c deferred_t as the default completion token type.
498 typedef deferred_t default_completion_token_type;
499
500 /// Construct the adapted executor from the inner executor type.
501 template <typename InnerExecutor1>
502 executor_with_default(const InnerExecutor1& ex,
503 typename constraint<
504 conditional<
505 !is_same<InnerExecutor1, executor_with_default>::value,
506 is_convertible<InnerExecutor1, InnerExecutor>,
507 false_type
508 >::type::value
509 >::type = 0) BOOST_ASIO_NOEXCEPT
510 : InnerExecutor(ex)
511 {
512 }
513 };
514
515 /// Type alias to adapt an I/O object to use @c deferred_t as its
516 /// default completion token type.
517#if defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES) \
518 || defined(GENERATING_DOCUMENTATION)
519 template <typename T>
520 using as_default_on_t = typename T::template rebind_executor<
521 executor_with_default<typename T::executor_type> >::other;
522#endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
523 // || defined(GENERATING_DOCUMENTATION)
524
525 /// Function helper to adapt an I/O object to use @c deferred_t as its
526 /// default completion token type.
527 template <typename T>
528 static typename decay<T>::type::template rebind_executor<
529 executor_with_default<typename decay<T>::type::executor_type>
530 >::other
531 as_default_on(BOOST_ASIO_MOVE_ARG(T) object)
532 {
533 return typename decay<T>::type::template rebind_executor<
534 executor_with_default<typename decay<T>::type::executor_type>
535 >::other(BOOST_ASIO_MOVE_CAST(T)(object));
536 }
537
538 /// Creates a new deferred from a function.
539 template <typename Function>
540 typename constraint<
541 !is_deferred<typename decay<Function>::type>::value,
542 deferred_function<typename decay<Function>::type>
543 >::type operator()(BOOST_ASIO_MOVE_ARG(Function) function) const
544 {
545 return deferred_function<typename decay<Function>::type>(
546 deferred_init_tag{}, BOOST_ASIO_MOVE_CAST(Function)(function));
547 }
548
549 /// Passes through anything that is already deferred.
550 template <typename T>
551 typename constraint<
552 is_deferred<typename decay<T>::type>::value,
553 typename decay<T>::type
554 >::type operator()(BOOST_ASIO_MOVE_ARG(T) t) const
555 {
556 return BOOST_ASIO_MOVE_CAST(T)(t);
557 }
558
559 /// Returns a deferred operation that returns the provided values.
560 template <typename... Args>
561 static BOOST_ASIO_CONSTEXPR deferred_values<typename decay<Args>::type...>
562 values(BOOST_ASIO_MOVE_ARG(Args)... args)
563 {
564 return deferred_values<typename decay<Args>::type...>(
565 deferred_init_tag{}, BOOST_ASIO_MOVE_CAST(Args)(args)...);
566 }
567
568 /// Creates a conditional object for branching deferred operations.
569 static BOOST_ASIO_CONSTEXPR deferred_conditional<> when(bool b)
570 {
571 return deferred_conditional<>(b);
572 }
573};
574
575/// Pipe operator used to chain deferred operations.
576template <typename Head, typename Tail>
577inline auto operator|(Head head, BOOST_ASIO_MOVE_ARG(Tail) tail)
578 -> typename constraint<
579 is_deferred<Head>::value,
580 decltype(BOOST_ASIO_MOVE_OR_LVALUE(Head)(head)(
581 BOOST_ASIO_MOVE_CAST(Tail)(tail)))
582 >::type
583{
584 return BOOST_ASIO_MOVE_OR_LVALUE(Head)(head)(
585 BOOST_ASIO_MOVE_CAST(Tail)(tail));
586}
587
588/// A @ref completion_token object used to specify that an asynchronous
589/// operation should return a function object to lazily launch the operation.
590/**
591 * See the documentation for boost::asio::experimental::deferred_t for a usage
592 * example.
593 */
594#if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
595constexpr deferred_t deferred;
596#elif defined(BOOST_ASIO_MSVC)
597__declspec(selectany) deferred_t deferred;
598#endif
599
600} // namespace experimental
601} // namespace asio
602} // namespace boost
603
604#include <boost/asio/detail/pop_options.hpp>
605
606#include <boost/asio/experimental/impl/deferred.hpp>
607
608#endif // BOOST_ASIO_EXPERIMENTAL_DEFERRED_HPP