deferred.hpp 26 KB

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