]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/detail/handler_work.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / asio / detail / handler_work.hpp
CommitLineData
b32b8144
FG
1//
2// detail/handler_work.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_DETAIL_HANDLER_WORK_HPP
12#define BOOST_ASIO_DETAIL_HANDLER_WORK_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_executor.hpp>
20#include <boost/asio/detail/handler_invoke_helpers.hpp>
20effc67
TL
21#include <boost/asio/detail/type_traits.hpp>
22#include <boost/asio/execution/allocator.hpp>
23#include <boost/asio/execution/blocking.hpp>
24#include <boost/asio/execution/execute.hpp>
25#include <boost/asio/execution/executor.hpp>
26#include <boost/asio/execution/outstanding_work.hpp>
27#include <boost/asio/executor_work_guard.hpp>
28#include <boost/asio/prefer.hpp>
b32b8144
FG
29
30#include <boost/asio/detail/push_options.hpp>
31
32namespace boost {
33namespace asio {
20effc67
TL
34
35class executor;
36class io_context;
37
38namespace execution {
39
40#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
41
42template <typename...> class any_executor;
43
44#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
45
46template <typename, typename, typename, typename, typename,
47 typename, typename, typename, typename> class any_executor;
48
49#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
50
51} // namespace execution
b32b8144
FG
52namespace detail {
53
20effc67
TL
54template <typename Executor, typename CandidateExecutor = void,
55 typename IoContext = io_context,
56 typename PolymorphicExecutor = executor, typename = void>
57class handler_work_base
b32b8144
FG
58{
59public:
20effc67
TL
60 explicit handler_work_base(const Executor& ex) BOOST_ASIO_NOEXCEPT
61 : executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
92f5a8d4
TL
62 {
63 }
64
20effc67
TL
65 template <typename OtherExecutor>
66 handler_work_base(const Executor& ex,
67 const OtherExecutor&) BOOST_ASIO_NOEXCEPT
68 : executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
b32b8144
FG
69 {
70 }
71
20effc67
TL
72 handler_work_base(const handler_work_base& other) BOOST_ASIO_NOEXCEPT
73 : executor_(other.executor_)
b32b8144 74 {
92f5a8d4
TL
75 }
76
20effc67
TL
77#if defined(BOOST_ASIO_HAS_MOVE)
78 handler_work_base(handler_work_base&& other) BOOST_ASIO_NOEXCEPT
79 : executor_(BOOST_ASIO_MOVE_CAST(executor_type)(other.executor_))
92f5a8d4 80 {
b32b8144 81 }
20effc67 82#endif // defined(BOOST_ASIO_HAS_MOVE)
b32b8144 83
20effc67 84 bool owns_work() const BOOST_ASIO_NOEXCEPT
b32b8144 85 {
20effc67 86 return true;
b32b8144
FG
87 }
88
20effc67
TL
89 template <typename Function, typename Handler>
90 void dispatch(Function& function, Handler& handler)
91 {
92 execution::execute(
93 boost::asio::prefer(executor_,
94 execution::blocking.possibly,
95 execution::allocator((get_associated_allocator)(handler))),
96 BOOST_ASIO_MOVE_CAST(Function)(function));
97 }
98
99private:
100 typedef typename decay<
101 typename prefer_result<Executor,
102 execution::outstanding_work_t::tracked_t
103 >::type
104 >::type executor_type;
105
106 executor_type executor_;
107};
108
109template <typename Executor, typename CandidateExecutor,
110 typename IoContext, typename PolymorphicExecutor>
111class handler_work_base<Executor, CandidateExecutor,
112 IoContext, PolymorphicExecutor,
113 typename enable_if<
114 !execution::is_executor<Executor>::value
115 && (!is_same<Executor, PolymorphicExecutor>::value
116 || !is_same<CandidateExecutor, void>::value)
117 >::type>
118{
119public:
120 explicit handler_work_base(const Executor& ex) BOOST_ASIO_NOEXCEPT
121 : executor_(ex),
122 owns_work_(true)
123 {
124 executor_.on_work_started();
125 }
126
127 handler_work_base(const Executor& ex,
128 const Executor& candidate) BOOST_ASIO_NOEXCEPT
129 : executor_(ex),
130 owns_work_(ex != candidate)
131 {
132 if (owns_work_)
133 executor_.on_work_started();
134 }
135
136 template <typename OtherExecutor>
137 handler_work_base(const Executor& ex,
138 const OtherExecutor&) BOOST_ASIO_NOEXCEPT
139 : executor_(ex),
140 owns_work_(true)
141 {
142 executor_.on_work_started();
143 }
144
145 handler_work_base(const handler_work_base& other) BOOST_ASIO_NOEXCEPT
146 : executor_(other.executor_),
147 owns_work_(other.owns_work_)
148 {
149 if (owns_work_)
150 executor_.on_work_started();
151 }
152
153#if defined(BOOST_ASIO_HAS_MOVE)
154 handler_work_base(handler_work_base&& other) BOOST_ASIO_NOEXCEPT
155 : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_)),
156 owns_work_(other.owns_work_)
157 {
158 other.owns_work_ = false;
159 }
160#endif // defined(BOOST_ASIO_HAS_MOVE)
161
162 ~handler_work_base()
163 {
164 if (owns_work_)
165 executor_.on_work_finished();
166 }
167
168 bool owns_work() const BOOST_ASIO_NOEXCEPT
169 {
170 return owns_work_;
171 }
172
173 template <typename Function, typename Handler>
174 void dispatch(Function& function, Handler& handler)
175 {
176 executor_.dispatch(BOOST_ASIO_MOVE_CAST(Function)(function),
177 boost::asio::get_associated_allocator(handler));
178 }
179
180private:
181 Executor executor_;
182 bool owns_work_;
183};
184
185template <typename Executor, typename IoContext, typename PolymorphicExecutor>
186class handler_work_base<Executor, void, IoContext, PolymorphicExecutor,
187 typename enable_if<
188 is_same<
189 Executor,
190 typename IoContext::executor_type
191 >::value
192 >::type>
193{
194public:
195 explicit handler_work_base(const Executor&)
196 {
197 }
198
199 bool owns_work() const BOOST_ASIO_NOEXCEPT
200 {
201 return false;
202 }
203
204 template <typename Function, typename Handler>
205 void dispatch(Function& function, Handler& handler)
206 {
207 // When using a native implementation, I/O completion handlers are
208 // already dispatched according to the execution context's executor's
209 // rules. We can call the function directly.
210 boost_asio_handler_invoke_helpers::invoke(function, handler);
211 }
212};
213
214template <typename Executor, typename IoContext>
215class handler_work_base<Executor, void, IoContext, Executor>
216{
217public:
218 explicit handler_work_base(const Executor& ex) BOOST_ASIO_NOEXCEPT
219#if !defined(BOOST_ASIO_NO_TYPEID)
220 : executor_(
221 ex.target_type() == typeid(typename IoContext::executor_type)
222 ? Executor() : ex)
223#else // !defined(BOOST_ASIO_NO_TYPEID)
224 : executor_(ex)
225#endif // !defined(BOOST_ASIO_NO_TYPEID)
226 {
227 if (executor_)
228 executor_.on_work_started();
229 }
230
231 handler_work_base(const Executor& ex,
232 const Executor& candidate) BOOST_ASIO_NOEXCEPT
233 : executor_(ex != candidate ? ex : Executor())
234 {
235 if (executor_)
236 executor_.on_work_started();
237 }
238
239 template <typename OtherExecutor>
240 handler_work_base(const Executor& ex,
241 const OtherExecutor&) BOOST_ASIO_NOEXCEPT
242 : executor_(ex)
243 {
244 executor_.on_work_started();
245 }
246
247 handler_work_base(const handler_work_base& other) BOOST_ASIO_NOEXCEPT
248 : executor_(other.executor_)
249 {
250 if (executor_)
251 executor_.on_work_started();
252 }
253
254#if defined(BOOST_ASIO_HAS_MOVE)
255 handler_work_base(handler_work_base&& other) BOOST_ASIO_NOEXCEPT
256 : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_))
257 {
258 }
259#endif // defined(BOOST_ASIO_HAS_MOVE)
260
261 ~handler_work_base()
262 {
263 if (executor_)
264 executor_.on_work_finished();
265 }
266
267 bool owns_work() const BOOST_ASIO_NOEXCEPT
268 {
269 return !!executor_;
270 }
271
272 template <typename Function, typename Handler>
273 void dispatch(Function& function, Handler& handler)
b32b8144
FG
274 {
275 executor_.dispatch(BOOST_ASIO_MOVE_CAST(Function)(function),
92f5a8d4 276 boost::asio::get_associated_allocator(handler));
b32b8144
FG
277 }
278
279private:
20effc67
TL
280 Executor executor_;
281};
282
283template <
284#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
285 typename... SupportableProperties,
286#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
287 typename T1, typename T2, typename T3, typename T4, typename T5,
288 typename T6, typename T7, typename T8, typename T9,
289#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
290 typename IoContext, typename PolymorphicExecutor>
291class handler_work_base<
292#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
293 execution::any_executor<SupportableProperties...>,
294#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
295 execution::any_executor<T1, T2, T3, T4, T5, T6, T7, T8, T9>,
296#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
297 void, IoContext, PolymorphicExecutor>
298{
299public:
300 typedef
301#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
302 execution::any_executor<SupportableProperties...>
303#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
304 execution::any_executor<T1, T2, T3, T4, T5, T6, T7, T8, T9>
305#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
306 executor_type;
307
308 explicit handler_work_base(const executor_type& ex) BOOST_ASIO_NOEXCEPT
309#if !defined(BOOST_ASIO_NO_TYPEID)
310 : executor_(
311 ex.target_type() == typeid(typename IoContext::executor_type)
312 ? executor_type()
313 : boost::asio::prefer(ex, execution::outstanding_work.tracked))
314#else // !defined(BOOST_ASIO_NO_TYPEID)
315 : executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
316#endif // !defined(BOOST_ASIO_NO_TYPEID)
317 {
318 }
319
320 handler_work_base(const executor_type& ex,
321 const executor_type& candidate) BOOST_ASIO_NOEXCEPT
322 : executor_(ex != candidate ? ex : executor_type())
323 {
324 }
325
326 template <typename OtherExecutor>
327 handler_work_base(const executor_type& ex,
328 const OtherExecutor&) BOOST_ASIO_NOEXCEPT
329 : executor_(boost::asio::prefer(ex, execution::outstanding_work.tracked))
330 {
331 }
332
333 handler_work_base(const handler_work_base& other) BOOST_ASIO_NOEXCEPT
334 : executor_(other.executor_)
335 {
336 }
337
338#if defined(BOOST_ASIO_HAS_MOVE)
339 handler_work_base(handler_work_base&& other) BOOST_ASIO_NOEXCEPT
340 : executor_(BOOST_ASIO_MOVE_CAST(executor_type)(other.executor_))
341 {
342 }
343#endif // defined(BOOST_ASIO_HAS_MOVE)
b32b8144 344
20effc67
TL
345 bool owns_work() const BOOST_ASIO_NOEXCEPT
346 {
347 return !!executor_;
348 }
349
350 template <typename Function, typename Handler>
351 void dispatch(Function& function, Handler& handler)
352 {
353 execution::execute(
354 boost::asio::prefer(executor_,
355 execution::blocking.possibly,
356 execution::allocator((get_associated_allocator)(handler))),
357 BOOST_ASIO_MOVE_CAST(Function)(function));
358 }
359
360private:
361 executor_type executor_;
b32b8144
FG
362};
363
20effc67
TL
364template <typename Handler, typename IoExecutor, typename = void>
365class handler_work :
366 handler_work_base<IoExecutor>,
367 handler_work_base<typename associated_executor<
368 Handler, IoExecutor>::type, IoExecutor>
b32b8144
FG
369{
370public:
20effc67
TL
371 typedef handler_work_base<IoExecutor> base1_type;
372 typedef handler_work_base<typename associated_executor<
373 Handler, IoExecutor>::type, IoExecutor> base2_type;
374
375 handler_work(Handler& handler, const IoExecutor& io_ex) BOOST_ASIO_NOEXCEPT
376 : base1_type(io_ex),
377 base2_type(boost::asio::get_associated_executor(handler, io_ex), io_ex)
378 {
379 }
b32b8144
FG
380
381 template <typename Function>
382 void complete(Function& function, Handler& handler)
383 {
20effc67
TL
384 if (!base1_type::owns_work() && !base2_type::owns_work())
385 {
386 // When using a native implementation, I/O completion handlers are
387 // already dispatched according to the execution context's executor's
388 // rules. We can call the function directly.
389 boost_asio_handler_invoke_helpers::invoke(function, handler);
390 }
391 else
392 {
393 base2_type::dispatch(function, handler);
394 }
b32b8144 395 }
20effc67 396};
b32b8144 397
20effc67
TL
398template <typename Handler, typename IoExecutor>
399class handler_work<
400 Handler, IoExecutor,
401 typename enable_if<
402 is_same<
403 typename associated_executor<Handler,
404 IoExecutor>::asio_associated_executor_is_unspecialised,
405 void
406 >::value
407 >::type> : handler_work_base<IoExecutor>
408{
409public:
410 typedef handler_work_base<IoExecutor> base1_type;
411
412 handler_work(Handler&, const IoExecutor& io_ex) BOOST_ASIO_NOEXCEPT
413 : base1_type(io_ex)
414 {
415 }
416
417 template <typename Function>
418 void complete(Function& function, Handler& handler)
419 {
420 if (!base1_type::owns_work())
421 {
422 // When using a native implementation, I/O completion handlers are
423 // already dispatched according to the execution context's executor's
424 // rules. We can call the function directly.
425 boost_asio_handler_invoke_helpers::invoke(function, handler);
426 }
427 else
428 {
429 base1_type::dispatch(function, handler);
430 }
431 }
b32b8144
FG
432};
433
434} // namespace detail
435} // namespace asio
436} // namespace boost
437
438#include <boost/asio/detail/pop_options.hpp>
439
440#endif // BOOST_ASIO_DETAIL_HANDLER_WORK_HPP