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