initiate_defer.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. //
  2. // detail/initiate_defer.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 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_DETAIL_INITIATE_DEFER_HPP
  11. #define ASIO_DETAIL_INITIATE_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()(CompletionHandler&& handler,
  32. enable_if_t<
  33. execution::is_executor<
  34. associated_executor_t<decay_t<CompletionHandler>>
  35. >::value
  36. >* = 0) const
  37. {
  38. associated_executor_t<decay_t<CompletionHandler>> ex(
  39. (get_associated_executor)(handler));
  40. associated_allocator_t<decay_t<CompletionHandler>> alloc(
  41. (get_associated_allocator)(handler));
  42. asio::prefer(
  43. asio::require(ex, execution::blocking.never),
  44. execution::relationship.continuation,
  45. execution::allocator(alloc)
  46. ).execute(
  47. asio::detail::bind_handler(
  48. static_cast<CompletionHandler&&>(handler)));
  49. }
  50. template <typename CompletionHandler>
  51. void operator()(CompletionHandler&& handler,
  52. enable_if_t<
  53. !execution::is_executor<
  54. associated_executor_t<decay_t<CompletionHandler>>
  55. >::value
  56. >* = 0) const
  57. {
  58. associated_executor_t<decay_t<CompletionHandler>> ex(
  59. (get_associated_executor)(handler));
  60. associated_allocator_t<decay_t<CompletionHandler>> alloc(
  61. (get_associated_allocator)(handler));
  62. ex.defer(asio::detail::bind_handler(
  63. static_cast<CompletionHandler&&>(handler)), alloc);
  64. }
  65. };
  66. template <typename Executor>
  67. class initiate_defer_with_executor
  68. {
  69. public:
  70. typedef Executor executor_type;
  71. explicit initiate_defer_with_executor(const Executor& ex)
  72. : ex_(ex)
  73. {
  74. }
  75. executor_type get_executor() const noexcept
  76. {
  77. return ex_;
  78. }
  79. template <typename CompletionHandler>
  80. void operator()(CompletionHandler&& handler,
  81. enable_if_t<
  82. execution::is_executor<
  83. conditional_t<true, executor_type, CompletionHandler>
  84. >::value
  85. >* = 0,
  86. enable_if_t<
  87. !detail::is_work_dispatcher_required<
  88. decay_t<CompletionHandler>,
  89. Executor
  90. >::value
  91. >* = 0) const
  92. {
  93. associated_allocator_t<decay_t<CompletionHandler>> alloc(
  94. (get_associated_allocator)(handler));
  95. asio::prefer(
  96. asio::require(ex_, execution::blocking.never),
  97. execution::relationship.continuation,
  98. execution::allocator(alloc)
  99. ).execute(
  100. asio::detail::bind_handler(
  101. static_cast<CompletionHandler&&>(handler)));
  102. }
  103. template <typename CompletionHandler>
  104. void operator()(CompletionHandler&& handler,
  105. enable_if_t<
  106. execution::is_executor<
  107. conditional_t<true, executor_type, CompletionHandler>
  108. >::value
  109. >* = 0,
  110. enable_if_t<
  111. detail::is_work_dispatcher_required<
  112. decay_t<CompletionHandler>,
  113. Executor
  114. >::value
  115. >* = 0) const
  116. {
  117. typedef decay_t<CompletionHandler> handler_t;
  118. typedef associated_executor_t<handler_t, Executor> handler_ex_t;
  119. handler_ex_t handler_ex((get_associated_executor)(handler, ex_));
  120. associated_allocator_t<handler_t> alloc(
  121. (get_associated_allocator)(handler));
  122. asio::prefer(
  123. asio::require(ex_, execution::blocking.never),
  124. execution::relationship.continuation,
  125. execution::allocator(alloc)
  126. ).execute(
  127. detail::work_dispatcher<handler_t, handler_ex_t>(
  128. static_cast<CompletionHandler&&>(handler), handler_ex));
  129. }
  130. template <typename CompletionHandler>
  131. void operator()(CompletionHandler&& handler,
  132. enable_if_t<
  133. !execution::is_executor<
  134. conditional_t<true, executor_type, CompletionHandler>
  135. >::value
  136. >* = 0,
  137. enable_if_t<
  138. !detail::is_work_dispatcher_required<
  139. decay_t<CompletionHandler>,
  140. Executor
  141. >::value
  142. >* = 0) const
  143. {
  144. associated_allocator_t<decay_t<CompletionHandler>> alloc(
  145. (get_associated_allocator)(handler));
  146. ex_.defer(asio::detail::bind_handler(
  147. static_cast<CompletionHandler&&>(handler)), alloc);
  148. }
  149. template <typename CompletionHandler>
  150. void operator()(CompletionHandler&& handler,
  151. enable_if_t<
  152. !execution::is_executor<
  153. conditional_t<true, executor_type, CompletionHandler>
  154. >::value
  155. >* = 0,
  156. enable_if_t<
  157. detail::is_work_dispatcher_required<
  158. decay_t<CompletionHandler>,
  159. Executor
  160. >::value
  161. >* = 0) const
  162. {
  163. typedef decay_t<CompletionHandler> handler_t;
  164. typedef associated_executor_t<handler_t, Executor> handler_ex_t;
  165. handler_ex_t handler_ex((get_associated_executor)(handler, ex_));
  166. associated_allocator_t<handler_t> alloc(
  167. (get_associated_allocator)(handler));
  168. ex_.defer(detail::work_dispatcher<handler_t, handler_ex_t>(
  169. static_cast<CompletionHandler&&>(handler), handler_ex), alloc);
  170. }
  171. private:
  172. Executor ex_;
  173. };
  174. } // namespace detail
  175. } // namespace asio
  176. #include "asio/detail/pop_options.hpp"
  177. #endif // ASIO_DETAIL_INITIATE_DEFER_HPP