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