]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/bind_executor.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / asio / bind_executor.hpp
1 //
2 // bind_executor.hpp
3 // ~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2017 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_BIND_EXECUTOR_HPP
12 #define BOOST_ASIO_BIND_EXECUTOR_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/detail/type_traits.hpp>
20 #include <boost/asio/detail/variadic_templates.hpp>
21 #include <boost/asio/associated_executor.hpp>
22 #include <boost/asio/associated_allocator.hpp>
23 #include <boost/asio/async_result.hpp>
24 #include <boost/asio/execution_context.hpp>
25 #include <boost/asio/is_executor.hpp>
26 #include <boost/asio/uses_executor.hpp>
27
28 #include <boost/asio/detail/push_options.hpp>
29
30 namespace boost {
31 namespace asio {
32 namespace detail {
33
34 template <typename T>
35 struct executor_binder_check
36 {
37 typedef void type;
38 };
39
40 // Helper to automatically define nested typedef result_type.
41
42 template <typename T, typename = void>
43 struct executor_binder_result_type
44 {
45 protected:
46 typedef void result_type_or_void;
47 };
48
49 template <typename T>
50 struct executor_binder_result_type<T,
51 typename executor_binder_check<typename T::result_type>::type>
52 {
53 typedef typename T::result_type result_type;
54 protected:
55 typedef result_type result_type_or_void;
56 };
57
58 template <typename R>
59 struct executor_binder_result_type<R(*)()>
60 {
61 typedef R result_type;
62 protected:
63 typedef result_type result_type_or_void;
64 };
65
66 template <typename R>
67 struct executor_binder_result_type<R(&)()>
68 {
69 typedef R result_type;
70 protected:
71 typedef result_type result_type_or_void;
72 };
73
74 template <typename R, typename A1>
75 struct executor_binder_result_type<R(*)(A1)>
76 {
77 typedef R result_type;
78 protected:
79 typedef result_type result_type_or_void;
80 };
81
82 template <typename R, typename A1>
83 struct executor_binder_result_type<R(&)(A1)>
84 {
85 typedef R result_type;
86 protected:
87 typedef result_type result_type_or_void;
88 };
89
90 template <typename R, typename A1, typename A2>
91 struct executor_binder_result_type<R(*)(A1, A2)>
92 {
93 typedef R result_type;
94 protected:
95 typedef result_type result_type_or_void;
96 };
97
98 template <typename R, typename A1, typename A2>
99 struct executor_binder_result_type<R(&)(A1, A2)>
100 {
101 typedef R result_type;
102 protected:
103 typedef result_type result_type_or_void;
104 };
105
106 // Helper to automatically define nested typedef argument_type.
107
108 template <typename T, typename = void>
109 struct executor_binder_argument_type {};
110
111 template <typename T>
112 struct executor_binder_argument_type<T,
113 typename executor_binder_check<typename T::argument_type>::type>
114 {
115 typedef typename T::argument_type argument_type;
116 };
117
118 template <typename R, typename A1>
119 struct executor_binder_argument_type<R(*)(A1)>
120 {
121 typedef A1 argument_type;
122 };
123
124 template <typename R, typename A1>
125 struct executor_binder_argument_type<R(&)(A1)>
126 {
127 typedef A1 argument_type;
128 };
129
130 // Helper to automatically define nested typedefs first_argument_type and
131 // second_argument_type.
132
133 template <typename T, typename = void>
134 struct executor_binder_argument_types {};
135
136 template <typename T>
137 struct executor_binder_argument_types<T,
138 typename executor_binder_check<typename T::first_argument_type>::type>
139 {
140 typedef typename T::first_argument_type first_argument_type;
141 typedef typename T::second_argument_type second_argument_type;
142 };
143
144 template <typename R, typename A1, typename A2>
145 struct executor_binder_argument_type<R(*)(A1, A2)>
146 {
147 typedef A1 first_argument_type;
148 typedef A2 second_argument_type;
149 };
150
151 template <typename R, typename A1, typename A2>
152 struct executor_binder_argument_type<R(&)(A1, A2)>
153 {
154 typedef A1 first_argument_type;
155 typedef A2 second_argument_type;
156 };
157
158 // Helper to:
159 // - Apply the empty base optimisation to the executor.
160 // - Perform uses_executor construction of the target type, if required.
161
162 template <typename T, typename Executor, bool UsesExecutor>
163 class executor_binder_base;
164
165 template <typename T, typename Executor>
166 class executor_binder_base<T, Executor, true>
167 : protected Executor
168 {
169 protected:
170 template <typename E, typename U>
171 executor_binder_base(BOOST_ASIO_MOVE_ARG(E) e, BOOST_ASIO_MOVE_ARG(U) u)
172 : executor_(BOOST_ASIO_MOVE_CAST(E)(e)),
173 target_(executor_arg_t(), executor_, BOOST_ASIO_MOVE_CAST(U)(u))
174 {
175 }
176
177 Executor executor_;
178 T target_;
179 };
180
181 template <typename T, typename Executor>
182 class executor_binder_base<T, Executor, false>
183 {
184 protected:
185 template <typename E, typename U>
186 executor_binder_base(BOOST_ASIO_MOVE_ARG(E) e, BOOST_ASIO_MOVE_ARG(U) u)
187 : executor_(BOOST_ASIO_MOVE_CAST(E)(e)),
188 target_(BOOST_ASIO_MOVE_CAST(U)(u))
189 {
190 }
191
192 Executor executor_;
193 T target_;
194 };
195
196 // Helper to enable SFINAE on zero-argument operator() below.
197
198 template <typename T, typename = void>
199 struct executor_binder_result_of0
200 {
201 typedef void type;
202 };
203
204 template <typename T>
205 struct executor_binder_result_of0<T,
206 typename executor_binder_check<typename result_of<T()>::type>::type>
207 {
208 typedef typename result_of<T()>::type type;
209 };
210
211 } // namespace detail
212
213 /// A call wrapper type to bind an executor of type @c Executor to an object of
214 /// type @c T.
215 template <typename T, typename Executor>
216 class executor_binder
217 #if !defined(GENERATING_DOCUMENTATION)
218 : public detail::executor_binder_result_type<T>,
219 public detail::executor_binder_argument_type<T>,
220 public detail::executor_binder_argument_types<T>,
221 private detail::executor_binder_base<
222 T, Executor, uses_executor<T, Executor>::value>
223 #endif // !defined(GENERATING_DOCUMENTATION)
224 {
225 public:
226 /// The type of the target object.
227 typedef T target_type;
228
229 /// The type of the associated executor.
230 typedef Executor executor_type;
231
232 #if defined(GENERATING_DOCUMENTATION)
233 /// The return type if a function.
234 /**
235 * The type of @c result_type is based on the type @c T of the wrapper's
236 * target object:
237 *
238 * @li if @c T is a pointer to function type, @c result_type is a synonym for
239 * the return type of @c T;
240 *
241 * @li if @c T is a class type with a member type @c result_type, then @c
242 * result_type is a synonym for @c T::result_type;
243 *
244 * @li otherwise @c result_type is not defined.
245 */
246 typedef see_below result_type;
247
248 /// The type of the function's argument.
249 /**
250 * The type of @c argument_type is based on the type @c T of the wrapper's
251 * target object:
252 *
253 * @li if @c T is a pointer to a function type accepting a single argument,
254 * @c argument_type is a synonym for the return type of @c T;
255 *
256 * @li if @c T is a class type with a member type @c argument_type, then @c
257 * argument_type is a synonym for @c T::argument_type;
258 *
259 * @li otherwise @c argument_type is not defined.
260 */
261 typedef see_below argument_type;
262
263 /// The type of the function's first argument.
264 /**
265 * The type of @c first_argument_type is based on the type @c T of the
266 * wrapper's target object:
267 *
268 * @li if @c T is a pointer to a function type accepting two arguments, @c
269 * first_argument_type is a synonym for the return type of @c T;
270 *
271 * @li if @c T is a class type with a member type @c first_argument_type,
272 * then @c first_argument_type is a synonym for @c T::first_argument_type;
273 *
274 * @li otherwise @c first_argument_type is not defined.
275 */
276 typedef see_below first_argument_type;
277
278 /// The type of the function's second argument.
279 /**
280 * The type of @c second_argument_type is based on the type @c T of the
281 * wrapper's target object:
282 *
283 * @li if @c T is a pointer to a function type accepting two arguments, @c
284 * second_argument_type is a synonym for the return type of @c T;
285 *
286 * @li if @c T is a class type with a member type @c first_argument_type,
287 * then @c second_argument_type is a synonym for @c T::second_argument_type;
288 *
289 * @li otherwise @c second_argument_type is not defined.
290 */
291 typedef see_below second_argument_type;
292 #endif // defined(GENERATING_DOCUMENTATION)
293
294 /// Construct an executor wrapper for the specified object.
295 /**
296 * This constructor is only valid if the type @c T is constructible from type
297 * @c U.
298 */
299 template <typename U>
300 executor_binder(executor_arg_t, const executor_type& e,
301 BOOST_ASIO_MOVE_ARG(U) u)
302 : base_type(e, BOOST_ASIO_MOVE_CAST(U)(u))
303 {
304 }
305
306 /// Copy constructor.
307 executor_binder(const executor_binder& other)
308 : base_type(other.get_executor(), other.get())
309 {
310 }
311
312 /// Construct a copy, but specify a different executor.
313 executor_binder(executor_arg_t, const executor_type& e,
314 const executor_binder& other)
315 : base_type(e, other.get())
316 {
317 }
318
319 /// Construct a copy of a different executor wrapper type.
320 /**
321 * This constructor is only valid if the @c Executor type is constructible
322 * from type @c OtherExecutor, and the type @c T is constructible from type
323 * @c U.
324 */
325 template <typename U, typename OtherExecutor>
326 executor_binder(const executor_binder<U, OtherExecutor>& other)
327 : base_type(other.get_executor(), other.get())
328 {
329 }
330
331 /// Construct a copy of a different executor wrapper type, but specify a
332 /// different executor.
333 /**
334 * This constructor is only valid if the type @c T is constructible from type
335 * @c U.
336 */
337 template <typename U, typename OtherExecutor>
338 executor_binder(executor_arg_t, const executor_type& e,
339 const executor_binder<U, OtherExecutor>& other)
340 : base_type(e, other.get())
341 {
342 }
343
344 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
345
346 /// Move constructor.
347 executor_binder(executor_binder&& other)
348 : base_type(BOOST_ASIO_MOVE_CAST(executor_type)(other.get_executor()),
349 BOOST_ASIO_MOVE_CAST(T)(other.get()))
350 {
351 }
352
353 /// Move construct the target object, but specify a different executor.
354 executor_binder(executor_arg_t, const executor_type& e,
355 executor_binder&& other)
356 : base_type(e, BOOST_ASIO_MOVE_CAST(T)(other.get()))
357 {
358 }
359
360 /// Move construct from a different executor wrapper type.
361 template <typename U, typename OtherExecutor>
362 executor_binder(executor_binder<U, OtherExecutor>&& other)
363 : base_type(BOOST_ASIO_MOVE_CAST(OtherExecutor)(other.get_executor()),
364 BOOST_ASIO_MOVE_CAST(U)(other.get()))
365 {
366 }
367
368 /// Move construct from a different executor wrapper type, but specify a
369 /// different executor.
370 template <typename U, typename OtherExecutor>
371 executor_binder(executor_arg_t, const executor_type& e,
372 executor_binder<U, OtherExecutor>&& other)
373 : base_type(e, BOOST_ASIO_MOVE_CAST(U)(other.get()))
374 {
375 }
376
377 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
378
379 /// Destructor.
380 ~executor_binder()
381 {
382 }
383
384 /// Obtain a reference to the target object.
385 target_type& get() BOOST_ASIO_NOEXCEPT
386 {
387 return this->target_;
388 }
389
390 /// Obtain a reference to the target object.
391 const target_type& get() const BOOST_ASIO_NOEXCEPT
392 {
393 return this->target_;
394 }
395
396 /// Obtain the associated executor.
397 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
398 {
399 return this->executor_;
400 }
401
402 #if defined(GENERATING_DOCUMENTATION)
403
404 template <typename... Args> auto operator()(Args&& ...);
405 template <typename... Args> auto operator()(Args&& ...) const;
406
407 #elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
408
409 /// Forwarding function call operator.
410 template <typename... Args>
411 typename result_of<T(Args...)>::type operator()(
412 BOOST_ASIO_MOVE_ARG(Args)... args)
413 {
414 return this->target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
415 }
416
417 /// Forwarding function call operator.
418 template <typename... Args>
419 typename result_of<T(Args...)>::type operator()(
420 BOOST_ASIO_MOVE_ARG(Args)... args) const
421 {
422 return this->target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
423 }
424
425 #elif defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
426
427 typename detail::executor_binder_result_of0<T>::type operator()()
428 {
429 return this->target_();
430 }
431
432 typename detail::executor_binder_result_of0<T>::type operator()() const
433 {
434 return this->target_();
435 }
436
437 #define BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
438 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
439 typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
440 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
441 { \
442 return this->target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
443 } \
444 \
445 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
446 typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
447 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
448 { \
449 return this->target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
450 } \
451 /**/
452 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
453 #undef BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
454
455 #else // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
456
457 typedef typename detail::executor_binder_result_type<T>::result_type_or_void
458 result_type_or_void;
459
460 result_type_or_void operator()()
461 {
462 return this->target_();
463 }
464
465 result_type_or_void operator()() const
466 {
467 return this->target_();
468 }
469
470 #define BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
471 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
472 result_type_or_void operator()( \
473 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
474 { \
475 return this->target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
476 } \
477 \
478 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
479 result_type_or_void operator()( \
480 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
481 { \
482 return this->target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
483 } \
484 /**/
485 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
486 #undef BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
487
488 #endif // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
489
490 private:
491 typedef detail::executor_binder_base<T, Executor,
492 uses_executor<T, Executor>::value> base_type;
493 };
494
495 /// Associate an object of type @c T with an executor of type @c Executor.
496 template <typename Executor, typename T>
497 inline executor_binder<typename decay<T>::type, Executor>
498 bind_executor(const Executor& ex, BOOST_ASIO_MOVE_ARG(T) t,
499 typename enable_if<is_executor<Executor>::value>::type* = 0)
500 {
501 return executor_binder<typename decay<T>::type, Executor>(
502 executor_arg_t(), ex, BOOST_ASIO_MOVE_CAST(T)(t));
503 }
504
505 /// Associate an object of type @c T with an execution context's executor.
506 template <typename ExecutionContext, typename T>
507 inline executor_binder<typename decay<T>::type,
508 typename ExecutionContext::executor_type>
509 bind_executor(ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(T) t,
510 typename enable_if<is_convertible<
511 ExecutionContext&, execution_context&>::value>::type* = 0)
512 {
513 return executor_binder<typename decay<T>::type,
514 typename ExecutionContext::executor_type>(
515 executor_arg_t(), ctx.get_executor(), BOOST_ASIO_MOVE_CAST(T)(t));
516 }
517
518 #if !defined(GENERATING_DOCUMENTATION)
519
520 template <typename T, typename Executor>
521 struct uses_executor<executor_binder<T, Executor>, Executor>
522 : true_type {};
523
524 template <typename T, typename Executor, typename Signature>
525 class async_result<executor_binder<T, Executor>, Signature>
526 {
527 public:
528 typedef executor_binder<
529 typename async_result<T, Signature>::completion_handler_type, Executor>
530 completion_handler_type;
531
532 typedef typename async_result<T, Signature>::return_type return_type;
533
534 explicit async_result(executor_binder<T, Executor>& b)
535 : target_(b.get())
536 {
537 }
538
539 return_type get()
540 {
541 return target_.get();
542 }
543
544 private:
545 async_result(const async_result&) BOOST_ASIO_DELETED;
546 async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
547
548 async_result<T, Signature> target_;
549 };
550
551 #if !defined(BOOST_ASIO_NO_DEPRECATED)
552
553 template <typename T, typename Executor, typename Signature>
554 struct handler_type<executor_binder<T, Executor>, Signature>
555 {
556 typedef executor_binder<
557 typename handler_type<T, Signature>::type, Executor> type;
558 };
559
560 template <typename T, typename Executor>
561 class async_result<executor_binder<T, Executor> >
562 {
563 public:
564 typedef typename async_result<T>::type type;
565
566 explicit async_result(executor_binder<T, Executor>& b)
567 : target_(b.get())
568 {
569 }
570
571 type get()
572 {
573 return target_.get();
574 }
575
576 private:
577 async_result<T> target_;
578 };
579
580 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
581
582 template <typename T, typename Executor, typename Allocator>
583 struct associated_allocator<executor_binder<T, Executor>, Allocator>
584 {
585 typedef typename associated_allocator<T, Allocator>::type type;
586
587 static type get(const executor_binder<T, Executor>& b,
588 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
589 {
590 return associated_allocator<T, Allocator>::get(b.get(), a);
591 }
592 };
593
594 template <typename T, typename Executor, typename Executor1>
595 struct associated_executor<executor_binder<T, Executor>, Executor1>
596 {
597 typedef Executor type;
598
599 static type get(const executor_binder<T, Executor>& b,
600 const Executor1& = Executor1()) BOOST_ASIO_NOEXCEPT
601 {
602 return b.get_executor();
603 }
604 };
605
606 #endif // !defined(GENERATING_DOCUMENTATION)
607
608 } // namespace asio
609 } // namespace boost
610
611 #include <boost/asio/detail/pop_options.hpp>
612
613 #endif // BOOST_ASIO_BIND_EXECUTOR_HPP