compose.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. //
  2. // compose.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_COMPOSE_HPP
  11. #define BOOST_ASIO_COMPOSE_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. #include <boost/asio/associated_executor.hpp>
  17. #include <boost/asio/async_result.hpp>
  18. #include <boost/asio/detail/base_from_cancellation_state.hpp>
  19. #include <boost/asio/detail/composed_work.hpp>
  20. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  21. #include <boost/asio/detail/handler_cont_helpers.hpp>
  22. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  23. #include <boost/asio/detail/type_traits.hpp>
  24. #include <boost/asio/detail/variadic_templates.hpp>
  25. #include <boost/asio/detail/push_options.hpp>
  26. namespace boost {
  27. namespace asio {
  28. namespace detail {
  29. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  30. template <typename Impl, typename Work, typename Handler, typename Signature>
  31. class composed_op;
  32. template <typename Impl, typename Work, typename Handler,
  33. typename R, typename... Args>
  34. class composed_op<Impl, Work, Handler, R(Args...)>
  35. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  36. template <typename Impl, typename Work, typename Handler, typename Signature>
  37. class composed_op
  38. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  39. : public base_from_cancellation_state<Handler>
  40. {
  41. public:
  42. template <typename I, typename W, typename H>
  43. composed_op(BOOST_ASIO_MOVE_ARG(I) impl,
  44. BOOST_ASIO_MOVE_ARG(W) work,
  45. BOOST_ASIO_MOVE_ARG(H) handler)
  46. : base_from_cancellation_state<Handler>(
  47. handler, enable_terminal_cancellation()),
  48. impl_(BOOST_ASIO_MOVE_CAST(I)(impl)),
  49. work_(BOOST_ASIO_MOVE_CAST(W)(work)),
  50. handler_(BOOST_ASIO_MOVE_CAST(H)(handler)),
  51. invocations_(0)
  52. {
  53. }
  54. #if defined(BOOST_ASIO_HAS_MOVE)
  55. composed_op(composed_op&& other)
  56. : base_from_cancellation_state<Handler>(
  57. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  58. Handler>)(other)),
  59. impl_(BOOST_ASIO_MOVE_CAST(Impl)(other.impl_)),
  60. work_(BOOST_ASIO_MOVE_CAST(Work)(other.work_)),
  61. handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
  62. invocations_(other.invocations_)
  63. {
  64. }
  65. #endif // defined(BOOST_ASIO_HAS_MOVE)
  66. typedef typename composed_work_guard<
  67. typename Work::head_type>::executor_type io_executor_type;
  68. io_executor_type get_io_executor() const BOOST_ASIO_NOEXCEPT
  69. {
  70. return work_.head_.get_executor();
  71. }
  72. typedef typename associated_executor<Handler, io_executor_type>::type
  73. executor_type;
  74. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  75. {
  76. return (get_associated_executor)(handler_, work_.head_.get_executor());
  77. }
  78. typedef typename associated_allocator<Handler,
  79. std::allocator<void> >::type allocator_type;
  80. allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
  81. {
  82. return (get_associated_allocator)(handler_, std::allocator<void>());
  83. }
  84. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  85. template<typename... T>
  86. void operator()(BOOST_ASIO_MOVE_ARG(T)... t)
  87. {
  88. if (invocations_ < ~0u)
  89. ++invocations_;
  90. this->get_cancellation_state().slot().clear();
  91. impl_(*this, BOOST_ASIO_MOVE_CAST(T)(t)...);
  92. }
  93. void complete(Args... args)
  94. {
  95. this->work_.reset();
  96. BOOST_ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)(
  97. BOOST_ASIO_MOVE_CAST(Args)(args)...);
  98. }
  99. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  100. void operator()()
  101. {
  102. if (invocations_ < ~0u)
  103. ++invocations_;
  104. this->get_cancellation_state().slot().clear();
  105. impl_(*this);
  106. }
  107. void complete()
  108. {
  109. this->work_.reset();
  110. BOOST_ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)();
  111. }
  112. #define BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF(n) \
  113. template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  114. void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  115. { \
  116. if (invocations_ < ~0u) \
  117. ++invocations_; \
  118. this->get_cancellation_state().slot().clear(); \
  119. impl_(*this, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  120. } \
  121. \
  122. template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  123. void complete(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  124. { \
  125. this->work_.reset(); \
  126. BOOST_ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)( \
  127. BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  128. } \
  129. /**/
  130. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF)
  131. #undef BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF
  132. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  133. void reset_cancellation_state()
  134. {
  135. base_from_cancellation_state<Handler>::reset_cancellation_state(handler_);
  136. }
  137. template <typename Filter>
  138. void reset_cancellation_state(BOOST_ASIO_MOVE_ARG(Filter) filter)
  139. {
  140. base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,
  141. BOOST_ASIO_MOVE_CAST(Filter)(filter));
  142. }
  143. template <typename InFilter, typename OutFilter>
  144. void reset_cancellation_state(BOOST_ASIO_MOVE_ARG(InFilter) in_filter,
  145. BOOST_ASIO_MOVE_ARG(OutFilter) out_filter)
  146. {
  147. base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,
  148. BOOST_ASIO_MOVE_CAST(InFilter)(in_filter),
  149. BOOST_ASIO_MOVE_CAST(OutFilter)(out_filter));
  150. }
  151. cancellation_type_t cancelled() const BOOST_ASIO_NOEXCEPT
  152. {
  153. return base_from_cancellation_state<Handler>::cancelled();
  154. }
  155. //private:
  156. Impl impl_;
  157. Work work_;
  158. Handler handler_;
  159. unsigned invocations_;
  160. };
  161. template <typename Impl, typename Work, typename Handler, typename Signature>
  162. inline asio_handler_allocate_is_deprecated
  163. asio_handler_allocate(std::size_t size,
  164. composed_op<Impl, Work, Handler, Signature>* this_handler)
  165. {
  166. #if defined(BOOST_ASIO_NO_DEPRECATED)
  167. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  168. return asio_handler_allocate_is_no_longer_used();
  169. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  170. return boost_asio_handler_alloc_helpers::allocate(
  171. size, this_handler->handler_);
  172. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  173. }
  174. template <typename Impl, typename Work, typename Handler, typename Signature>
  175. inline asio_handler_deallocate_is_deprecated
  176. asio_handler_deallocate(void* pointer, std::size_t size,
  177. composed_op<Impl, Work, Handler, Signature>* this_handler)
  178. {
  179. boost_asio_handler_alloc_helpers::deallocate(
  180. pointer, size, this_handler->handler_);
  181. #if defined(BOOST_ASIO_NO_DEPRECATED)
  182. return asio_handler_deallocate_is_no_longer_used();
  183. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  184. }
  185. template <typename Impl, typename Work, typename Handler, typename Signature>
  186. inline bool asio_handler_is_continuation(
  187. composed_op<Impl, Work, Handler, Signature>* this_handler)
  188. {
  189. return this_handler->invocations_ > 1 ? true
  190. : boost_asio_handler_cont_helpers::is_continuation(
  191. this_handler->handler_);
  192. }
  193. template <typename Function, typename Impl,
  194. typename Work, typename Handler, typename Signature>
  195. inline asio_handler_invoke_is_deprecated
  196. asio_handler_invoke(Function& function,
  197. composed_op<Impl, Work, Handler, Signature>* this_handler)
  198. {
  199. boost_asio_handler_invoke_helpers::invoke(
  200. function, this_handler->handler_);
  201. #if defined(BOOST_ASIO_NO_DEPRECATED)
  202. return asio_handler_invoke_is_no_longer_used();
  203. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  204. }
  205. template <typename Function, typename Impl,
  206. typename Work, typename Handler, typename Signature>
  207. inline asio_handler_invoke_is_deprecated
  208. asio_handler_invoke(const Function& function,
  209. composed_op<Impl, Work, Handler, Signature>* this_handler)
  210. {
  211. boost_asio_handler_invoke_helpers::invoke(
  212. function, this_handler->handler_);
  213. #if defined(BOOST_ASIO_NO_DEPRECATED)
  214. return asio_handler_invoke_is_no_longer_used();
  215. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  216. }
  217. template <typename Signature, typename Executors>
  218. class initiate_composed_op
  219. {
  220. public:
  221. typedef typename composed_io_executors<Executors>::head_type executor_type;
  222. template <typename T>
  223. explicit initiate_composed_op(int, BOOST_ASIO_MOVE_ARG(T) executors)
  224. : executors_(BOOST_ASIO_MOVE_CAST(T)(executors))
  225. {
  226. }
  227. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  228. {
  229. return executors_.head_;
  230. }
  231. template <typename Handler, typename Impl>
  232. void operator()(BOOST_ASIO_MOVE_ARG(Handler) handler,
  233. BOOST_ASIO_MOVE_ARG(Impl) impl) const
  234. {
  235. composed_op<typename decay<Impl>::type, composed_work<Executors>,
  236. typename decay<Handler>::type, Signature>(
  237. BOOST_ASIO_MOVE_CAST(Impl)(impl),
  238. composed_work<Executors>(executors_),
  239. BOOST_ASIO_MOVE_CAST(Handler)(handler))();
  240. }
  241. private:
  242. composed_io_executors<Executors> executors_;
  243. };
  244. template <typename Signature, typename Executors>
  245. inline initiate_composed_op<Signature, Executors> make_initiate_composed_op(
  246. BOOST_ASIO_MOVE_ARG(composed_io_executors<Executors>) executors)
  247. {
  248. return initiate_composed_op<Signature, Executors>(0,
  249. BOOST_ASIO_MOVE_CAST(composed_io_executors<Executors>)(executors));
  250. }
  251. } // namespace detail
  252. #if !defined(GENERATING_DOCUMENTATION)
  253. template <template <typename, typename> class Associator,
  254. typename Impl, typename Work, typename Handler,
  255. typename Signature, typename DefaultCandidate>
  256. struct associator<Associator,
  257. detail::composed_op<Impl, Work, Handler, Signature>,
  258. DefaultCandidate>
  259. : Associator<Handler, DefaultCandidate>
  260. {
  261. static typename Associator<Handler, DefaultCandidate>::type
  262. get(const detail::composed_op<Impl, Work, Handler, Signature>& h)
  263. BOOST_ASIO_NOEXCEPT
  264. {
  265. return Associator<Handler, DefaultCandidate>::get(h.handler_);
  266. }
  267. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  268. typename Associator<Handler, DefaultCandidate>::type)
  269. get(const detail::composed_op<Impl, Work, Handler, Signature>& h,
  270. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  271. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  272. Associator<Handler, DefaultCandidate>::get(h.handler_, c)))
  273. {
  274. return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
  275. }
  276. };
  277. #endif // !defined(GENERATING_DOCUMENTATION)
  278. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) \
  279. || defined(GENERATING_DOCUMENTATION)
  280. /// Launch an asynchronous operation with a stateful implementation.
  281. /**
  282. * The async_compose function simplifies the implementation of composed
  283. * asynchronous operations automatically wrapping a stateful function object
  284. * with a conforming intermediate completion handler.
  285. *
  286. * @param implementation A function object that contains the implementation of
  287. * the composed asynchronous operation. The first argument to the function
  288. * object is a non-const reference to the enclosing intermediate completion
  289. * handler. The remaining arguments are any arguments that originate from the
  290. * completion handlers of any asynchronous operations performed by the
  291. * implementation.
  292. *
  293. * @param token The completion token.
  294. *
  295. * @param io_objects_or_executors Zero or more I/O objects or I/O executors for
  296. * which outstanding work must be maintained.
  297. *
  298. * @par Per-Operation Cancellation
  299. * By default, terminal per-operation cancellation is enabled for
  300. * composed operations that are implemented using @c async_compose. To
  301. * disable cancellation for the composed operation, or to alter its
  302. * supported cancellation types, call the @c self object's @c
  303. * reset_cancellation_state function.
  304. *
  305. * @par Example:
  306. *
  307. * @code struct async_echo_implementation
  308. * {
  309. * tcp::socket& socket_;
  310. * boost::asio::mutable_buffer buffer_;
  311. * enum { starting, reading, writing } state_;
  312. *
  313. * template <typename Self>
  314. * void operator()(Self& self,
  315. * boost::system::error_code error = {},
  316. * std::size_t n = 0)
  317. * {
  318. * switch (state_)
  319. * {
  320. * case starting:
  321. * state_ = reading;
  322. * socket_.async_read_some(
  323. * buffer_, std::move(self));
  324. * break;
  325. * case reading:
  326. * if (error)
  327. * {
  328. * self.complete(error, 0);
  329. * }
  330. * else
  331. * {
  332. * state_ = writing;
  333. * boost::asio::async_write(socket_, buffer_,
  334. * boost::asio::transfer_exactly(n),
  335. * std::move(self));
  336. * }
  337. * break;
  338. * case writing:
  339. * self.complete(error, n);
  340. * break;
  341. * }
  342. * }
  343. * };
  344. *
  345. * template <typename CompletionToken>
  346. * auto async_echo(tcp::socket& socket,
  347. * boost::asio::mutable_buffer buffer,
  348. * CompletionToken&& token) ->
  349. * decltype(
  350. * boost::asio::async_compose<CompletionToken,
  351. * void(boost::system::error_code, std::size_t)>(
  352. * std::declval<async_echo_implementation>(),
  353. * token, socket))
  354. * {
  355. * return boost::asio::async_compose<CompletionToken,
  356. * void(boost::system::error_code, std::size_t)>(
  357. * async_echo_implementation{socket, buffer,
  358. * async_echo_implementation::starting},
  359. * token, socket);
  360. * } @endcode
  361. */
  362. template <typename CompletionToken, typename Signature,
  363. typename Implementation, typename... IoObjectsOrExecutors>
  364. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, Signature)
  365. async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
  366. BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
  367. BOOST_ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)
  368. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  369. async_initiate<CompletionToken, Signature>(
  370. detail::make_initiate_composed_op<Signature>(
  371. detail::make_composed_io_executors(
  372. detail::get_composed_io_executor(
  373. BOOST_ASIO_MOVE_CAST(IoObjectsOrExecutors)(
  374. io_objects_or_executors))...)),
  375. token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation))))
  376. {
  377. return async_initiate<CompletionToken, Signature>(
  378. detail::make_initiate_composed_op<Signature>(
  379. detail::make_composed_io_executors(
  380. detail::get_composed_io_executor(
  381. BOOST_ASIO_MOVE_CAST(IoObjectsOrExecutors)(
  382. io_objects_or_executors))...)),
  383. token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation));
  384. }
  385. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  386. // || defined(GENERATING_DOCUMENTATION)
  387. template <typename CompletionToken, typename Signature, typename Implementation>
  388. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, Signature)
  389. async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
  390. BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
  391. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  392. async_initiate<CompletionToken, Signature>(
  393. detail::make_initiate_composed_op<Signature>(
  394. detail::make_composed_io_executors()),
  395. token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation))))
  396. {
  397. return async_initiate<CompletionToken, Signature>(
  398. detail::make_initiate_composed_op<Signature>(
  399. detail::make_composed_io_executors()),
  400. token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation));
  401. }
  402. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \
  403. BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n
  404. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \
  405. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1))
  406. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \
  407. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  408. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2))
  409. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \
  410. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  411. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  412. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3))
  413. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \
  414. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  415. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  416. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
  417. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4))
  418. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \
  419. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  420. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  421. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
  422. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
  423. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5))
  424. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6 \
  425. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  426. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  427. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
  428. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
  429. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5)), \
  430. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T6)(x6))
  431. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7 \
  432. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  433. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  434. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
  435. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
  436. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5)), \
  437. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T6)(x6)), \
  438. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T7)(x7))
  439. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8 \
  440. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  441. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  442. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
  443. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
  444. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5)), \
  445. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T6)(x6)), \
  446. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T7)(x7)), \
  447. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T8)(x8))
  448. #define BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
  449. template <typename CompletionToken, typename Signature, \
  450. typename Implementation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  451. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, Signature) \
  452. async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, \
  453. BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
  454. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  455. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(( \
  456. async_initiate<CompletionToken, Signature>( \
  457. detail::make_initiate_composed_op<Signature>( \
  458. detail::make_composed_io_executors( \
  459. BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \
  460. token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation)))) \
  461. { \
  462. return async_initiate<CompletionToken, Signature>( \
  463. detail::make_initiate_composed_op<Signature>( \
  464. detail::make_composed_io_executors( \
  465. BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \
  466. token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation)); \
  467. } \
  468. /**/
  469. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
  470. #undef BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF
  471. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR
  472. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1
  473. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2
  474. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3
  475. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4
  476. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5
  477. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6
  478. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7
  479. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8
  480. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  481. // || defined(GENERATING_DOCUMENTATION)
  482. } // namespace asio
  483. } // namespace boost
  484. #include <boost/asio/detail/pop_options.hpp>
  485. #endif // BOOST_ASIO_COMPOSE_HPP