]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // impl/defer.hpp | |
3 | // ~~~~~~~~~~~~~~ | |
4 | // | |
f67539c2 | 5 | // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
b32b8144 FG |
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_IMPL_DEFER_HPP | |
12 | #define BOOST_ASIO_IMPL_DEFER_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/associated_allocator.hpp> | |
20 | #include <boost/asio/associated_executor.hpp> | |
21 | #include <boost/asio/detail/work_dispatcher.hpp> | |
20effc67 TL |
22 | #include <boost/asio/execution/allocator.hpp> |
23 | #include <boost/asio/execution/blocking.hpp> | |
24 | #include <boost/asio/execution/relationship.hpp> | |
25 | #include <boost/asio/prefer.hpp> | |
26 | #include <boost/asio/require.hpp> | |
b32b8144 FG |
27 | |
28 | #include <boost/asio/detail/push_options.hpp> | |
29 | ||
30 | namespace boost { | |
31 | namespace asio { | |
92f5a8d4 | 32 | namespace detail { |
b32b8144 | 33 | |
92f5a8d4 | 34 | class initiate_defer |
b32b8144 | 35 | { |
92f5a8d4 TL |
36 | public: |
37 | template <typename CompletionHandler> | |
20effc67 TL |
38 | void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, |
39 | typename enable_if< | |
40 | execution::is_executor< | |
41 | typename associated_executor< | |
42 | typename decay<CompletionHandler>::type | |
43 | >::type | |
44 | >::value | |
45 | >::type* = 0) const | |
92f5a8d4 | 46 | { |
20effc67 | 47 | typedef typename decay<CompletionHandler>::type handler_t; |
b32b8144 | 48 | |
20effc67 | 49 | typename associated_executor<handler_t>::type ex( |
92f5a8d4 | 50 | (get_associated_executor)(handler)); |
b32b8144 | 51 | |
20effc67 TL |
52 | typename associated_allocator<handler_t>::type alloc( |
53 | (get_associated_allocator)(handler)); | |
54 | ||
55 | execution::execute( | |
56 | boost::asio::prefer( | |
57 | boost::asio::require(ex, execution::blocking.never), | |
58 | execution::relationship.continuation, | |
59 | execution::allocator(alloc)), | |
60 | BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)); | |
61 | } | |
62 | ||
63 | template <typename CompletionHandler> | |
64 | void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, | |
65 | typename enable_if< | |
66 | !execution::is_executor< | |
67 | typename associated_executor< | |
68 | typename decay<CompletionHandler>::type | |
69 | >::type | |
70 | >::value | |
71 | >::type* = 0) const | |
72 | { | |
73 | typedef typename decay<CompletionHandler>::type handler_t; | |
74 | ||
75 | typename associated_executor<handler_t>::type ex( | |
76 | (get_associated_executor)(handler)); | |
77 | ||
78 | typename associated_allocator<handler_t>::type alloc( | |
92f5a8d4 | 79 | (get_associated_allocator)(handler)); |
b32b8144 | 80 | |
92f5a8d4 TL |
81 | ex.defer(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc); |
82 | } | |
83 | }; | |
b32b8144 | 84 | |
92f5a8d4 TL |
85 | template <typename Executor> |
86 | class initiate_defer_with_executor | |
87 | { | |
88 | public: | |
89 | typedef Executor executor_type; | |
b32b8144 | 90 | |
92f5a8d4 TL |
91 | explicit initiate_defer_with_executor(const Executor& ex) |
92 | : ex_(ex) | |
93 | { | |
94 | } | |
b32b8144 | 95 | |
92f5a8d4 TL |
96 | executor_type get_executor() const BOOST_ASIO_NOEXCEPT |
97 | { | |
98 | return ex_; | |
99 | } | |
100 | ||
101 | template <typename CompletionHandler> | |
20effc67 TL |
102 | void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, |
103 | typename enable_if< | |
104 | execution::is_executor< | |
105 | typename conditional<true, executor_type, CompletionHandler>::type | |
106 | >::value | |
107 | && | |
108 | !detail::is_work_dispatcher_required< | |
109 | typename decay<CompletionHandler>::type, | |
110 | Executor | |
111 | >::value | |
112 | >::type* = 0) const | |
92f5a8d4 | 113 | { |
20effc67 TL |
114 | typedef typename decay<CompletionHandler>::type handler_t; |
115 | ||
116 | typename associated_allocator<handler_t>::type alloc( | |
117 | (get_associated_allocator)(handler)); | |
118 | ||
119 | execution::execute( | |
120 | boost::asio::prefer( | |
121 | boost::asio::require(ex_, execution::blocking.never), | |
122 | execution::relationship.continuation, | |
123 | execution::allocator(alloc)), | |
124 | BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler)); | |
125 | } | |
126 | ||
127 | template <typename CompletionHandler> | |
128 | void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, | |
129 | typename enable_if< | |
130 | execution::is_executor< | |
131 | typename conditional<true, executor_type, CompletionHandler>::type | |
132 | >::value | |
133 | && | |
134 | detail::is_work_dispatcher_required< | |
135 | typename decay<CompletionHandler>::type, | |
136 | Executor | |
137 | >::value | |
138 | >::type* = 0) const | |
139 | { | |
140 | typedef typename decay<CompletionHandler>::type handler_t; | |
141 | ||
142 | typedef typename associated_executor< | |
143 | handler_t, Executor>::type handler_ex_t; | |
144 | handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); | |
92f5a8d4 | 145 | |
20effc67 | 146 | typename associated_allocator<handler_t>::type alloc( |
92f5a8d4 | 147 | (get_associated_allocator)(handler)); |
b32b8144 | 148 | |
20effc67 TL |
149 | execution::execute( |
150 | boost::asio::prefer( | |
151 | boost::asio::require(ex_, execution::blocking.never), | |
152 | execution::relationship.continuation, | |
153 | execution::allocator(alloc)), | |
154 | detail::work_dispatcher<handler_t, handler_ex_t>( | |
155 | BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex)); | |
156 | } | |
157 | ||
158 | template <typename CompletionHandler> | |
159 | void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, | |
160 | typename enable_if< | |
161 | !execution::is_executor< | |
162 | typename conditional<true, executor_type, CompletionHandler>::type | |
163 | >::value | |
164 | && | |
165 | !detail::is_work_dispatcher_required< | |
166 | typename decay<CompletionHandler>::type, | |
167 | Executor | |
168 | >::value | |
169 | >::type* = 0) const | |
170 | { | |
171 | typedef typename decay<CompletionHandler>::type handler_t; | |
172 | ||
173 | typename associated_allocator<handler_t>::type alloc( | |
174 | (get_associated_allocator)(handler)); | |
175 | ||
176 | ex_.defer(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc); | |
177 | } | |
178 | ||
179 | template <typename CompletionHandler> | |
180 | void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler, | |
181 | typename enable_if< | |
182 | !execution::is_executor< | |
183 | typename conditional<true, executor_type, CompletionHandler>::type | |
184 | >::value | |
185 | && | |
186 | detail::is_work_dispatcher_required< | |
187 | typename decay<CompletionHandler>::type, | |
188 | Executor | |
189 | >::value | |
190 | >::type* = 0) const | |
191 | { | |
192 | typedef typename decay<CompletionHandler>::type handler_t; | |
193 | ||
194 | typedef typename associated_executor< | |
195 | handler_t, Executor>::type handler_ex_t; | |
196 | handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); | |
197 | ||
198 | typename associated_allocator<handler_t>::type alloc( | |
199 | (get_associated_allocator)(handler)); | |
200 | ||
201 | ex_.defer(detail::work_dispatcher<handler_t, handler_ex_t>( | |
202 | BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), | |
203 | handler_ex), alloc); | |
92f5a8d4 | 204 | } |
b32b8144 | 205 | |
92f5a8d4 TL |
206 | private: |
207 | Executor ex_; | |
208 | }; | |
b32b8144 | 209 | |
92f5a8d4 | 210 | } // namespace detail |
b32b8144 | 211 | |
92f5a8d4 TL |
212 | template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> |
213 | BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( | |
214 | BOOST_ASIO_MOVE_ARG(CompletionToken) token) | |
215 | { | |
216 | return async_initiate<CompletionToken, void()>( | |
217 | detail::initiate_defer(), token); | |
218 | } | |
219 | ||
220 | template <typename Executor, | |
221 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> | |
222 | BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( | |
223 | const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token, | |
20effc67 TL |
224 | typename enable_if< |
225 | execution::is_executor<Executor>::value || is_executor<Executor>::value | |
226 | >::type*) | |
92f5a8d4 TL |
227 | { |
228 | return async_initiate<CompletionToken, void()>( | |
229 | detail::initiate_defer_with_executor<Executor>(ex), token); | |
b32b8144 FG |
230 | } |
231 | ||
92f5a8d4 TL |
232 | template <typename ExecutionContext, |
233 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> | |
234 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( | |
b32b8144 FG |
235 | ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token, |
236 | typename enable_if<is_convertible< | |
237 | ExecutionContext&, execution_context&>::value>::type*) | |
238 | { | |
20effc67 TL |
239 | return async_initiate<CompletionToken, void()>( |
240 | detail::initiate_defer_with_executor< | |
241 | typename ExecutionContext::executor_type>( | |
242 | ctx.get_executor()), token); | |
b32b8144 FG |
243 | } |
244 | ||
245 | } // namespace asio | |
246 | } // namespace boost | |
247 | ||
248 | #include <boost/asio/detail/pop_options.hpp> | |
249 | ||
250 | #endif // BOOST_ASIO_IMPL_DEFER_HPP |