dispatch.hpp 7.4 KB

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