dispatch.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. //
  2. // impl/dispatch.hpp
  3. // ~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2021 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_DISPATCH_HPP
  11. #define BOOST_ASIO_IMPL_DISPATCH_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_allocator.hpp>
  17. #include <boost/asio/associated_executor.hpp>
  18. #include <boost/asio/detail/work_dispatcher.hpp>
  19. #include <boost/asio/execution/allocator.hpp>
  20. #include <boost/asio/execution/blocking.hpp>
  21. #include <boost/asio/prefer.hpp>
  22. #include <boost/asio/detail/push_options.hpp>
  23. namespace boost {
  24. namespace asio {
  25. namespace detail {
  26. class initiate_dispatch
  27. {
  28. public:
  29. template <typename CompletionHandler>
  30. void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
  31. typename enable_if<
  32. execution::is_executor<
  33. typename associated_executor<
  34. typename decay<CompletionHandler>::type
  35. >::type
  36. >::value
  37. >::type* = 0) const
  38. {
  39. typedef typename decay<CompletionHandler>::type handler_t;
  40. typename associated_executor<handler_t>::type ex(
  41. (get_associated_executor)(handler));
  42. typename associated_allocator<handler_t>::type alloc(
  43. (get_associated_allocator)(handler));
  44. execution::execute(
  45. boost::asio::prefer(ex,
  46. execution::blocking.possibly,
  47. execution::allocator(alloc)),
  48. BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
  49. }
  50. template <typename CompletionHandler>
  51. void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
  52. typename enable_if<
  53. !execution::is_executor<
  54. typename associated_executor<
  55. typename decay<CompletionHandler>::type
  56. >::type
  57. >::value
  58. >::type* = 0) const
  59. {
  60. typedef typename decay<CompletionHandler>::type handler_t;
  61. typename associated_executor<handler_t>::type ex(
  62. (get_associated_executor)(handler));
  63. typename associated_allocator<handler_t>::type alloc(
  64. (get_associated_allocator)(handler));
  65. ex.dispatch(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
  66. }
  67. };
  68. template <typename Executor>
  69. class initiate_dispatch_with_executor
  70. {
  71. public:
  72. typedef Executor executor_type;
  73. explicit initiate_dispatch_with_executor(const Executor& ex)
  74. : ex_(ex)
  75. {
  76. }
  77. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  78. {
  79. return ex_;
  80. }
  81. template <typename CompletionHandler>
  82. void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
  83. typename enable_if<
  84. execution::is_executor<
  85. typename conditional<true, executor_type, CompletionHandler>::type
  86. >::value
  87. >::type* = 0,
  88. typename enable_if<
  89. !detail::is_work_dispatcher_required<
  90. typename decay<CompletionHandler>::type,
  91. Executor
  92. >::value
  93. >::type* = 0) const
  94. {
  95. typedef typename decay<CompletionHandler>::type handler_t;
  96. typename associated_allocator<handler_t>::type alloc(
  97. (get_associated_allocator)(handler));
  98. execution::execute(
  99. boost::asio::prefer(ex_,
  100. execution::blocking.possibly,
  101. execution::allocator(alloc)),
  102. BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
  103. }
  104. template <typename CompletionHandler>
  105. void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
  106. typename enable_if<
  107. execution::is_executor<
  108. typename conditional<true, executor_type, CompletionHandler>::type
  109. >::value
  110. >::type* = 0,
  111. typename enable_if<
  112. detail::is_work_dispatcher_required<
  113. typename decay<CompletionHandler>::type,
  114. Executor
  115. >::value
  116. >::type* = 0) const
  117. {
  118. typedef typename decay<CompletionHandler>::type handler_t;
  119. typedef typename associated_executor<
  120. handler_t, Executor>::type handler_ex_t;
  121. handler_ex_t handler_ex((get_associated_executor)(handler, ex_));
  122. typename associated_allocator<handler_t>::type alloc(
  123. (get_associated_allocator)(handler));
  124. execution::execute(
  125. boost::asio::prefer(ex_,
  126. execution::blocking.possibly,
  127. execution::allocator(alloc)),
  128. detail::work_dispatcher<handler_t, handler_ex_t>(
  129. BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));
  130. }
  131. template <typename CompletionHandler>
  132. void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
  133. typename enable_if<
  134. !execution::is_executor<
  135. typename conditional<true, executor_type, CompletionHandler>::type
  136. >::value
  137. >::type* = 0,
  138. typename enable_if<
  139. !detail::is_work_dispatcher_required<
  140. typename decay<CompletionHandler>::type,
  141. Executor
  142. >::value
  143. >::type* = 0) const
  144. {
  145. typedef typename decay<CompletionHandler>::type handler_t;
  146. typename associated_allocator<handler_t>::type alloc(
  147. (get_associated_allocator)(handler));
  148. ex_.dispatch(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
  149. }
  150. template <typename CompletionHandler>
  151. void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
  152. typename enable_if<
  153. !execution::is_executor<
  154. typename conditional<true, executor_type, CompletionHandler>::type
  155. >::value
  156. >::type* = 0,
  157. typename enable_if<
  158. detail::is_work_dispatcher_required<
  159. typename decay<CompletionHandler>::type,
  160. Executor
  161. >::value
  162. >::type* = 0) const
  163. {
  164. typedef typename decay<CompletionHandler>::type handler_t;
  165. typedef typename associated_executor<
  166. handler_t, Executor>::type handler_ex_t;
  167. handler_ex_t handler_ex((get_associated_executor)(handler, ex_));
  168. typename associated_allocator<handler_t>::type alloc(
  169. (get_associated_allocator)(handler));
  170. ex_.dispatch(detail::work_dispatcher<handler_t, handler_ex_t>(
  171. BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler),
  172. handler_ex), alloc);
  173. }
  174. private:
  175. Executor ex_;
  176. };
  177. } // namespace detail
  178. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>
  179. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(
  180. BOOST_ASIO_MOVE_ARG(CompletionToken) token)
  181. {
  182. return async_initiate<CompletionToken, void()>(
  183. detail::initiate_dispatch(), token);
  184. }
  185. template <typename Executor,
  186. BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>
  187. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(
  188. const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
  189. typename constraint<
  190. execution::is_executor<Executor>::value || is_executor<Executor>::value
  191. >::type)
  192. {
  193. return async_initiate<CompletionToken, void()>(
  194. detail::initiate_dispatch_with_executor<Executor>(ex), token);
  195. }
  196. template <typename ExecutionContext,
  197. BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>
  198. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(
  199. ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
  200. typename constraint<is_convertible<
  201. ExecutionContext&, execution_context&>::value>::type)
  202. {
  203. return async_initiate<CompletionToken, void()>(
  204. detail::initiate_dispatch_with_executor<
  205. typename ExecutionContext::executor_type>(
  206. ctx.get_executor()), token);
  207. }
  208. } // namespace asio
  209. } // namespace boost
  210. #include <boost/asio/detail/pop_options.hpp>
  211. #endif // BOOST_ASIO_IMPL_DISPATCH_HPP