defer.hpp 7.6 KB

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