File indexing completed on 2025-01-30 09:33:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DEFERRED_HPP
0012 #define BOOST_ASIO_DEFERRED_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019 #include <tuple>
0020 #include <boost/asio/associator.hpp>
0021 #include <boost/asio/async_result.hpp>
0022 #include <boost/asio/detail/type_traits.hpp>
0023 #include <boost/asio/detail/utility.hpp>
0024
0025 #include <boost/asio/detail/push_options.hpp>
0026
0027 namespace boost {
0028 namespace asio {
0029
0030
0031 template <typename T>
0032 struct is_deferred : false_type
0033 {
0034 };
0035
0036
0037 template <typename... Signatures>
0038 struct deferred_signatures
0039 {
0040 };
0041
0042 namespace detail {
0043
0044
0045
0046
0047 template <typename Tail, typename... Signatures>
0048 struct deferred_sequence_signatures;
0049
0050 template <typename Tail, typename R, typename... Args, typename... Signatures>
0051 struct deferred_sequence_signatures<Tail, R(Args...), Signatures...>
0052 : completion_signature_of<decltype(declval<Tail>()(declval<Args>()...))>
0053 {
0054 static_assert(
0055 !is_same<decltype(declval<Tail>()(declval<Args>()...)), void>::value,
0056 "deferred functions must produce a deferred return type");
0057 };
0058
0059
0060 template <typename Handler, typename Tail>
0061 class deferred_sequence_handler
0062 {
0063 public:
0064 template <typename H, typename T>
0065 explicit deferred_sequence_handler(H&& handler, T&& tail)
0066 : handler_(static_cast<H&&>(handler)),
0067 tail_(static_cast<T&&>(tail))
0068 {
0069 }
0070
0071 template <typename... Args>
0072 void operator()(Args&&... args)
0073 {
0074 static_cast<Tail&&>(tail_)(
0075 static_cast<Args&&>(args)...)(
0076 static_cast<Handler&&>(handler_));
0077 }
0078
0079
0080 Handler handler_;
0081 Tail tail_;
0082 };
0083
0084 template <typename Head, typename Tail, typename... Signatures>
0085 class deferred_sequence_base
0086 {
0087 private:
0088 struct initiate
0089 {
0090 template <typename Handler>
0091 void operator()(Handler&& handler, Head head, Tail&& tail)
0092 {
0093 static_cast<Head&&>(head)(
0094 deferred_sequence_handler<decay_t<Handler>, decay_t<Tail>>(
0095 static_cast<Handler&&>(handler), static_cast<Tail&&>(tail)));
0096 }
0097 };
0098
0099 Head head_;
0100 Tail tail_;
0101
0102 public:
0103 template <typename H, typename T>
0104 constexpr explicit deferred_sequence_base(H&& head, T&& tail)
0105 : head_(static_cast<H&&>(head)),
0106 tail_(static_cast<T&&>(tail))
0107 {
0108 }
0109
0110 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
0111 auto operator()(CompletionToken&& token) &&
0112 -> decltype(
0113 async_initiate<CompletionToken, Signatures...>(
0114 initiate(), token, static_cast<Head&&>(this->head_),
0115 static_cast<Tail&&>(this->tail_)))
0116 {
0117 return async_initiate<CompletionToken, Signatures...>(initiate(),
0118 token, static_cast<Head&&>(head_), static_cast<Tail&&>(tail_));
0119 }
0120
0121 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
0122 auto operator()(CompletionToken&& token) const &
0123 -> decltype(
0124 async_initiate<CompletionToken, Signatures...>(
0125 initiate(), token, this->head_, this->tail_))
0126 {
0127 return async_initiate<CompletionToken, Signatures...>(
0128 initiate(), token, head_, tail_);
0129 }
0130 };
0131
0132
0133
0134 template <typename Head, typename Tail>
0135 struct deferred_sequence_types
0136 {
0137 template <typename... Signatures>
0138 struct op1
0139 {
0140 typedef deferred_sequence_base<Head, Tail, Signatures...> type;
0141 };
0142
0143 template <typename... Signatures>
0144 struct op2
0145 {
0146 typedef typename deferred_sequence_signatures<Tail, Signatures...>::template
0147 apply<op1>::type::type type;
0148 };
0149
0150 typedef typename completion_signature_of<Head>::template
0151 apply<op2>::type::type base;
0152 };
0153
0154 }
0155
0156
0157 struct deferred_noop
0158 {
0159
0160 template <typename... Args>
0161 void operator()(Args&&...) &&
0162 {
0163 }
0164
0165
0166 template <typename... Args>
0167 void operator()(Args&&...) const &
0168 {
0169 }
0170 };
0171
0172 #if !defined(GENERATING_DOCUMENTATION)
0173 template <>
0174 struct is_deferred<deferred_noop> : true_type
0175 {
0176 };
0177 #endif
0178
0179
0180 struct deferred_init_tag {};
0181
0182
0183
0184 template <typename Function>
0185 class deferred_function
0186 {
0187 public:
0188
0189 template <typename F>
0190 constexpr explicit deferred_function(deferred_init_tag, F&& function)
0191 : function_(static_cast<F&&>(function))
0192 {
0193 }
0194
0195
0196 Function function_;
0197
0198 public:
0199 template <typename... Args>
0200 auto operator()(Args&&... args) &&
0201 -> decltype(
0202 static_cast<Function&&>(this->function_)(static_cast<Args&&>(args)...))
0203 {
0204 return static_cast<Function&&>(function_)(static_cast<Args&&>(args)...);
0205 }
0206
0207 template <typename... Args>
0208 auto operator()(Args&&... args) const &
0209 -> decltype(Function(function_)(static_cast<Args&&>(args)...))
0210 {
0211 return Function(function_)(static_cast<Args&&>(args)...);
0212 }
0213 };
0214
0215 #if !defined(GENERATING_DOCUMENTATION)
0216 template <typename Function>
0217 struct is_deferred<deferred_function<Function>> : true_type
0218 {
0219 };
0220 #endif
0221
0222
0223 template <typename... Values>
0224 class BOOST_ASIO_NODISCARD deferred_values
0225 {
0226 private:
0227 std::tuple<Values...> values_;
0228
0229 struct initiate
0230 {
0231 template <typename Handler, typename... V>
0232 void operator()(Handler handler, V&&... values)
0233 {
0234 static_cast<Handler&&>(handler)(static_cast<V&&>(values)...);
0235 }
0236 };
0237
0238 template <typename CompletionToken, std::size_t... I>
0239 auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
0240 -> decltype(
0241 async_initiate<CompletionToken, void(Values...)>(initiate(), token,
0242 std::get<I>(static_cast<std::tuple<Values...>&&>(this->values_))...))
0243 {
0244 return async_initiate<CompletionToken, void(Values...)>(initiate(), token,
0245 std::get<I>(static_cast<std::tuple<Values...>&&>(values_))...);
0246 }
0247
0248 template <typename CompletionToken, std::size_t... I>
0249 auto const_invoke_helper(CompletionToken&& token,
0250 detail::index_sequence<I...>)
0251 -> decltype(
0252 async_initiate<CompletionToken, void(Values...)>(
0253 initiate(), token, std::get<I>(values_)...))
0254 {
0255 return async_initiate<CompletionToken, void(Values...)>(
0256 initiate(), token, std::get<I>(values_)...);
0257 }
0258
0259 public:
0260
0261
0262 template <typename... V>
0263 constexpr explicit deferred_values(
0264 deferred_init_tag, V&&... values)
0265 : values_(static_cast<V&&>(values)...)
0266 {
0267 }
0268
0269
0270 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>
0271 auto operator()(CompletionToken&& token) &&
0272 -> decltype(
0273 this->invoke_helper(
0274 static_cast<CompletionToken&&>(token),
0275 detail::index_sequence_for<Values...>()))
0276 {
0277 return this->invoke_helper(
0278 static_cast<CompletionToken&&>(token),
0279 detail::index_sequence_for<Values...>());
0280 }
0281
0282 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>
0283 auto operator()(CompletionToken&& token) const &
0284 -> decltype(
0285 this->const_invoke_helper(
0286 static_cast<CompletionToken&&>(token),
0287 detail::index_sequence_for<Values...>()))
0288 {
0289 return this->const_invoke_helper(
0290 static_cast<CompletionToken&&>(token),
0291 detail::index_sequence_for<Values...>());
0292 }
0293 };
0294
0295 #if !defined(GENERATING_DOCUMENTATION)
0296 template <typename... Values>
0297 struct is_deferred<deferred_values<Values...>> : true_type
0298 {
0299 };
0300 #endif
0301
0302
0303 template <typename Signature, typename Initiation, typename... InitArgs>
0304 class BOOST_ASIO_NODISCARD deferred_async_operation
0305 {
0306 private:
0307 typedef decay_t<Initiation> initiation_t;
0308 initiation_t initiation_;
0309 typedef std::tuple<decay_t<InitArgs>...> init_args_t;
0310 init_args_t init_args_;
0311
0312 template <typename CompletionToken, std::size_t... I>
0313 auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
0314 -> decltype(
0315 async_initiate<CompletionToken, Signature>(
0316 static_cast<initiation_t&&>(initiation_), token,
0317 std::get<I>(static_cast<init_args_t&&>(init_args_))...))
0318 {
0319 return async_initiate<CompletionToken, Signature>(
0320 static_cast<initiation_t&&>(initiation_), token,
0321 std::get<I>(static_cast<init_args_t&&>(init_args_))...);
0322 }
0323
0324 template <typename CompletionToken, std::size_t... I>
0325 auto const_invoke_helper(CompletionToken&& token,
0326 detail::index_sequence<I...>) const &
0327 -> decltype(
0328 async_initiate<CompletionToken, Signature>(
0329 initiation_t(initiation_), token, std::get<I>(init_args_)...))
0330 {
0331 return async_initiate<CompletionToken, Signature>(
0332 initiation_t(initiation_), token, std::get<I>(init_args_)...);
0333 }
0334
0335 public:
0336
0337
0338 template <typename I, typename... A>
0339 constexpr explicit deferred_async_operation(
0340 deferred_init_tag, I&& initiation, A&&... init_args)
0341 : initiation_(static_cast<I&&>(initiation)),
0342 init_args_(static_cast<A&&>(init_args)...)
0343 {
0344 }
0345
0346
0347 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
0348 auto operator()(CompletionToken&& token) &&
0349 -> decltype(
0350 this->invoke_helper(
0351 static_cast<CompletionToken&&>(token),
0352 detail::index_sequence_for<InitArgs...>()))
0353 {
0354 return this->invoke_helper(
0355 static_cast<CompletionToken&&>(token),
0356 detail::index_sequence_for<InitArgs...>());
0357 }
0358
0359 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
0360 auto operator()(CompletionToken&& token) const &
0361 -> decltype(
0362 this->const_invoke_helper(
0363 static_cast<CompletionToken&&>(token),
0364 detail::index_sequence_for<InitArgs...>()))
0365 {
0366 return this->const_invoke_helper(
0367 static_cast<CompletionToken&&>(token),
0368 detail::index_sequence_for<InitArgs...>());
0369 }
0370 };
0371
0372
0373
0374 template <typename... Signatures, typename Initiation, typename... InitArgs>
0375 class BOOST_ASIO_NODISCARD deferred_async_operation<
0376 deferred_signatures<Signatures...>, Initiation, InitArgs...>
0377 {
0378 private:
0379 typedef decay_t<Initiation> initiation_t;
0380 initiation_t initiation_;
0381 typedef std::tuple<decay_t<InitArgs>...> init_args_t;
0382 init_args_t init_args_;
0383
0384 template <typename CompletionToken, std::size_t... I>
0385 auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
0386 -> decltype(
0387 async_initiate<CompletionToken, Signatures...>(
0388 static_cast<initiation_t&&>(initiation_), token,
0389 std::get<I>(static_cast<init_args_t&&>(init_args_))...))
0390 {
0391 return async_initiate<CompletionToken, Signatures...>(
0392 static_cast<initiation_t&&>(initiation_), token,
0393 std::get<I>(static_cast<init_args_t&&>(init_args_))...);
0394 }
0395
0396 template <typename CompletionToken, std::size_t... I>
0397 auto const_invoke_helper(CompletionToken&& token,
0398 detail::index_sequence<I...>) const &
0399 -> decltype(
0400 async_initiate<CompletionToken, Signatures...>(
0401 initiation_t(initiation_), token, std::get<I>(init_args_)...))
0402 {
0403 return async_initiate<CompletionToken, Signatures...>(
0404 initiation_t(initiation_), token, std::get<I>(init_args_)...);
0405 }
0406
0407 public:
0408
0409
0410 template <typename I, typename... A>
0411 constexpr explicit deferred_async_operation(
0412 deferred_init_tag, I&& initiation, A&&... init_args)
0413 : initiation_(static_cast<I&&>(initiation)),
0414 init_args_(static_cast<A&&>(init_args)...)
0415 {
0416 }
0417
0418
0419 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
0420 auto operator()(CompletionToken&& token) &&
0421 -> decltype(
0422 this->invoke_helper(
0423 static_cast<CompletionToken&&>(token),
0424 detail::index_sequence_for<InitArgs...>()))
0425 {
0426 return this->invoke_helper(
0427 static_cast<CompletionToken&&>(token),
0428 detail::index_sequence_for<InitArgs...>());
0429 }
0430
0431 template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
0432 auto operator()(CompletionToken&& token) const &
0433 -> decltype(
0434 this->const_invoke_helper(
0435 static_cast<CompletionToken&&>(token),
0436 detail::index_sequence_for<InitArgs...>()))
0437 {
0438 return this->const_invoke_helper(
0439 static_cast<CompletionToken&&>(token),
0440 detail::index_sequence_for<InitArgs...>());
0441 }
0442 };
0443
0444 #if !defined(GENERATING_DOCUMENTATION)
0445 template <typename Signature, typename Initiation, typename... InitArgs>
0446 struct is_deferred<
0447 deferred_async_operation<Signature, Initiation, InitArgs...>> : true_type
0448 {
0449 };
0450 #endif
0451
0452
0453 template <typename Head, typename Tail>
0454 class BOOST_ASIO_NODISCARD deferred_sequence :
0455 public detail::deferred_sequence_types<Head, Tail>::base
0456 {
0457 public:
0458 template <typename H, typename T>
0459 constexpr explicit deferred_sequence(deferred_init_tag, H&& head, T&& tail)
0460 : detail::deferred_sequence_types<Head, Tail>::base(
0461 static_cast<H&&>(head), static_cast<T&&>(tail))
0462 {
0463 }
0464
0465 #if defined(GENERATING_DOCUMENTATION)
0466 template <typename CompletionToken>
0467 auto operator()(CompletionToken&& token) &&;
0468
0469 template <typename CompletionToken>
0470 auto operator()(CompletionToken&& token) const &;
0471 #endif
0472 };
0473
0474 #if !defined(GENERATING_DOCUMENTATION)
0475 template <typename Head, typename Tail>
0476 struct is_deferred<deferred_sequence<Head, Tail>> : true_type
0477 {
0478 };
0479 #endif
0480
0481
0482 template <typename OnTrue = deferred_noop, typename OnFalse = deferred_noop>
0483 class BOOST_ASIO_NODISCARD deferred_conditional
0484 {
0485 private:
0486 template <typename T, typename F> friend class deferred_conditional;
0487
0488
0489 template <typename T, typename F>
0490 explicit deferred_conditional(bool b, T&& on_true, F&& on_false)
0491 : on_true_(static_cast<T&&>(on_true)),
0492 on_false_(static_cast<F&&>(on_false)),
0493 bool_(b)
0494 {
0495 }
0496
0497 OnTrue on_true_;
0498 OnFalse on_false_;
0499 bool bool_;
0500
0501 public:
0502
0503
0504 constexpr explicit deferred_conditional(bool b)
0505 : on_true_(),
0506 on_false_(),
0507 bool_(b)
0508 {
0509 }
0510
0511
0512 template <typename... Args>
0513 auto operator()(Args&&... args) &&
0514 -> decltype(static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...))
0515 {
0516 if (bool_)
0517 {
0518 return static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...);
0519 }
0520 else
0521 {
0522 return static_cast<OnFalse&&>(on_false_)(static_cast<Args&&>(args)...);
0523 }
0524 }
0525
0526 template <typename... Args>
0527 auto operator()(Args&&... args) const &
0528 -> decltype(on_true_(static_cast<Args&&>(args)...))
0529 {
0530 if (bool_)
0531 {
0532 return on_true_(static_cast<Args&&>(args)...);
0533 }
0534 else
0535 {
0536 return on_false_(static_cast<Args&&>(args)...);
0537 }
0538 }
0539
0540
0541 template <typename T>
0542 deferred_conditional<T, OnFalse> then(T on_true,
0543 constraint_t<
0544 is_deferred<T>::value
0545 >* = 0,
0546 constraint_t<
0547 is_same<
0548 conditional_t<true, OnTrue, T>,
0549 deferred_noop
0550 >::value
0551 >* = 0) &&
0552 {
0553 return deferred_conditional<T, OnFalse>(
0554 bool_, static_cast<T&&>(on_true),
0555 static_cast<OnFalse&&>(on_false_));
0556 }
0557
0558
0559 template <typename T>
0560 deferred_conditional<OnTrue, T> otherwise(T on_false,
0561 constraint_t<
0562 is_deferred<T>::value
0563 >* = 0,
0564 constraint_t<
0565 !is_same<
0566 conditional_t<true, OnTrue, T>,
0567 deferred_noop
0568 >::value
0569 >* = 0,
0570 constraint_t<
0571 is_same<
0572 conditional_t<true, OnFalse, T>,
0573 deferred_noop
0574 >::value
0575 >* = 0) &&
0576 {
0577 return deferred_conditional<OnTrue, T>(
0578 bool_, static_cast<OnTrue&&>(on_true_),
0579 static_cast<T&&>(on_false));
0580 }
0581 };
0582
0583 #if !defined(GENERATING_DOCUMENTATION)
0584 template <typename OnTrue, typename OnFalse>
0585 struct is_deferred<deferred_conditional<OnTrue, OnFalse>> : true_type
0586 {
0587 };
0588 #endif
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606 class deferred_t
0607 {
0608 public:
0609
0610 constexpr deferred_t()
0611 {
0612 }
0613
0614
0615
0616 template <typename InnerExecutor>
0617 struct executor_with_default : InnerExecutor
0618 {
0619
0620 typedef deferred_t default_completion_token_type;
0621
0622
0623 template <typename InnerExecutor1>
0624 executor_with_default(const InnerExecutor1& ex,
0625 constraint_t<
0626 conditional_t<
0627 !is_same<InnerExecutor1, executor_with_default>::value,
0628 is_convertible<InnerExecutor1, InnerExecutor>,
0629 false_type
0630 >::value
0631 > = 0) noexcept
0632 : InnerExecutor(ex)
0633 {
0634 }
0635 };
0636
0637
0638
0639 template <typename T>
0640 using as_default_on_t = typename T::template rebind_executor<
0641 executor_with_default<typename T::executor_type>>::other;
0642
0643
0644
0645 template <typename T>
0646 static typename decay_t<T>::template rebind_executor<
0647 executor_with_default<typename decay_t<T>::executor_type>
0648 >::other
0649 as_default_on(T&& object)
0650 {
0651 return typename decay_t<T>::template rebind_executor<
0652 executor_with_default<typename decay_t<T>::executor_type>
0653 >::other(static_cast<T&&>(object));
0654 }
0655
0656
0657 template <typename Function>
0658 constraint_t<
0659 !is_deferred<decay_t<Function>>::value,
0660 deferred_function<decay_t<Function>>
0661 > operator()(Function&& function) const
0662 {
0663 return deferred_function<decay_t<Function>>(
0664 deferred_init_tag{}, static_cast<Function&&>(function));
0665 }
0666
0667
0668 template <typename T>
0669 constraint_t<
0670 is_deferred<decay_t<T>>::value,
0671 decay_t<T>
0672 > operator()(T&& t) const
0673 {
0674 return static_cast<T&&>(t);
0675 }
0676
0677
0678 template <typename... Args>
0679 static constexpr deferred_values<decay_t<Args>...> values(Args&&... args)
0680 {
0681 return deferred_values<decay_t<Args>...>(
0682 deferred_init_tag{}, static_cast<Args&&>(args)...);
0683 }
0684
0685
0686 static constexpr deferred_conditional<> when(bool b)
0687 {
0688 return deferred_conditional<>(b);
0689 }
0690 };
0691
0692
0693 template <typename Head, typename Tail>
0694 inline auto operator|(Head head, Tail&& tail)
0695 -> constraint_t<
0696 is_deferred<Head>::value,
0697 decltype(static_cast<Head&&>(head)(static_cast<Tail&&>(tail)))
0698 >
0699 {
0700 return static_cast<Head&&>(head)(static_cast<Tail&&>(tail));
0701 }
0702
0703
0704
0705
0706
0707
0708 constexpr deferred_t deferred;
0709
0710 }
0711 }
0712
0713 #include <boost/asio/detail/pop_options.hpp>
0714
0715 #include <boost/asio/impl/deferred.hpp>
0716
0717 #endif