compose.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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_work;
  31. template <>
  32. struct composed_work<void()>
  33. {
  34. composed_work() BOOST_ASIO_NOEXCEPT
  35. : head_(system_executor())
  36. {
  37. }
  38. void reset()
  39. {
  40. head_.reset();
  41. }
  42. typedef system_executor head_type;
  43. executor_work_guard<system_executor> head_;
  44. };
  45. inline composed_work<void()> make_composed_work()
  46. {
  47. return composed_work<void()>();
  48. }
  49. template <typename Head>
  50. struct composed_work<void(Head)>
  51. {
  52. explicit composed_work(const Head& ex) BOOST_ASIO_NOEXCEPT
  53. : head_(ex)
  54. {
  55. }
  56. void reset()
  57. {
  58. head_.reset();
  59. }
  60. typedef Head head_type;
  61. executor_work_guard<Head> head_;
  62. };
  63. template <typename Head>
  64. inline composed_work<void(Head)> make_composed_work(const Head& head)
  65. {
  66. return composed_work<void(Head)>(head);
  67. }
  68. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  69. template <typename Head, typename... Tail>
  70. struct composed_work<void(Head, Tail...)>
  71. {
  72. explicit composed_work(const Head& head,
  73. const Tail&... tail) BOOST_ASIO_NOEXCEPT
  74. : head_(head),
  75. tail_(tail...)
  76. {
  77. }
  78. void reset()
  79. {
  80. head_.reset();
  81. tail_.reset();
  82. }
  83. typedef Head head_type;
  84. executor_work_guard<Head> head_;
  85. composed_work<void(Tail...)> tail_;
  86. };
  87. template <typename Head, typename... Tail>
  88. inline composed_work<void(Head, Tail...)>
  89. make_composed_work(const Head& head, const Tail&... tail)
  90. {
  91. return composed_work<void(Head, Tail...)>(head, tail...);
  92. }
  93. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  94. #define BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \
  95. template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  96. struct composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
  97. { \
  98. explicit composed_work(const Head& head, \
  99. BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) BOOST_ASIO_NOEXCEPT \
  100. : head_(head), \
  101. tail_(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) \
  102. { \
  103. } \
  104. \
  105. void reset() \
  106. { \
  107. head_.reset(); \
  108. tail_.reset(); \
  109. } \
  110. \
  111. typedef Head head_type; \
  112. executor_work_guard<Head> head_; \
  113. composed_work<void(BOOST_ASIO_VARIADIC_TARGS(n))> tail_; \
  114. }; \
  115. \
  116. template <typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  117. inline composed_work<void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
  118. make_composed_work(const Head& head, BOOST_ASIO_VARIADIC_CONSTREF_PARAMS(n)) \
  119. { \
  120. return composed_work< \
  121. void(Head, BOOST_ASIO_VARIADIC_TARGS(n))>( \
  122. head, BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)); \
  123. } \
  124. /**/
  125. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF)
  126. #undef BOOST_ASIO_PRIVATE_COMPOSED_WORK_DEF
  127. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  128. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  129. template <typename Impl, typename Work, typename Handler, typename Signature>
  130. class composed_op;
  131. template <typename Impl, typename Work, typename Handler,
  132. typename R, typename... Args>
  133. class composed_op<Impl, Work, Handler, R(Args...)>
  134. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  135. template <typename Impl, typename Work, typename Handler, typename Signature>
  136. class composed_op
  137. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  138. {
  139. public:
  140. composed_op(BOOST_ASIO_MOVE_ARG(Impl) impl,
  141. BOOST_ASIO_MOVE_ARG(Work) work,
  142. BOOST_ASIO_MOVE_ARG(Handler) handler)
  143. : impl_(BOOST_ASIO_MOVE_CAST(Impl)(impl)),
  144. work_(BOOST_ASIO_MOVE_CAST(Work)(work)),
  145. handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
  146. invocations_(0)
  147. {
  148. }
  149. #if defined(BOOST_ASIO_HAS_MOVE)
  150. composed_op(composed_op&& other)
  151. : impl_(BOOST_ASIO_MOVE_CAST(Impl)(other.impl_)),
  152. work_(BOOST_ASIO_MOVE_CAST(Work)(other.work_)),
  153. handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
  154. invocations_(other.invocations_)
  155. {
  156. }
  157. #endif // defined(BOOST_ASIO_HAS_MOVE)
  158. typedef typename associated_executor<Handler,
  159. typename Work::head_type>::type executor_type;
  160. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  161. {
  162. return (get_associated_executor)(handler_, work_.head_.get_executor());
  163. }
  164. typedef typename associated_allocator<Handler,
  165. std::allocator<void> >::type allocator_type;
  166. allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
  167. {
  168. return (get_associated_allocator)(handler_, std::allocator<void>());
  169. }
  170. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  171. template<typename... T>
  172. void operator()(BOOST_ASIO_MOVE_ARG(T)... t)
  173. {
  174. if (invocations_ < ~unsigned(0))
  175. ++invocations_;
  176. impl_(*this, BOOST_ASIO_MOVE_CAST(T)(t)...);
  177. }
  178. void complete(Args... args)
  179. {
  180. this->work_.reset();
  181. this->handler_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
  182. }
  183. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  184. void operator()()
  185. {
  186. if (invocations_ < ~unsigned(0))
  187. ++invocations_;
  188. impl_(*this);
  189. }
  190. void complete()
  191. {
  192. this->work_.reset();
  193. this->handler_();
  194. }
  195. #define BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF(n) \
  196. template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  197. void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  198. { \
  199. if (invocations_ < ~unsigned(0)) \
  200. ++invocations_; \
  201. impl_(*this, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  202. } \
  203. \
  204. template<BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  205. void complete(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  206. { \
  207. this->work_.reset(); \
  208. this->handler_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  209. } \
  210. /**/
  211. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF)
  212. #undef BOOST_ASIO_PRIVATE_COMPOSED_OP_DEF
  213. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  214. //private:
  215. Impl impl_;
  216. Work work_;
  217. Handler handler_;
  218. unsigned invocations_;
  219. };
  220. template <typename Impl, typename Work, typename Handler, typename Signature>
  221. inline void* asio_handler_allocate(std::size_t size,
  222. composed_op<Impl, Work, Handler, Signature>* this_handler)
  223. {
  224. return boost_asio_handler_alloc_helpers::allocate(
  225. size, this_handler->handler_);
  226. }
  227. template <typename Impl, typename Work, typename Handler, typename Signature>
  228. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  229. composed_op<Impl, Work, Handler, Signature>* this_handler)
  230. {
  231. boost_asio_handler_alloc_helpers::deallocate(
  232. pointer, size, this_handler->handler_);
  233. }
  234. template <typename Impl, typename Work, typename Handler, typename Signature>
  235. inline bool asio_handler_is_continuation(
  236. composed_op<Impl, Work, Handler, Signature>* this_handler)
  237. {
  238. return this_handler->invocations_ > 1 ? true
  239. : boost_asio_handler_cont_helpers::is_continuation(
  240. this_handler->handler_);
  241. }
  242. template <typename Function, typename Impl,
  243. typename Work, typename Handler, typename Signature>
  244. inline void asio_handler_invoke(Function& function,
  245. composed_op<Impl, Work, Handler, Signature>* this_handler)
  246. {
  247. boost_asio_handler_invoke_helpers::invoke(
  248. function, this_handler->handler_);
  249. }
  250. template <typename Function, typename Impl,
  251. typename Work, typename Handler, typename Signature>
  252. inline void asio_handler_invoke(const Function& function,
  253. composed_op<Impl, Work, Handler, Signature>* this_handler)
  254. {
  255. boost_asio_handler_invoke_helpers::invoke(
  256. function, this_handler->handler_);
  257. }
  258. template <typename Signature>
  259. struct initiate_composed_op
  260. {
  261. template <typename Handler, typename Impl, typename Work>
  262. void operator()(BOOST_ASIO_MOVE_ARG(Handler) handler,
  263. BOOST_ASIO_MOVE_ARG(Impl) impl,
  264. BOOST_ASIO_MOVE_ARG(Work) work) const
  265. {
  266. composed_op<typename decay<Impl>::type, typename decay<Work>::type,
  267. typename decay<Handler>::type, Signature>(
  268. BOOST_ASIO_MOVE_CAST(Impl)(impl), BOOST_ASIO_MOVE_CAST(Work)(work),
  269. BOOST_ASIO_MOVE_CAST(Handler)(handler))();
  270. }
  271. };
  272. template <typename IoObject>
  273. inline typename IoObject::executor_type
  274. get_composed_io_executor(IoObject& io_object)
  275. {
  276. return io_object.get_executor();
  277. }
  278. template <typename Executor>
  279. inline const Executor& get_composed_io_executor(const Executor& ex,
  280. typename enable_if<is_executor<Executor>::value>::type* = 0)
  281. {
  282. return ex;
  283. }
  284. } // namespace detail
  285. #if !defined(GENERATING_DOCUMENTATION)
  286. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  287. template <typename CompletionToken, typename Signature,
  288. typename Implementation, typename... IoObjectsOrExecutors>
  289. BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
  290. async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
  291. BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,
  292. BOOST_ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)
  293. {
  294. return async_initiate<CompletionToken, Signature>(
  295. detail::initiate_composed_op<Signature>(), token,
  296. BOOST_ASIO_MOVE_CAST(Implementation)(implementation),
  297. detail::make_composed_work(
  298. detail::get_composed_io_executor(
  299. BOOST_ASIO_MOVE_CAST(IoObjectsOrExecutors)(
  300. io_objects_or_executors))...));
  301. }
  302. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  303. template <typename CompletionToken, typename Signature, typename Implementation>
  304. BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)
  305. async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation,
  306. BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)
  307. {
  308. return async_initiate<CompletionToken, Signature>(
  309. detail::initiate_composed_op<Signature>(), token,
  310. BOOST_ASIO_MOVE_CAST(Implementation)(implementation),
  311. detail::make_composed_work());
  312. }
  313. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \
  314. BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n
  315. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \
  316. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1))
  317. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \
  318. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  319. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2))
  320. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \
  321. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  322. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  323. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3))
  324. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \
  325. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  326. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  327. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
  328. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4))
  329. # define BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \
  330. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T1)(x1)), \
  331. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T2)(x2)), \
  332. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T3)(x3)), \
  333. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T4)(x4)), \
  334. detail::get_composed_io_executor(BOOST_ASIO_MOVE_CAST(T5)(x5))
  335. #define BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \
  336. template <typename CompletionToken, typename Signature, \
  337. typename Implementation, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  338. BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature) \
  339. async_compose(BOOST_ASIO_MOVE_ARG(Implementation) implementation, \
  340. BOOST_ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \
  341. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  342. { \
  343. return async_initiate<CompletionToken, Signature>( \
  344. detail::initiate_composed_op<Signature>(), token, \
  345. BOOST_ASIO_MOVE_CAST(Implementation)(implementation), \
  346. detail::make_composed_work( \
  347. BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))); \
  348. } \
  349. /**/
  350. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF)
  351. #undef BOOST_ASIO_PRIVATE_ASYNC_COMPOSE_DEF
  352. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR
  353. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1
  354. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2
  355. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3
  356. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4
  357. #undef BOOST_ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5
  358. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  359. #endif // !defined(GENERATING_DOCUMENTATION)
  360. } // namespace asio
  361. } // namespace boost
  362. #include <boost/asio/detail/pop_options.hpp>
  363. #endif // BOOST_ASIO_IMPL_COMPOSE_HPP