compose.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. //
  2. // impl/compose.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. #ifndef ASIO_IMPL_COMPOSE_HPP
  11. #define ASIO_IMPL_COMPOSE_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include "asio/associated_executor.hpp"
  17. #include "asio/detail/base_from_cancellation_state.hpp"
  18. #include "asio/detail/handler_alloc_helpers.hpp"
  19. #include "asio/detail/handler_cont_helpers.hpp"
  20. #include "asio/detail/handler_invoke_helpers.hpp"
  21. #include "asio/detail/type_traits.hpp"
  22. #include "asio/detail/variadic_templates.hpp"
  23. #include "asio/execution/executor.hpp"
  24. #include "asio/execution/outstanding_work.hpp"
  25. #include "asio/executor_work_guard.hpp"
  26. #include "asio/is_executor.hpp"
  27. #include "asio/system_executor.hpp"
  28. #include "asio/detail/push_options.hpp"
  29. namespace asio {
  30. namespace detail
  31. {
  32. template <typename Executor, typename = void>
  33. class composed_work_guard
  34. {
  35. public:
  36. typedef typename decay<
  37. typename prefer_result<Executor,
  38. execution::outstanding_work_t::tracked_t
  39. >::type
  40. >::type executor_type;
  41. composed_work_guard(const Executor& ex)
  42. : executor_(asio::prefer(ex, execution::outstanding_work.tracked))
  43. {
  44. }
  45. void reset()
  46. {
  47. }
  48. executor_type get_executor() const ASIO_NOEXCEPT
  49. {
  50. return executor_;
  51. }
  52. private:
  53. executor_type executor_;
  54. };
  55. template <>
  56. struct composed_work_guard<system_executor>
  57. {
  58. public:
  59. typedef system_executor executor_type;
  60. composed_work_guard(const system_executor&)
  61. {
  62. }
  63. void reset()
  64. {
  65. }
  66. executor_type get_executor() const ASIO_NOEXCEPT
  67. {
  68. return system_executor();
  69. }
  70. };
  71. #if !defined(ASIO_NO_TS_EXECUTORS)
  72. template <typename Executor>
  73. struct composed_work_guard<Executor,
  74. typename enable_if<
  75. !execution::is_executor<Executor>::value
  76. >::type> : executor_work_guard<Executor>
  77. {
  78. composed_work_guard(const Executor& ex)
  79. : executor_work_guard<Executor>(ex)
  80. {
  81. }
  82. };
  83. #endif // !defined(ASIO_NO_TS_EXECUTORS)
  84. template <typename>
  85. struct composed_io_executors;
  86. template <>
  87. struct composed_io_executors<void()>
  88. {
  89. composed_io_executors() ASIO_NOEXCEPT
  90. : head_(system_executor())
  91. {
  92. }
  93. typedef system_executor head_type;
  94. system_executor head_;
  95. };
  96. inline composed_io_executors<void()> make_composed_io_executors()
  97. {
  98. return composed_io_executors<void()>();
  99. }
  100. template <typename Head>
  101. struct composed_io_executors<void(Head)>
  102. {
  103. explicit composed_io_executors(const Head& ex) ASIO_NOEXCEPT
  104. : head_(ex)
  105. {
  106. }
  107. typedef Head head_type;
  108. Head head_;
  109. };
  110. template <typename Head>
  111. inline composed_io_executors<void(Head)>
  112. make_composed_io_executors(const Head& head)
  113. {
  114. return composed_io_executors<void(Head)>(head);
  115. }
  116. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  117. template <typename Head, typename... Tail>
  118. struct composed_io_executors<void(Head, Tail...)>
  119. {
  120. explicit composed_io_executors(const Head& head,
  121. const Tail&... tail) ASIO_NOEXCEPT
  122. : head_(head),
  123. tail_(tail...)
  124. {
  125. }
  126. void reset()
  127. {
  128. head_.reset();
  129. tail_.reset();
  130. }
  131. typedef Head head_type;
  132. Head head_;
  133. composed_io_executors<void(Tail...)> tail_;
  134. };
  135. template <typename Head, typename... Tail>
  136. inline composed_io_executors<void(Head, Tail...)>
  137. make_composed_io_executors(const Head& head, const Tail&... tail)
  138. {
  139. return composed_io_executors<void(Head, Tail...)>(head, tail...);
  140. }
  141. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  142. #define ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF(n) \
  143. template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \
  144. struct composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \
  145. { \
  146. explicit composed_io_executors(const Head& head, \
  147. ASIO_VARIADIC_CONSTREF_PARAMS(n)) ASIO_NOEXCEPT \
  148. : head_(head), \
  149. tail_(ASIO_VARIADIC_BYVAL_ARGS(n)) \
  150. { \
  151. } \
  152. \
  153. void reset() \
  154. { \
  155. head_.reset(); \
  156. tail_.reset(); \
  157. } \
  158. \
  159. typedef Head head_type; \
  160. Head head_; \
  161. composed_io_executors<void(ASIO_VARIADIC_TARGS(n))> tail_; \
  162. }; \
  163. \
  164. template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \
  165. inline composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \
  166. make_composed_io_executors(const Head& head, \
  167. ASIO_VARIADIC_CONSTREF_PARAMS(n)) \
  168. { \
  169. return composed_io_executors< \
  170. void(Head, ASIO_VARIADIC_TARGS(n))>( \
  171. head, ASIO_VARIADIC_BYVAL_ARGS(n)); \
  172. } \
  173. /**/
  174. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF)
  175. #undef ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF
  176. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  177. template <typename>
  178. struct composed_work;
  179. template <>
  180. struct composed_work<void()>
  181. {
  182. typedef composed_io_executors<void()> executors_type;
  183. composed_work(const executors_type&) ASIO_NOEXCEPT
  184. : head_(system_executor())
  185. {
  186. }
  187. void reset()
  188. {
  189. head_.reset();
  190. }
  191. typedef system_executor head_type;
  192. composed_work_guard<system_executor> head_;
  193. };
  194. template <typename Head>
  195. struct composed_work<void(Head)>
  196. {
  197. typedef composed_io_executors<void(Head)> executors_type;
  198. explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT
  199. : head_(ex.head_)
  200. {
  201. }
  202. void reset()
  203. {
  204. head_.reset();
  205. }
  206. typedef Head head_type;
  207. composed_work_guard<Head> head_;
  208. };
  209. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  210. template <typename Head, typename... Tail>
  211. struct composed_work<void(Head, Tail...)>
  212. {
  213. typedef composed_io_executors<void(Head, Tail...)> executors_type;
  214. explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT
  215. : head_(ex.head_),
  216. tail_(ex.tail_)
  217. {
  218. }
  219. void reset()
  220. {
  221. head_.reset();
  222. tail_.reset();
  223. }
  224. typedef Head head_type;
  225. composed_work_guard<Head> head_;
  226. composed_work<void(Tail...)> tail_;
  227. };
  228. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  229. #define ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \
  230. template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \
  231. struct composed_work<void(Head, ASIO_VARIADIC_TARGS(n))> \
  232. { \
  233. typedef composed_io_executors<void(Head, \
  234. ASIO_VARIADIC_TARGS(n))> executors_type; \
  235. \
  236. explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT \
  237. : head_(ex.head_), \
  238. tail_(ex.tail_) \
  239. { \
  240. } \
  241. \
  242. void reset() \
  243. { \
  244. head_.reset(); \
  245. tail_.reset(); \
  246. } \
  247. \
  248. typedef Head head_type; \
  249. composed_work_guard<Head> head_; \
  250. composed_work<void(ASIO_VARIADIC_TARGS(n))> tail_; \
  251. }; \
  252. /**/
  253. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_WORK_DEF)
  254. #undef ASIO_PRIVATE_COMPOSED_WORK_DEF
  255. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  256. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  257. template <typename Impl, typename Work, typename Handler, typename Signature>
  258. class composed_op;
  259. template <typename Impl, typename Work, typename Handler,
  260. typename R, typename... Args>
  261. class composed_op<Impl, Work, Handler, R(Args...)>
  262. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  263. template <typename Impl, typename Work, typename Handler, typename Signature>
  264. class composed_op
  265. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  266. : public base_from_cancellation_state<Handler>
  267. {
  268. public:
  269. template <typename I, typename W, typename H>
  270. composed_op(ASIO_MOVE_ARG(I) impl,
  271. ASIO_MOVE_ARG(W) work,
  272. ASIO_MOVE_ARG(H) handler)
  273. : base_from_cancellation_state<Handler>(
  274. handler, enable_terminal_cancellation()),
  275. impl_(ASIO_MOVE_CAST(I)(impl)),
  276. work_(ASIO_MOVE_CAST(W)(work)),
  277. handler_(ASIO_MOVE_CAST(H)(handler)),
  278. invocations_(0)
  279. {
  280. }
  281. #if defined(ASIO_HAS_MOVE)
  282. composed_op(composed_op&& other)
  283. : base_from_cancellation_state<Handler>(
  284. ASIO_MOVE_CAST(base_from_cancellation_state<
  285. Handler>)(other)),
  286. impl_(ASIO_MOVE_CAST(Impl)(other.impl_)),
  287. work_(ASIO_MOVE_CAST(Work)(other.work_)),
  288. handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),
  289. invocations_(other.invocations_)
  290. {
  291. }
  292. #endif // defined(ASIO_HAS_MOVE)
  293. typedef typename associated_executor<Handler,
  294. typename composed_work_guard<
  295. typename Work::head_type
  296. >::executor_type
  297. >::type executor_type;
  298. executor_type get_executor() const ASIO_NOEXCEPT
  299. {
  300. return (get_associated_executor)(handler_, work_.head_.get_executor());
  301. }
  302. typedef typename associated_allocator<Handler,
  303. std::allocator<void> >::type allocator_type;
  304. allocator_type get_allocator() const ASIO_NOEXCEPT
  305. {
  306. return (get_associated_allocator)(handler_, std::allocator<void>());
  307. }
  308. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  309. template<typename... T>
  310. void operator()(ASIO_MOVE_ARG(T)... t)
  311. {
  312. if (invocations_ < ~0u)
  313. ++invocations_;
  314. this->get_cancellation_state().slot().clear();
  315. impl_(*this, ASIO_MOVE_CAST(T)(t)...);
  316. }
  317. void complete(Args... args)
  318. {
  319. this->work_.reset();
  320. ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)(
  321. ASIO_MOVE_CAST(Args)(args)...);
  322. }
  323. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  324. void operator()()
  325. {
  326. if (invocations_ < ~0u)
  327. ++invocations_;
  328. this->get_cancellation_state().slot().clear();
  329. impl_(*this);
  330. }
  331. void complete()
  332. {
  333. this->work_.reset();
  334. ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)();
  335. }
  336. #define ASIO_PRIVATE_COMPOSED_OP_DEF(n) \
  337. template<ASIO_VARIADIC_TPARAMS(n)> \
  338. void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \
  339. { \
  340. if (invocations_ < ~0u) \
  341. ++invocations_; \
  342. this->get_cancellation_state().slot().clear(); \
  343. impl_(*this, ASIO_VARIADIC_MOVE_ARGS(n)); \
  344. } \
  345. \
  346. template<ASIO_VARIADIC_TPARAMS(n)> \
  347. void complete(ASIO_VARIADIC_MOVE_PARAMS(n)) \
  348. { \
  349. this->work_.reset(); \
  350. ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)( \
  351. ASIO_VARIADIC_MOVE_ARGS(n)); \
  352. } \
  353. /**/
  354. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_OP_DEF)
  355. #undef ASIO_PRIVATE_COMPOSED_OP_DEF
  356. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  357. void reset_cancellation_state()
  358. {
  359. base_from_cancellation_state<Handler>::reset_cancellation_state(handler_);
  360. }
  361. template <typename Filter>
  362. void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter)
  363. {
  364. base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,
  365. ASIO_MOVE_CAST(Filter)(filter));
  366. }
  367. template <typename InFilter, typename OutFilter>
  368. void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter,
  369. ASIO_MOVE_ARG(OutFilter) out_filter)
  370. {
  371. base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,
  372. ASIO_MOVE_CAST(InFilter)(in_filter),
  373. ASIO_MOVE_CAST(OutFilter)(out_filter));
  374. }
  375. //private:
  376. Impl impl_;
  377. Work work_;
  378. Handler handler_;
  379. unsigned invocations_;
  380. };
  381. template <typename Impl, typename Work, typename Handler, typename Signature>
  382. inline asio_handler_allocate_is_deprecated
  383. asio_handler_allocate(std::size_t size,
  384. composed_op<Impl, Work, Handler, Signature>* this_handler)
  385. {
  386. #if defined(ASIO_NO_DEPRECATED)
  387. asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  388. return asio_handler_allocate_is_no_longer_used();
  389. #else // defined(ASIO_NO_DEPRECATED)
  390. return asio_handler_alloc_helpers::allocate(
  391. size, this_handler->handler_);
  392. #endif // defined(ASIO_NO_DEPRECATED)
  393. }
  394. template <typename Impl, typename Work, typename Handler, typename Signature>
  395. inline asio_handler_deallocate_is_deprecated
  396. asio_handler_deallocate(void* pointer, std::size_t size,
  397. composed_op<Impl, Work, Handler, Signature>* this_handler)
  398. {
  399. asio_handler_alloc_helpers::deallocate(
  400. pointer, size, this_handler->handler_);
  401. #if defined(ASIO_NO_DEPRECATED)
  402. return asio_handler_deallocate_is_no_longer_used();
  403. #endif // defined(ASIO_NO_DEPRECATED)
  404. }
  405. template <typename Impl, typename Work, typename Handler, typename Signature>
  406. inline bool asio_handler_is_continuation(
  407. composed_op<Impl, Work, Handler, Signature>* this_handler)
  408. {
  409. return this_handler->invocations_ > 1 ? true
  410. : asio_handler_cont_helpers::is_continuation(
  411. this_handler->handler_);
  412. }
  413. template <typename Function, typename Impl,
  414. typename Work, typename Handler, typename Signature>
  415. inline asio_handler_invoke_is_deprecated
  416. asio_handler_invoke(Function& function,
  417. composed_op<Impl, Work, Handler, Signature>* this_handler)
  418. {
  419. asio_handler_invoke_helpers::invoke(
  420. function, this_handler->handler_);
  421. #if defined(ASIO_NO_DEPRECATED)
  422. return asio_handler_invoke_is_no_longer_used();
  423. #endif // defined(ASIO_NO_DEPRECATED)
  424. }
  425. template <typename Function, typename Impl,
  426. typename Work, typename Handler, typename Signature>
  427. inline asio_handler_invoke_is_deprecated
  428. asio_handler_invoke(const Function& function,
  429. composed_op<Impl, Work, Handler, Signature>* this_handler)
  430. {
  431. asio_handler_invoke_helpers::invoke(
  432. function, this_handler->handler_);
  433. #if defined(ASIO_NO_DEPRECATED)
  434. return asio_handler_invoke_is_no_longer_used();
  435. #endif // defined(ASIO_NO_DEPRECATED)
  436. }
  437. template <typename Signature, typename Executors>
  438. class initiate_composed_op
  439. {
  440. public:
  441. typedef typename composed_io_executors<Executors>::head_type executor_type;
  442. template <typename T>
  443. explicit initiate_composed_op(int, ASIO_MOVE_ARG(T) executors)
  444. : executors_(ASIO_MOVE_CAST(T)(executors))
  445. {
  446. }
  447. executor_type get_executor() const ASIO_NOEXCEPT
  448. {
  449. return executors_.head_;
  450. }
  451. template <typename Handler, typename Impl>
  452. void operator()(ASIO_MOVE_ARG(Handler) handler,
  453. ASIO_MOVE_ARG(Impl) impl) const
  454. {
  455. composed_op<typename decay<Impl>::type, composed_work<Executors>,
  456. typename decay<Handler>::type, Signature>(
  457. ASIO_MOVE_CAST(Impl)(impl),
  458. composed_work<Executors>(executors_),
  459. ASIO_MOVE_CAST(Handler)(handler))();
  460. }
  461. private:
  462. composed_io_executors<Executors> executors_;
  463. };
  464. template <typename Signature, typename Executors>
  465. inline initiate_composed_op<Signature, Executors> make_initiate_composed_op(
  466. ASIO_MOVE_ARG(composed_io_executors<Executors>) executors)
  467. {
  468. return initiate_composed_op<Signature, Executors>(0,
  469. ASIO_MOVE_CAST(composed_io_executors<Executors>)(executors));
  470. }
  471. template <typename IoObject>
  472. inline typename IoObject::executor_type
  473. get_composed_io_executor(IoObject& io_object,
  474. typename enable_if<
  475. !is_executor<IoObject>::value
  476. >::type* = 0,
  477. typename enable_if<
  478. !execution::is_executor<IoObject>::value
  479. >::type* = 0)
  480. {
  481. return io_object.get_executor();
  482. }
  483. template <typename Executor>
  484. inline const Executor& get_composed_io_executor(const Executor& ex,
  485. typename enable_if<
  486. is_executor<Executor>::value
  487. || execution::is_executor<Executor>::value
  488. >::type* = 0)
  489. {
  490. return ex;
  491. }
  492. } // namespace detail
  493. #if !defined(GENERATING_DOCUMENTATION)
  494. template <template <typename, typename> class Associator,
  495. typename Impl, typename Work, typename Handler,
  496. typename Signature, typename DefaultCandidate>
  497. struct associator<Associator,
  498. detail::composed_op<Impl, Work, Handler, Signature>,
  499. DefaultCandidate>
  500. : Associator<Handler, DefaultCandidate>
  501. {
  502. static typename Associator<Handler, DefaultCandidate>::type get(
  503. const detail::composed_op<Impl, Work, Handler, Signature>& h,
  504. const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT
  505. {
  506. return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
  507. }
  508. };
  509. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  510. template <typename CompletionToken, typename Signature,
  511. typename Implementation, typename... IoObjectsOrExecutors>
  512. ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
  513. async_compose(ASIO_MOVE_ARG(Implementation) implementation,
  514. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
  515. ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)
  516. {
  517. return async_initiate<CompletionToken, Signature>(
  518. detail::make_initiate_composed_op<Signature>(
  519. detail::make_composed_io_executors(
  520. detail::get_composed_io_executor(
  521. ASIO_MOVE_CAST(IoObjectsOrExecutors)(
  522. io_objects_or_executors))...)),
  523. token, ASIO_MOVE_CAST(Implementation)(implementation));
  524. }
  525. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  526. template <typename CompletionToken, typename Signature, typename Implementation>
  527. ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
  528. async_compose(ASIO_MOVE_ARG(Implementation) implementation,
  529. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
  530. {
  531. return async_initiate<CompletionToken, Signature>(
  532. detail::make_initiate_composed_op<Signature>(
  533. detail::make_composed_io_executors()),
  534. token, ASIO_MOVE_CAST(Implementation)(implementation));
  535. }
  536. # define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \
  537. ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n
  538. # define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \
  539. detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1))
  540. # define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \
  541. detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \
  542. detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2))
  543. # define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \
  544. detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \
  545. detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \
  546. detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3))
  547. # define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \
  548. detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \
  549. detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \
  550. detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \
  551. detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4))
  552. # define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \
  553. detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \
  554. detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \
  555. detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \
  556. detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \
  557. detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5))
  558. # define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6 \
  559. detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \
  560. detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \
  561. detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \
  562. detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \
  563. detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \
  564. detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6))
  565. # define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7 \
  566. detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \
  567. detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \
  568. detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \
  569. detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \
  570. detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \
  571. detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \
  572. detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7))
  573. # define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8 \
  574. detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \
  575. detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \
  576. detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \
  577. detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \
  578. detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \
  579. detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \
  580. detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7)), \
  581. detail::get_composed_io_executor(ASIO_MOVE_CAST(T8)(x8))
  582. #define ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
  583. template <typename CompletionToken, typename Signature, \
  584. typename Implementation, ASIO_VARIADIC_TPARAMS(n)> \
  585. ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) \
  586. async_compose(ASIO_MOVE_ARG(Implementation) implementation, \
  587. ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
  588. ASIO_VARIADIC_MOVE_PARAMS(n)) \
  589. { \
  590. return async_initiate<CompletionToken, Signature>( \
  591. detail::make_initiate_composed_op<Signature>( \
  592. detail::make_composed_io_executors( \
  593. ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \
  594. token, ASIO_MOVE_CAST(Implementation)(implementation)); \
  595. } \
  596. /**/
  597. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
  598. #undef ASIO_PRIVATE_ASYNC_COMPOSE_DEF
  599. #undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR
  600. #undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1
  601. #undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2
  602. #undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3
  603. #undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4
  604. #undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5
  605. #undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6
  606. #undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7
  607. #undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8
  608. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  609. #endif // !defined(GENERATING_DOCUMENTATION)
  610. } // namespace asio
  611. #include "asio/detail/pop_options.hpp"
  612. #endif // ASIO_IMPL_COMPOSE_HPP