post.hpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //
  2. // post.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_POST_HPP
  11. #define ASIO_POST_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/async_result.hpp"
  17. #include "asio/detail/initiate_post.hpp"
  18. #include "asio/detail/type_traits.hpp"
  19. #include "asio/execution_context.hpp"
  20. #include "asio/execution/blocking.hpp"
  21. #include "asio/execution/executor.hpp"
  22. #include "asio/is_executor.hpp"
  23. #include "asio/require.hpp"
  24. #include "asio/detail/push_options.hpp"
  25. namespace asio {
  26. /// Submits a completion token or function object for execution.
  27. /**
  28. * This function submits an object for execution using the object's associated
  29. * executor. The function object is queued for execution, and is never called
  30. * from the current thread prior to returning from <tt>post()</tt>.
  31. *
  32. * The use of @c post(), rather than @ref defer(), indicates the caller's
  33. * preference that the function object be eagerly queued for execution.
  34. *
  35. * @param token The @ref completion_token that will be used to produce a
  36. * completion handler. The function signature of the completion handler must be:
  37. * @code void handler(); @endcode
  38. *
  39. * @returns This function returns <tt>async_initiate<NullaryToken,
  40. * void()>(Init{}, token)</tt>, where @c Init is a function object type defined
  41. * as:
  42. *
  43. * @code class Init
  44. * {
  45. * public:
  46. * template <typename CompletionHandler>
  47. * void operator()(CompletionHandler&& completion_handler) const;
  48. * }; @endcode
  49. *
  50. * The function call operator of @c Init:
  51. *
  52. * @li Obtains the handler's associated executor object @c ex of type @c Ex by
  53. * performing @code auto ex = get_associated_executor(handler); @endcode
  54. *
  55. * @li Obtains the handler's associated allocator object @c alloc by performing
  56. * @code auto alloc = get_associated_allocator(handler); @endcode
  57. *
  58. * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs
  59. * @code prefer(
  60. * require(ex, execution::blocking.never),
  61. * execution::relationship.fork,
  62. * execution::allocator(alloc)
  63. * ).execute(std::forward<CompletionHandler>(completion_handler)); @endcode
  64. *
  65. * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs
  66. * @code ex.post(
  67. * std::forward<CompletionHandler>(completion_handler),
  68. * alloc); @endcode
  69. *
  70. * @par Completion Signature
  71. * @code void() @endcode
  72. */
  73. template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken>
  74. inline auto post(NullaryToken&& token)
  75. -> decltype(
  76. async_initiate<NullaryToken, void()>(
  77. declval<detail::initiate_post>(), token))
  78. {
  79. return async_initiate<NullaryToken, void()>(
  80. detail::initiate_post(), token);
  81. }
  82. /// Submits a completion token or function object for execution.
  83. /**
  84. * This function submits an object for execution using the specified executor.
  85. * The function object is queued for execution, and is never called from the
  86. * current thread prior to returning from <tt>post()</tt>.
  87. *
  88. * The use of @c post(), rather than @ref defer(), indicates the caller's
  89. * preference that the function object be eagerly queued for execution.
  90. *
  91. * @param ex The target executor.
  92. *
  93. * @param token The @ref completion_token that will be used to produce a
  94. * completion handler. The function signature of the completion handler must be:
  95. * @code void handler(); @endcode
  96. *
  97. * @returns This function returns <tt>async_initiate<NullaryToken,
  98. * void()>(Init{ex}, token)</tt>, where @c Init is a function object type
  99. * defined as:
  100. *
  101. * @code class Init
  102. * {
  103. * public:
  104. * using executor_type = Executor;
  105. * explicit Init(const Executor& ex) : ex_(ex) {}
  106. * executor_type get_executor() const noexcept { return ex_; }
  107. * template <typename CompletionHandler>
  108. * void operator()(CompletionHandler&& completion_handler) const;
  109. * private:
  110. * Executor ex_; // exposition only
  111. * }; @endcode
  112. *
  113. * The function call operator of @c Init:
  114. *
  115. * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by
  116. * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode
  117. *
  118. * @li Obtains the handler's associated allocator object @c alloc by performing
  119. * @code auto alloc = get_associated_allocator(handler); @endcode
  120. *
  121. * @li If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a
  122. * function object @c f with a member @c executor_ that is initialised with
  123. * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c
  124. * handler_ that is a decay-copy of @c completion_handler, and a function call
  125. * operator that performs:
  126. * @code auto a = get_associated_allocator(handler_);
  127. * prefer(executor_, execution::allocator(a)).execute(std::move(handler_));
  128. * @endcode
  129. *
  130. * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a
  131. * function object @c f with a member @c work_ that is initialised with
  132. * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of
  133. * @c completion_handler, and a function call operator that performs:
  134. * @code auto a = get_associated_allocator(handler_);
  135. * work_.get_executor().dispatch(std::move(handler_), a);
  136. * work_.reset(); @endcode
  137. *
  138. * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs
  139. * @code prefer(
  140. * require(ex, execution::blocking.never),
  141. * execution::relationship.fork,
  142. * execution::allocator(alloc)
  143. * ).execute(std::move(f)); @endcode
  144. *
  145. * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs
  146. * @code ex.post(std::move(f), alloc); @endcode
  147. *
  148. * @par Completion Signature
  149. * @code void() @endcode
  150. */
  151. template <typename Executor,
  152. ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken
  153. = default_completion_token_t<Executor>>
  154. inline auto post(const Executor& ex,
  155. NullaryToken&& token = default_completion_token_t<Executor>(),
  156. constraint_t<
  157. (execution::is_executor<Executor>::value
  158. && can_require<Executor, execution::blocking_t::never_t>::value)
  159. || is_executor<Executor>::value
  160. > = 0)
  161. -> decltype(
  162. async_initiate<NullaryToken, void()>(
  163. declval<detail::initiate_post_with_executor<Executor>>(), token))
  164. {
  165. return async_initiate<NullaryToken, void()>(
  166. detail::initiate_post_with_executor<Executor>(ex), token);
  167. }
  168. /// Submits a completion token or function object for execution.
  169. /**
  170. * @param ctx An execution context, from which the target executor is obtained.
  171. *
  172. * @param token The @ref completion_token that will be used to produce a
  173. * completion handler. The function signature of the completion handler must be:
  174. * @code void handler(); @endcode
  175. *
  176. * @returns <tt>post(ctx.get_executor(), forward<NullaryToken>(token))</tt>.
  177. *
  178. * @par Completion Signature
  179. * @code void() @endcode
  180. */
  181. template <typename ExecutionContext,
  182. ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken
  183. = default_completion_token_t<typename ExecutionContext::executor_type>>
  184. inline auto post(ExecutionContext& ctx,
  185. NullaryToken&& token = default_completion_token_t<
  186. typename ExecutionContext::executor_type>(),
  187. constraint_t<
  188. is_convertible<ExecutionContext&, execution_context&>::value
  189. > = 0)
  190. -> decltype(
  191. async_initiate<NullaryToken, void()>(
  192. declval<detail::initiate_post_with_executor<
  193. typename ExecutionContext::executor_type>>(), token))
  194. {
  195. return async_initiate<NullaryToken, void()>(
  196. detail::initiate_post_with_executor<
  197. typename ExecutionContext::executor_type>(
  198. ctx.get_executor()), token);
  199. }
  200. } // namespace asio
  201. #include "asio/detail/pop_options.hpp"
  202. #endif // ASIO_POST_HPP