compose.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. //
  2. // impl/compose.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 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_IMPL_COMPOSE_HPP
  11. #define BOOST_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 <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  17. #include <boost/asio/detail/handler_cont_helpers.hpp>
  18. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  19. #include <boost/asio/detail/type_traits.hpp>
  20. #include <boost/asio/detail/variadic_templates.hpp>
  21. #include <boost/asio/executor_work_guard.hpp>
  22. #include <boost/asio/is_executor.hpp>
  23. #include <boost/asio/system_executor.hpp>
  24. #include <boost/asio/detail/push_options.hpp>
  25. namespace boost {
  26. namespace asio {
  27. namespace detail
  28. {
  29. template <typename>
  30. struct composed_io_executors;
  31. template <>
  32. struct composed_io_executors<void()>
  33. {
  34. composed_io_executors() BOOST_ASIO_NOEXCEPT
  35. : head_(system_executor())
  36. {
  37. }
  38. typedef system_executor head_type;
  39. system_executor head_;
  40. };
  41. inline composed_io_executors<void()> make_composed_io_executors()
  42. {
  43. return composed_io_executors<void()>();
  44. }
  45. template <typename Head>
  46. struct composed_io_executors<void(Head)>
  47. {
  48. explicit composed_io_executors(const Head& ex) BOOST_ASIO_NOEXCEPT
  49. : head_(ex)
  50. {
  51. }
  52. typedef Head head_type;
  53. Head head_;
  54. };
  55. template <typename Head>
  56. inline composed_io_executors<void(Head)>
  57. make_composed_io_executors(const Head& head)
  58. {
  59. return composed_io_executors<void(Head)>(head);
  60. }
  61. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  62. template <typename Head, typename... Tail>
  63. struct composed_io_executors<void(Head, Tail...)>
  64. {
  65. explicit composed_io_executors(const Head& head,
  66. const Tail&... tail) BOOST_ASIO_NOEXCEPT
  67. : head_(head),
  68. tail_(tail...)
  69. {
  70. }
  71. void reset()
  72. {
  73. head_.reset();
  74. tail_.reset();
  75. }
  76. typedef Head head_type;
  77. Head head_;
  78. composed_io_executors<void(Tail...)> tail_;
  79. };
  80. template <typename Head, typename... Tail>
  81. inline composed_io_executors<void(Head, Tail...)>
  82. make_composed_io_executors(const Head& head, const Tail&... tail)
  83. {
  84. return composed_io_executors<void(Head, Tail...)>(head, tail...);
  85. }
  86. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  87. #define BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF(n) \
  88. template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  89. struct composed_io_executors<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
  90. { \
  91. explicit composed_io_executors(const Head& head, \
  92. BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) BOOST_ASIO_NOEXCEPT \
  93. : head_(head), \
  94. tail_(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) \
  95. { \
  96. } \
  97. \
  98. void reset() \
  99. { \
  100. head_.reset(); \
  101. tail_.reset(); \
  102. } \
  103. \
  104. typedef Head head_type; \
  105. Head head_; \
  106. composed_io_executors<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
  107. }; \
  108. \
  109. template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  110. inline composed_io_executors<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
  111. make_composed_io_executors(const Head& head, \
  112. BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) \
  113. { \
  114. return composed_io_executors< \
  115. void(Head, BOOST_ASIO_VARIADIC_TARGS(n))>( \
  116. head, BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)); \
  117. } \
  118. /**/
  119. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF)
  120. #undef BOOST_ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF
  121. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  122. template <typename>
  123. struct composed_work;
  124. template <>
  125. struct composed_work<void()>
  126. {
  127. typedef composed_io_executors<void()> executors_type;
  128. composed_work(const executors_type&) BOOST_ASIO_NOEXCEPT
  129. : head_(system_executor())
  130. {
  131. }
  132. void reset()
  133. {
  134. head_.reset();
  135. }
  136. typedef system_executor head_type;
  137. executor_work_guard<system_executor> head_;
  138. };
  139. template <typename Head>
  140. struct composed_work<void(Head)>
  141. {
  142. typedef composed_io_executors<void(Head)> executors_type;
  143. explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT
  144. : head_(ex.head_)
  145. {
  146. }
  147. void reset()
  148. {
  149. head_.reset();
  150. }
  151. typedef Head head_type;
  152. executor_work_guard<Head> head_;
  153. };
  154. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  155. template <typename Head, typename... Tail>
  156. struct composed_work<void(Head, Tail...)>
  157. {
  158. typedef composed_io_executors<void(Head, Tail...)> executors_type;
  159. explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT
  160. : head_(ex.head_),
  161. tail_(ex.tail_)
  162. {
  163. }
  164. void reset()
  165. {
  166. head_.reset();
  167. tail_.reset();
  168. }
  169. typedef Head head_type;
  170. executor_work_guard<Head> head_;
  171. composed_work<void(Tail...)> tail_;
  172. };
  173. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  174. #define BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \
  175. template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  176. struct composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
  177. { \
  178. typedef composed_io_executors<void(Head, \
  179. BOOST_ASIO_VARIADIC_TARGS(n))> executors_type; \
  180. \
  181. explicit composed_work(const executors_type& ex) BOOST_ASIO_NOEXCEPT \
  182. : head_(ex.head_), \
  183. tail_(ex.tail_) \
  184. { \
  185. } \
  186. \
  187. void reset() \
  188. { \
  189. head_.reset(); \
  190. tail_.reset(); \
  191. } \
  192. \
  193. typedef Head head_type; \
  194. executor_work_guard<Head> head_; \
  195. composed_work<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
  196. }; \
  197. /**/
  198. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF)
  199. #undef BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF
  200. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  201. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  202. template <typename Impl, typename Work, typename Handler, typename Signature>
  203. class composed_op;
  204. template <typename Impl, typename Work, typename Handler,
  205. typename R, typename... Args>
  206. class composed_op<Impl, Work, Handler, R(Args...)>
  207. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  208. template <typename Impl, typename Work, typename Handler, typename Signature>
  209. class composed_op
  210. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  211. {
  212. public:
  213. composed_op(BOOST_ASIO_MOVE_ARG(Impl) impl,
  214. BOOST_ASIO_MOVE_ARG(Work) work,
  215. BOOST_ASIO_MOVE_ARG(Handler) handler)
  216. : impl_(BOOST_ASIO_MOVE_CAST(Impl)(impl)),
  217. work_(BOOST_ASIO_MOVE_CAST(Work)(work)),
  218. handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
  219. invocations_(0)
  220. {
  221. }
  222. #if defined(BOOST_ASIO_HAS_MOVE)
  223. composed_op(composed_op&& other)
  224. : impl_(BOOST_ASIO_MOVE_CAST(Impl)(other.impl_)),
  225. work_(BOOST_ASIO_MOVE_CAST(Work)(other.work_)),
  226. handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
  227. invocations_(other.invocations_)
  228. {
  229. }
  230. #endif // defined(BOOST_ASIO_HAS_MOVE)
  231. typedef typename associated_executor<Handler,
  232. typename Work::head_type>::type executor_type;
  233. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  234. {
  235. return (get_associated_executor)(handler_, work_.head_.get_executor());
  236. }
  237. typedef typename associated_allocator<Handler,
  238. std::allocator<void> >::type allocator_type;
  239. allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
  240. {
  241. return (get_associated_allocator)(handler_, std::allocator<void>());
  242. }
  243. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  244. template<typename... T>
  245. void operator()(BOOST_ASIO_MOVE_ARG(T)... t)
  246. {
  247. if (invocations_ < ~unsigned(0))
  248. ++invocations_;
  249. impl_(*this, BOOST_ASIO_MOVE_CAST(T)(t)...);
  250. }
  251. void complete(Args... args)
  252. {
  253. this->work_.reset();
  254. this->handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
  255. }
  256. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  257. void operator()()
  258. {
  259. if (invocations_ < ~unsigned(0))
  260. ++invocations_;
  261. impl_(*this);
  262. }
  263. void complete()
  264. {
  265. this->work_.reset();
  266. this->handler_();
  267. }
  268. #define BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF(n) \
  269. template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  270. void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  271. { \
  272. if (invocations_ < ~unsigned(0)) \
  273. ++invocations_; \
  274. impl_(*this, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  275. } \
  276. \
  277. template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  278. void complete(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  279. { \
  280. this->work_.reset(); \
  281. this->handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  282. } \
  283. /**/
  284. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF)
  285. #undef BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF
  286. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  287. //private:
  288. Impl impl_;
  289. Work work_;
  290. Handler handler_;
  291. unsigned invocations_;
  292. };
  293. template <typename Impl, typename Work, typename Handler, typename Signature>
  294. inline void* asio_handler_allocate(std::size_t size,
  295. composed_op<Impl, Work, Handler, Signature>* this_handler)
  296. {
  297. return boost_asio_handler_alloc_helpers::allocate(
  298. size, this_handler->handler_);
  299. }
  300. template <typename Impl, typename Work, typename Handler, typename Signature>
  301. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  302. composed_op<Impl, Work, Handler, Signature>* this_handler)
  303. {
  304. boost_asio_handler_alloc_helpers::deallocate(
  305. pointer, size, this_handler->handler_);
  306. }
  307. template <typename Impl, typename Work, typename Handler, typename Signature>
  308. inline bool asio_handler_is_continuation(
  309. composed_op<Impl, Work, Handler, Signature>* this_handler)
  310. {
  311. return this_handler->invocations_ > 1 ? true
  312. : boost_asio_handler_cont_helpers::is_continuation(
  313. this_handler->handler_);
  314. }
  315. template <typename Function, typename Impl,
  316. typename Work, typename Handler, typename Signature>
  317. inline void asio_handler_invoke(Function& function,
  318. composed_op<Impl, Work, Handler, Signature>* this_handler)
  319. {
  320. boost_asio_handler_invoke_helpers::invoke(
  321. function, this_handler->handler_);
  322. }
  323. template <typename Function, typename Impl,
  324. typename Work, typename Handler, typename Signature>
  325. inline void asio_handler_invoke(const Function& function,
  326. composed_op<Impl, Work, Handler, Signature>* this_handler)
  327. {
  328. boost_asio_handler_invoke_helpers::invoke(
  329. function, this_handler->handler_);
  330. }
  331. template <typename Signature, typename Executors>
  332. class initiate_composed_op
  333. {
  334. public:
  335. typedef typename composed_io_executors<Executors>::head_type executor_type;
  336. template <typename T>
  337. explicit initiate_composed_op(BOOST_ASIO_MOVE_ARG(T) executors)
  338. : executors_(BOOST_ASIO_MOVE_CAST(T)(executors))
  339. {
  340. }
  341. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  342. {
  343. return executors_.head_;
  344. }
  345. template <typename Handler, typename Impl>
  346. void operator()(BOOST_ASIO_MOVE_ARG(Handler) handler,
  347. BOOST_ASIO_MOVE_ARG(Impl) impl) const
  348. {
  349. composed_op<typename decay<Impl>::type, composed_work<Executors>,
  350. typename decay<Handler>::type, Signature>(
  351. BOOST_ASIO_MOVE_CAST(Impl)(impl),
  352. composed_work<Executors>(executors_),
  353. BOOST_ASIO_MOVE_CAST(Handler)(handler))();
  354. }
  355. private:
  356. composed_io_executors<Executors> executors_;
  357. };
  358. template <typename Signature, typename Executors>
  359. inline initiate_composed_op<Signature, Executors> make_initiate_composed_op(
  360. BOOST_ASIO_MOVE_ARG(composed_io_executors<Executors>) executors)
  361. {
  362. return initiate_composed_op<Signature, Executors>(
  363. BOOST_ASIO_MOVE_CAST(composed_io_executors<Executors>)(executors));
  364. }
  365. template <typename IoObject>
  366. inline typename IoObject::executor_type
  367. get_composed_io_executor(IoObject& io_object)
  368. {
  369. return io_object.get_executor();
  370. }
  371. template <typename Executor>
  372. inline const Executor& get_composed_io_executor(const Executor& ex,
  373. typename enable_if<is_executor<Executor>::value>::type* = 0)
  374. {
  375. return ex;
  376. }
  377. } // namespace detail
  378. #if !defined(GENERATING_DOCUMENTATION)
  379. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  380. template <typename CompletionToken, typename Signature,
  381. typename Implementation, typename... IoObjectsOrExecutors>
  382. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
  383. async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
  384. BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
  385. BOOST_ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)
  386. {
  387. return async_initiate<CompletionToken, Signature>(
  388. detail::make_initiate_composed_op<Signature>(
  389. detail::make_composed_io_executors(
  390. detail::get_composed_io_executor(
  391. BOOST_ASIO_MOVE_CAST(IoObjectsOrExecutors)(
  392. io_objects_or_executors))...)),
  393. token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation));
  394. }
  395. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  396. template <typename CompletionToken, typename Signature, typename Implementation>
  397. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)
  398. async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
  399. BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
  400. {
  401. return async_initiate<CompletionToken, Signature>(
  402. detail::make_initiate_composed_op<Signature>(
  403. detail::make_composed_io_executors()),
  404. token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation));
  405. }
  406. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \
  407. BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n
  408. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \
  409. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1))
  410. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \
  411. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  412. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2))
  413. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \
  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. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \
  418. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  419. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  420. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
  421. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4))
  422. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \
  423. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  424. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  425. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
  426. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
  427. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5))
  428. #define BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
  429. template <typename CompletionToken, typename Signature, \
  430. typename Implementation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  431. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) \
  432. async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, \
  433. BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
  434. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  435. { \
  436. return async_initiate<CompletionToken, Signature>( \
  437. detail::make_initiate_composed_op<Signature>( \
  438. detail::make_composed_io_executors( \
  439. BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \
  440. token, BOOST_ASIO_MOVE_CAST(Implementation)(implementation)); \
  441. } \
  442. /**/
  443. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
  444. #undef BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF
  445. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR
  446. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1
  447. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2
  448. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3
  449. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4
  450. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5
  451. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  452. #endif // !defined(GENERATING_DOCUMENTATION)
  453. } // namespace asio
  454. } // namespace boost
  455. #include <boost/asio/detail/pop_options.hpp>
  456. #endif // BOOST_ASIO_IMPL_COMPOSE_HPP