]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/execution/any_executor.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / asio / execution / any_executor.hpp
1 //
2 // execution/any_executor.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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_EXECUTION_ANY_EXECUTOR_HPP
12 #define BOOST_ASIO_EXECUTION_ANY_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 <new>
20 #include <typeinfo>
21 #include <boost/asio/detail/assert.hpp>
22 #include <boost/asio/detail/cstddef.hpp>
23 #include <boost/asio/detail/executor_function.hpp>
24 #include <boost/asio/detail/memory.hpp>
25 #include <boost/asio/detail/non_const_lvalue.hpp>
26 #include <boost/asio/detail/scoped_ptr.hpp>
27 #include <boost/asio/detail/type_traits.hpp>
28 #include <boost/asio/detail/throw_exception.hpp>
29 #include <boost/asio/detail/variadic_templates.hpp>
30 #include <boost/asio/execution/bad_executor.hpp>
31 #include <boost/asio/execution/blocking.hpp>
32 #include <boost/asio/execution/execute.hpp>
33 #include <boost/asio/execution/executor.hpp>
34 #include <boost/asio/prefer.hpp>
35 #include <boost/asio/query.hpp>
36 #include <boost/asio/require.hpp>
37
38 #include <boost/asio/detail/push_options.hpp>
39
40 namespace boost {
41 namespace asio {
42
43 #if defined(GENERATING_DOCUMENTATION)
44
45 namespace execution {
46
47 /// Polymorphic executor wrapper.
48 template <typename... SupportableProperties>
49 class any_executor
50 {
51 public:
52 /// Default constructor.
53 any_executor() noexcept;
54
55 /// Construct in an empty state. Equivalent effects to default constructor.
56 any_executor(nullptr_t) noexcept;
57
58 /// Copy constructor.
59 any_executor(const any_executor& e) noexcept;
60
61 /// Move constructor.
62 any_executor(any_executor&& e) noexcept;
63
64 /// Construct to point to the same target as another any_executor.
65 template <class... OtherSupportableProperties>
66 any_executor(any_executor<OtherSupportableProperties...> e);
67
68 /// Construct a polymorphic wrapper for the specified executor.
69 template <typename Executor>
70 any_executor(Executor e);
71
72 /// Assignment operator.
73 any_executor& operator=(const any_executor& e) noexcept;
74
75 /// Move assignment operator.
76 any_executor& operator=(any_executor&& e) noexcept;
77
78 /// Assignment operator that sets the polymorphic wrapper to the empty state.
79 any_executor& operator=(nullptr_t);
80
81 /// Assignment operator to create a polymorphic wrapper for the specified
82 /// executor.
83 template <typename Executor>
84 any_executor& operator=(Executor e);
85
86 /// Destructor.
87 ~any_executor();
88
89 /// Swap targets with another polymorphic wrapper.
90 void swap(any_executor& other) noexcept;
91
92 /// Obtain a polymorphic wrapper with the specified property.
93 /**
94 * Do not call this function directly. It is intended for use with the
95 * boost::asio::require and boost::asio::prefer customisation points.
96 *
97 * For example:
98 * @code execution::any_executor<execution::blocking_t::possibly_t> ex = ...;
99 * auto ex2 = boost::asio::requre(ex, execution::blocking.possibly); @endcode
100 */
101 template <typename Property>
102 any_executor require(Property) const;
103
104 /// Obtain a polymorphic wrapper with the specified property.
105 /**
106 * Do not call this function directly. It is intended for use with the
107 * boost::asio::prefer customisation point.
108 *
109 * For example:
110 * @code execution::any_executor<execution::blocking_t::possibly_t> ex = ...;
111 * auto ex2 = boost::asio::prefer(ex, execution::blocking.possibly); @endcode
112 */
113 template <typename Property>
114 any_executor prefer(Property) const;
115
116 /// Obtain the value associated with the specified property.
117 /**
118 * Do not call this function directly. It is intended for use with the
119 * boost::asio::query customisation point.
120 *
121 * For example:
122 * @code execution::any_executor<execution::occupancy_t> ex = ...;
123 * size_t n = boost::asio::query(ex, execution::occupancy); @endcode
124 */
125 template <typename Property>
126 typename Property::polymorphic_query_result_type query(Property) const;
127
128 /// Execute the function on the target executor.
129 /**
130 * Do not call this function directly. It is intended for use with the
131 * execution::execute customisation point.
132 *
133 * For example:
134 * @code execution::any_executor<> ex = ...;
135 * execution::execute(ex, my_function_object); @endcode
136 *
137 * Throws boost::asio::bad_executor if the polymorphic wrapper has no target.
138 */
139 template <typename Function>
140 void execute(Function&& f) const;
141
142 /// Obtain the underlying execution context.
143 /**
144 * This function is provided for backward compatibility. It is automatically
145 * defined when the @c SupportableProperties... list includes a property of
146 * type <tt>execution::context_as<U></tt>, for some type <tt>U</tt>.
147 */
148 automatically_determined context() const;
149
150 /// Determine whether the wrapper has a target executor.
151 /**
152 * @returns @c true if the polymorphic wrapper has a target executor,
153 * otherwise false.
154 */
155 explicit operator bool() const noexcept;
156
157 /// Get the type of the target executor.
158 const type_info& target_type() const noexcept;
159
160 /// Get a pointer to the target executor.
161 template <typename Executor> Executor* target() noexcept;
162
163 /// Get a pointer to the target executor.
164 template <typename Executor> const Executor* target() const noexcept;
165 };
166
167 /// Equality operator.
168 /**
169 * @relates any_executor
170 */
171 template <typename... SupportableProperties>
172 bool operator==(const any_executor<SupportableProperties...>& a,
173 const any_executor<SupportableProperties...>& b) noexcept;
174
175 /// Equality operator.
176 /**
177 * @relates any_executor
178 */
179 template <typename... SupportableProperties>
180 bool operator==(const any_executor<SupportableProperties...>& a,
181 nullptr_t) noexcept;
182
183 /// Equality operator.
184 /**
185 * @relates any_executor
186 */
187 template <typename... SupportableProperties>
188 bool operator==(nullptr_t,
189 const any_executor<SupportableProperties...>& b) noexcept;
190
191 /// Inequality operator.
192 /**
193 * @relates any_executor
194 */
195 template <typename... SupportableProperties>
196 bool operator!=(const any_executor<SupportableProperties...>& a,
197 const any_executor<SupportableProperties...>& b) noexcept;
198
199 /// Inequality operator.
200 /**
201 * @relates any_executor
202 */
203 template <typename... SupportableProperties>
204 bool operator!=(const any_executor<SupportableProperties...>& a,
205 nullptr_t) noexcept;
206
207 /// Inequality operator.
208 /**
209 * @relates any_executor
210 */
211 template <typename... SupportableProperties>
212 bool operator!=(nullptr_t,
213 const any_executor<SupportableProperties...>& b) noexcept;
214
215 } // namespace execution
216
217 #else // defined(GENERATING_DOCUMENTATION)
218
219 namespace execution {
220
221 #if !defined(BOOST_ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)
222 #define BOOST_ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL
223
224 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
225
226 template <typename... SupportableProperties>
227 class any_executor;
228
229 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
230
231 template <typename = void, typename = void, typename = void,
232 typename = void, typename = void, typename = void,
233 typename = void, typename = void, typename = void>
234 class any_executor;
235
236 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
237
238 #endif // !defined(BOOST_ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)
239
240 template <typename U>
241 struct context_as_t;
242
243 namespace detail {
244
245 // Traits used to detect whether a property is requirable or preferable, taking
246 // into account that T::is_requirable or T::is_preferable may not not be well
247 // formed.
248
249 template <typename T, typename = void>
250 struct is_requirable : false_type {};
251
252 template <typename T>
253 struct is_requirable<T, typename enable_if<T::is_requirable>::type> :
254 true_type {};
255
256 template <typename T, typename = void>
257 struct is_preferable : false_type {};
258
259 template <typename T>
260 struct is_preferable<T, typename enable_if<T::is_preferable>::type> :
261 true_type {};
262
263 // Trait used to detect context_as property, for backward compatibility.
264
265 template <typename T>
266 struct is_context_as : false_type {};
267
268 template <typename U>
269 struct is_context_as<context_as_t<U> > : true_type {};
270
271 // Helper template to:
272 // - Check if a target can supply the supportable properties.
273 // - Find the first convertible-from-T property in the list.
274
275 template <std::size_t I, typename Props>
276 struct supportable_properties;
277
278 template <std::size_t I, typename Prop>
279 struct supportable_properties<I, void(Prop)>
280 {
281 template <typename T>
282 struct is_valid_target : integral_constant<bool,
283 (
284 is_requirable<Prop>::value
285 ? can_require<T, Prop>::value
286 : true
287 )
288 &&
289 (
290 is_preferable<Prop>::value
291 ? can_prefer<T, Prop>::value
292 : true
293 )
294 &&
295 (
296 !is_requirable<Prop>::value && !is_preferable<Prop>::value
297 ? can_query<T, Prop>::value
298 : true
299 )
300 >
301 {
302 };
303
304 struct found
305 {
306 BOOST_ASIO_STATIC_CONSTEXPR(bool, value = true);
307 typedef Prop type;
308 typedef typename Prop::polymorphic_query_result_type query_result_type;
309 BOOST_ASIO_STATIC_CONSTEXPR(std::size_t, index = I);
310 };
311
312 struct not_found
313 {
314 BOOST_ASIO_STATIC_CONSTEXPR(bool, value = false);
315 };
316
317 template <typename T>
318 struct find_convertible_property :
319 conditional<
320 is_same<T, Prop>::value || is_convertible<T, Prop>::value,
321 found,
322 not_found
323 >::type {};
324
325 template <typename T>
326 struct find_convertible_requirable_property :
327 conditional<
328 is_requirable<Prop>::value
329 && (is_same<T, Prop>::value || is_convertible<T, Prop>::value),
330 found,
331 not_found
332 >::type {};
333
334 template <typename T>
335 struct find_convertible_preferable_property :
336 conditional<
337 is_preferable<Prop>::value
338 && (is_same<T, Prop>::value || is_convertible<T, Prop>::value),
339 found,
340 not_found
341 >::type {};
342
343 struct find_context_as_property :
344 conditional<
345 is_context_as<Prop>::value,
346 found,
347 not_found
348 >::type {};
349 };
350
351 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
352
353 template <std::size_t I, typename Head, typename... Tail>
354 struct supportable_properties<I, void(Head, Tail...)>
355 {
356 template <typename T>
357 struct is_valid_target : integral_constant<bool,
358 (
359 supportable_properties<I,
360 void(Head)>::template is_valid_target<T>::value
361 &&
362 supportable_properties<I + 1,
363 void(Tail...)>::template is_valid_target<T>::value
364 )
365 >
366 {
367 };
368
369 template <typename T>
370 struct find_convertible_property :
371 conditional<
372 is_convertible<T, Head>::value,
373 typename supportable_properties<I, void(Head)>::found,
374 typename supportable_properties<I + 1,
375 void(Tail...)>::template find_convertible_property<T>
376 >::type {};
377
378 template <typename T>
379 struct find_convertible_requirable_property :
380 conditional<
381 is_requirable<Head>::value
382 && is_convertible<T, Head>::value,
383 typename supportable_properties<I, void(Head)>::found,
384 typename supportable_properties<I + 1,
385 void(Tail...)>::template find_convertible_requirable_property<T>
386 >::type {};
387
388 template <typename T>
389 struct find_convertible_preferable_property :
390 conditional<
391 is_preferable<Head>::value
392 && is_convertible<T, Head>::value,
393 typename supportable_properties<I, void(Head)>::found,
394 typename supportable_properties<I + 1,
395 void(Tail...)>::template find_convertible_preferable_property<T>
396 >::type {};
397
398 struct find_context_as_property :
399 conditional<
400 is_context_as<Head>::value,
401 typename supportable_properties<I, void(Head)>::found,
402 typename supportable_properties<I + 1,
403 void(Tail...)>::find_context_as_property
404 >::type {};
405 };
406
407 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
408
409 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF(n) \
410 template <std::size_t I, \
411 typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
412 struct supportable_properties<I, \
413 void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
414 { \
415 template <typename T> \
416 struct is_valid_target : integral_constant<bool, \
417 ( \
418 supportable_properties<I, \
419 void(Head)>::template is_valid_target<T>::value \
420 && \
421 supportable_properties<I + 1, \
422 void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
423 is_valid_target<T>::value \
424 ) \
425 > \
426 { \
427 }; \
428 \
429 template <typename T> \
430 struct find_convertible_property : \
431 conditional< \
432 is_convertible<T, Head>::value, \
433 typename supportable_properties<I, void(Head)>::found, \
434 typename supportable_properties<I + 1, \
435 void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
436 find_convertible_property<T> \
437 >::type {}; \
438 \
439 template <typename T> \
440 struct find_convertible_requirable_property : \
441 conditional< \
442 is_requirable<Head>::value \
443 && is_convertible<T, Head>::value, \
444 typename supportable_properties<I, void(Head)>::found, \
445 typename supportable_properties<I + 1, \
446 void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
447 find_convertible_requirable_property<T> \
448 >::type {}; \
449 \
450 template <typename T> \
451 struct find_convertible_preferable_property : \
452 conditional< \
453 is_preferable<Head>::value \
454 && is_convertible<T, Head>::value, \
455 typename supportable_properties<I, void(Head)>::found, \
456 typename supportable_properties<I + 1, \
457 void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
458 find_convertible_preferable_property<T> \
459 >::type {}; \
460 \
461 struct find_context_as_property : \
462 conditional< \
463 is_context_as<Head>::value, \
464 typename supportable_properties<I, void(Head)>::found, \
465 typename supportable_properties<I + 1, void( \
466 BOOST_ASIO_VARIADIC_TARGS(n))>::find_context_as_property \
467 >::type {}; \
468 }; \
469 /**/
470 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF)
471 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF
472
473 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
474
475 template <typename T, typename Props>
476 struct is_valid_target_executor :
477 conditional<
478 is_executor<T>::value,
479 typename supportable_properties<0, Props>::template is_valid_target<T>,
480 false_type
481 >::type
482 {
483 };
484
485 class any_executor_base
486 {
487 public:
488 any_executor_base() BOOST_ASIO_NOEXCEPT
489 : object_fns_(object_fns_table<void>()),
490 target_(0),
491 target_fns_(target_fns_table<void>())
492 {
493 }
494
495 template <BOOST_ASIO_EXECUTION_EXECUTOR Executor>
496 any_executor_base(Executor ex, false_type)
497 : target_fns_(target_fns_table<Executor>(
498 any_executor_base::query_blocking(ex,
499 can_query<const Executor&, const execution::blocking_t&>())
500 == execution::blocking.always))
501 {
502 any_executor_base::construct_object(ex,
503 integral_constant<bool,
504 sizeof(Executor) <= sizeof(object_type)
505 && alignment_of<Executor>::value <= alignment_of<object_type>::value
506 >());
507 }
508
509 template <BOOST_ASIO_EXECUTION_EXECUTOR Executor>
510 any_executor_base(Executor other, true_type)
511 : object_fns_(object_fns_table<boost::asio::detail::shared_ptr<void> >()),
512 target_fns_(other.target_fns_)
513 {
514 boost::asio::detail::shared_ptr<Executor> p =
515 boost::asio::detail::make_shared<Executor>(
516 BOOST_ASIO_MOVE_CAST(Executor)(other));
517 target_ = p->template target<void>();
518 new (&object_) boost::asio::detail::shared_ptr<void>(
519 BOOST_ASIO_MOVE_CAST(boost::asio::detail::shared_ptr<Executor>)(p));
520 }
521
522 any_executor_base(const any_executor_base& other) BOOST_ASIO_NOEXCEPT
523 : object_fns_(other.object_fns_),
524 target_fns_(other.target_fns_)
525 {
526 object_fns_->copy(*this, other);
527 }
528
529 ~any_executor_base() BOOST_ASIO_NOEXCEPT
530 {
531 object_fns_->destroy(*this);
532 }
533
534 any_executor_base& operator=(
535 const any_executor_base& other) BOOST_ASIO_NOEXCEPT
536 {
537 if (this != &other)
538 {
539 object_fns_->destroy(*this);
540 object_fns_ = other.object_fns_;
541 target_fns_ = other.target_fns_;
542 object_fns_->copy(*this, other);
543 }
544 return *this;
545 }
546
547 any_executor_base& operator=(nullptr_t) BOOST_ASIO_NOEXCEPT
548 {
549 object_fns_->destroy(*this);
550 target_ = 0;
551 object_fns_ = object_fns_table<void>();
552 target_fns_ = target_fns_table<void>();
553 return *this;
554 }
555
556 #if defined(BOOST_ASIO_HAS_MOVE)
557
558 any_executor_base(any_executor_base&& other) BOOST_ASIO_NOEXCEPT
559 : object_fns_(other.object_fns_),
560 target_fns_(other.target_fns_)
561 {
562 other.object_fns_ = object_fns_table<void>();
563 other.target_fns_ = target_fns_table<void>();
564 object_fns_->move(*this, other);
565 other.target_ = 0;
566 }
567
568 any_executor_base& operator=(
569 any_executor_base&& other) BOOST_ASIO_NOEXCEPT
570 {
571 if (this != &other)
572 {
573 object_fns_->destroy(*this);
574 object_fns_ = other.object_fns_;
575 other.object_fns_ = object_fns_table<void>();
576 target_fns_ = other.target_fns_;
577 other.target_fns_ = target_fns_table<void>();
578 object_fns_->move(*this, other);
579 other.target_ = 0;
580 }
581 return *this;
582 }
583
584 #endif // defined(BOOST_ASIO_HAS_MOVE)
585
586 void swap(any_executor_base& other) BOOST_ASIO_NOEXCEPT
587 {
588 if (this != &other)
589 {
590 any_executor_base tmp(BOOST_ASIO_MOVE_CAST(any_executor_base)(other));
591 other = BOOST_ASIO_MOVE_CAST(any_executor_base)(*this);
592 *this = BOOST_ASIO_MOVE_CAST(any_executor_base)(tmp);
593 }
594 }
595
596 template <typename F>
597 void execute(BOOST_ASIO_MOVE_ARG(F) f) const
598 {
599 if (target_fns_->blocking_execute != 0)
600 {
601 boost::asio::detail::non_const_lvalue<F> f2(f);
602 target_fns_->blocking_execute(*this, function_view(f2.value));
603 }
604 else
605 {
606 target_fns_->execute(*this,
607 function(BOOST_ASIO_MOVE_CAST(F)(f), std::allocator<void>()));
608 }
609 }
610
611 template <typename Executor>
612 Executor* target()
613 {
614 return static_cast<Executor*>(target_);
615 }
616
617 template <typename Executor>
618 const Executor* target() const
619 {
620 return static_cast<Executor*>(target_);
621 }
622
623 #if !defined(BOOST_ASIO_NO_TYPEID)
624 const std::type_info& target_type() const
625 #else // !defined(BOOST_ASIO_NO_TYPEID)
626 const void* target_type() const
627 #endif // !defined(BOOST_ASIO_NO_TYPEID)
628 {
629 return target_fns_->target_type();
630 }
631
632 struct unspecified_bool_type_t {};
633 typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
634 static void unspecified_bool_true(unspecified_bool_type_t) {}
635
636 operator unspecified_bool_type() const BOOST_ASIO_NOEXCEPT
637 {
638 return target_ ? &any_executor_base::unspecified_bool_true : 0;
639 }
640
641 bool operator!() const BOOST_ASIO_NOEXCEPT
642 {
643 return target_ == 0;
644 }
645
646 protected:
647 bool equality_helper(const any_executor_base& other) const BOOST_ASIO_NOEXCEPT
648 {
649 if (target_ == other.target_)
650 return true;
651 if (target_ && !other.target_)
652 return false;
653 if (!target_ && other.target_)
654 return false;
655 if (target_fns_ != other.target_fns_)
656 return false;
657 return target_fns_->equal(*this, other);
658 }
659
660 template <typename Ex>
661 Ex& object()
662 {
663 return *static_cast<Ex*>(static_cast<void*>(&object_));
664 }
665
666 template <typename Ex>
667 const Ex& object() const
668 {
669 return *static_cast<const Ex*>(static_cast<const void*>(&object_));
670 }
671
672 struct object_fns
673 {
674 void (*destroy)(any_executor_base&);
675 void (*copy)(any_executor_base&, const any_executor_base&);
676 void (*move)(any_executor_base&, any_executor_base&);
677 const void* (*target)(const any_executor_base&);
678 };
679
680 static void destroy_void(any_executor_base&)
681 {
682 }
683
684 static void copy_void(any_executor_base& ex1, const any_executor_base&)
685 {
686 ex1.target_ = 0;
687 }
688
689 static void move_void(any_executor_base& ex1, any_executor_base&)
690 {
691 ex1.target_ = 0;
692 }
693
694 static const void* target_void(const any_executor_base&)
695 {
696 return 0;
697 }
698
699 template <typename Obj>
700 static const object_fns* object_fns_table(
701 typename enable_if<
702 is_same<Obj, void>::value
703 >::type* = 0)
704 {
705 static const object_fns fns =
706 {
707 &any_executor_base::destroy_void,
708 &any_executor_base::copy_void,
709 &any_executor_base::move_void,
710 &any_executor_base::target_void
711 };
712 return &fns;
713 }
714
715 static void destroy_shared(any_executor_base& ex)
716 {
717 typedef boost::asio::detail::shared_ptr<void> type;
718 ex.object<type>().~type();
719 }
720
721 static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2)
722 {
723 typedef boost::asio::detail::shared_ptr<void> type;
724 new (&ex1.object_) type(ex2.object<type>());
725 ex1.target_ = ex2.target_;
726 }
727
728 static void move_shared(any_executor_base& ex1, any_executor_base& ex2)
729 {
730 typedef boost::asio::detail::shared_ptr<void> type;
731 new (&ex1.object_) type(BOOST_ASIO_MOVE_CAST(type)(ex2.object<type>()));
732 ex1.target_ = ex2.target_;
733 ex2.object<type>().~type();
734 }
735
736 static const void* target_shared(const any_executor_base& ex)
737 {
738 typedef boost::asio::detail::shared_ptr<void> type;
739 return ex.object<type>().get();
740 }
741
742 template <typename Obj>
743 static const object_fns* object_fns_table(
744 typename enable_if<
745 is_same<Obj, boost::asio::detail::shared_ptr<void> >::value
746 >::type* = 0)
747 {
748 static const object_fns fns =
749 {
750 &any_executor_base::destroy_shared,
751 &any_executor_base::copy_shared,
752 &any_executor_base::move_shared,
753 &any_executor_base::target_shared
754 };
755 return &fns;
756 }
757
758 template <typename Obj>
759 static void destroy_object(any_executor_base& ex)
760 {
761 ex.object<Obj>().~Obj();
762 }
763
764 template <typename Obj>
765 static void copy_object(any_executor_base& ex1, const any_executor_base& ex2)
766 {
767 new (&ex1.object_) Obj(ex2.object<Obj>());
768 ex1.target_ = &ex1.object<Obj>();
769 }
770
771 template <typename Obj>
772 static void move_object(any_executor_base& ex1, any_executor_base& ex2)
773 {
774 new (&ex1.object_) Obj(BOOST_ASIO_MOVE_CAST(Obj)(ex2.object<Obj>()));
775 ex1.target_ = &ex1.object<Obj>();
776 ex2.object<Obj>().~Obj();
777 }
778
779 template <typename Obj>
780 static const void* target_object(const any_executor_base& ex)
781 {
782 return &ex.object<Obj>();
783 }
784
785 template <typename Obj>
786 static const object_fns* object_fns_table(
787 typename enable_if<
788 !is_same<Obj, void>::value
789 && !is_same<Obj, boost::asio::detail::shared_ptr<void> >::value
790 >::type* = 0)
791 {
792 static const object_fns fns =
793 {
794 &any_executor_base::destroy_object<Obj>,
795 &any_executor_base::copy_object<Obj>,
796 &any_executor_base::move_object<Obj>,
797 &any_executor_base::target_object<Obj>
798 };
799 return &fns;
800 }
801
802 typedef boost::asio::detail::executor_function function;
803 typedef boost::asio::detail::executor_function_view function_view;
804
805 struct target_fns
806 {
807 #if !defined(BOOST_ASIO_NO_TYPEID)
808 const std::type_info& (*target_type)();
809 #else // !defined(BOOST_ASIO_NO_TYPEID)
810 const void* (*target_type)();
811 #endif // !defined(BOOST_ASIO_NO_TYPEID)
812 bool (*equal)(const any_executor_base&, const any_executor_base&);
813 void (*execute)(const any_executor_base&, BOOST_ASIO_MOVE_ARG(function));
814 void (*blocking_execute)(const any_executor_base&, function_view);
815 };
816
817 #if !defined(BOOST_ASIO_NO_TYPEID)
818 static const std::type_info& target_type_void()
819 {
820 return typeid(void);
821 }
822 #else // !defined(BOOST_ASIO_NO_TYPEID)
823 static const void* target_type_void()
824 {
825 return 0;
826 }
827 #endif // !defined(BOOST_ASIO_NO_TYPEID)
828
829 static bool equal_void(const any_executor_base&, const any_executor_base&)
830 {
831 return true;
832 }
833
834 static void execute_void(const any_executor_base&,
835 BOOST_ASIO_MOVE_ARG(function))
836 {
837 bad_executor ex;
838 boost::asio::detail::throw_exception(ex);
839 }
840
841 static void blocking_execute_void(const any_executor_base&, function_view)
842 {
843 bad_executor ex;
844 boost::asio::detail::throw_exception(ex);
845 }
846
847 template <typename Ex>
848 static const target_fns* target_fns_table(
849 typename enable_if<
850 is_same<Ex, void>::value
851 >::type* = 0)
852 {
853 static const target_fns fns =
854 {
855 &any_executor_base::target_type_void,
856 &any_executor_base::equal_void,
857 &any_executor_base::execute_void,
858 &any_executor_base::blocking_execute_void
859 };
860 return &fns;
861 }
862
863 #if !defined(BOOST_ASIO_NO_TYPEID)
864 template <typename Ex>
865 static const std::type_info& target_type_ex()
866 {
867 return typeid(Ex);
868 }
869 #else // !defined(BOOST_ASIO_NO_TYPEID)
870 template <typename Ex>
871 static const void* target_type_ex()
872 {
873 static int unique_id;
874 return &unique_id;
875 }
876 #endif // !defined(BOOST_ASIO_NO_TYPEID)
877
878 template <typename Ex>
879 static bool equal_ex(const any_executor_base& ex1,
880 const any_executor_base& ex2)
881 {
882 return *ex1.target<Ex>() == *ex2.target<Ex>();
883 }
884
885 template <typename Ex>
886 static void execute_ex(const any_executor_base& ex,
887 BOOST_ASIO_MOVE_ARG(function) f)
888 {
889 execution::execute(*ex.target<Ex>(), BOOST_ASIO_MOVE_CAST(function)(f));
890 }
891
892 template <typename Ex>
893 static void blocking_execute_ex(const any_executor_base& ex, function_view f)
894 {
895 execution::execute(*ex.target<Ex>(), f);
896 }
897
898 template <typename Ex>
899 static const target_fns* target_fns_table(bool is_always_blocking,
900 typename enable_if<
901 !is_same<Ex, void>::value
902 >::type* = 0)
903 {
904 static const target_fns fns_with_execute =
905 {
906 &any_executor_base::target_type_ex<Ex>,
907 &any_executor_base::equal_ex<Ex>,
908 &any_executor_base::execute_ex<Ex>,
909 0
910 };
911
912 static const target_fns fns_with_blocking_execute =
913 {
914 &any_executor_base::target_type_ex<Ex>,
915 &any_executor_base::equal_ex<Ex>,
916 0,
917 &any_executor_base::blocking_execute_ex<Ex>
918 };
919
920 return is_always_blocking ? &fns_with_blocking_execute : &fns_with_execute;
921 }
922
923 #if defined(BOOST_ASIO_MSVC)
924 # pragma warning (push)
925 # pragma warning (disable:4702)
926 #endif // defined(BOOST_ASIO_MSVC)
927
928 static void query_fn_void(void*, const void*, const void*)
929 {
930 bad_executor ex;
931 boost::asio::detail::throw_exception(ex);
932 }
933
934 template <typename Ex, class Prop>
935 static void query_fn_non_void(void*, const void* ex, const void* prop,
936 typename enable_if<
937 boost::asio::can_query<const Ex&, const Prop&>::value
938 && is_same<typename Prop::polymorphic_query_result_type, void>::value
939 >::type*)
940 {
941 boost::asio::query(*static_cast<const Ex*>(ex),
942 *static_cast<const Prop*>(prop));
943 }
944
945 template <typename Ex, class Prop>
946 static void query_fn_non_void(void*, const void*, const void*,
947 typename enable_if<
948 !boost::asio::can_query<const Ex&, const Prop&>::value
949 && is_same<typename Prop::polymorphic_query_result_type, void>::value
950 >::type*)
951 {
952 }
953
954 template <typename Ex, class Prop>
955 static void query_fn_non_void(void* result, const void* ex, const void* prop,
956 typename enable_if<
957 boost::asio::can_query<const Ex&, const Prop&>::value
958 && !is_same<typename Prop::polymorphic_query_result_type, void>::value
959 && is_reference<typename Prop::polymorphic_query_result_type>::value
960 >::type*)
961 {
962 *static_cast<typename remove_reference<
963 typename Prop::polymorphic_query_result_type>::type**>(result)
964 = &static_cast<typename Prop::polymorphic_query_result_type>(
965 boost::asio::query(*static_cast<const Ex*>(ex),
966 *static_cast<const Prop*>(prop)));
967 }
968
969 template <typename Ex, class Prop>
970 static void query_fn_non_void(void*, const void*, const void*,
971 typename enable_if<
972 !boost::asio::can_query<const Ex&, const Prop&>::value
973 && !is_same<typename Prop::polymorphic_query_result_type, void>::value
974 && is_reference<typename Prop::polymorphic_query_result_type>::value
975 >::type*)
976 {
977 std::terminate(); // Combination should not be possible.
978 }
979
980 template <typename Ex, class Prop>
981 static void query_fn_non_void(void* result, const void* ex, const void* prop,
982 typename enable_if<
983 boost::asio::can_query<const Ex&, const Prop&>::value
984 && !is_same<typename Prop::polymorphic_query_result_type, void>::value
985 && is_scalar<typename Prop::polymorphic_query_result_type>::value
986 >::type*)
987 {
988 *static_cast<typename Prop::polymorphic_query_result_type*>(result)
989 = static_cast<typename Prop::polymorphic_query_result_type>(
990 boost::asio::query(*static_cast<const Ex*>(ex),
991 *static_cast<const Prop*>(prop)));
992 }
993
994 template <typename Ex, class Prop>
995 static void query_fn_non_void(void* result, const void*, const void*,
996 typename enable_if<
997 !boost::asio::can_query<const Ex&, const Prop&>::value
998 && !is_same<typename Prop::polymorphic_query_result_type, void>::value
999 && is_scalar<typename Prop::polymorphic_query_result_type>::value
1000 >::type*)
1001 {
1002 *static_cast<typename Prop::polymorphic_query_result_type*>(result)
1003 = typename Prop::polymorphic_query_result_type();
1004 }
1005
1006 template <typename Ex, class Prop>
1007 static void query_fn_non_void(void* result, const void* ex, const void* prop,
1008 typename enable_if<
1009 boost::asio::can_query<const Ex&, const Prop&>::value
1010 && !is_same<typename Prop::polymorphic_query_result_type, void>::value
1011 && !is_reference<typename Prop::polymorphic_query_result_type>::value
1012 && !is_scalar<typename Prop::polymorphic_query_result_type>::value
1013 >::type*)
1014 {
1015 *static_cast<typename Prop::polymorphic_query_result_type**>(result)
1016 = new typename Prop::polymorphic_query_result_type(
1017 boost::asio::query(*static_cast<const Ex*>(ex),
1018 *static_cast<const Prop*>(prop)));
1019 }
1020
1021 template <typename Ex, class Prop>
1022 static void query_fn_non_void(void* result, const void*, const void*, ...)
1023 {
1024 *static_cast<typename Prop::polymorphic_query_result_type**>(result)
1025 = new typename Prop::polymorphic_query_result_type();
1026 }
1027
1028 template <typename Ex, class Prop>
1029 static void query_fn_impl(void* result, const void* ex, const void* prop,
1030 typename enable_if<
1031 is_same<Ex, void>::value
1032 >::type*)
1033 {
1034 query_fn_void(result, ex, prop);
1035 }
1036
1037 template <typename Ex, class Prop>
1038 static void query_fn_impl(void* result, const void* ex, const void* prop,
1039 typename enable_if<
1040 !is_same<Ex, void>::value
1041 >::type*)
1042 {
1043 query_fn_non_void<Ex, Prop>(result, ex, prop, 0);
1044 }
1045
1046 template <typename Ex, class Prop>
1047 static void query_fn(void* result, const void* ex, const void* prop)
1048 {
1049 query_fn_impl<Ex, Prop>(result, ex, prop, 0);
1050 }
1051
1052 template <typename Poly, typename Ex, class Prop>
1053 static Poly require_fn_impl(const void*, const void*,
1054 typename enable_if<
1055 is_same<Ex, void>::value
1056 >::type*)
1057 {
1058 bad_executor ex;
1059 boost::asio::detail::throw_exception(ex);
1060 return Poly();
1061 }
1062
1063 template <typename Poly, typename Ex, class Prop>
1064 static Poly require_fn_impl(const void* ex, const void* prop,
1065 typename enable_if<
1066 !is_same<Ex, void>::value && Prop::is_requirable
1067 >::type*)
1068 {
1069 return boost::asio::require(*static_cast<const Ex*>(ex),
1070 *static_cast<const Prop*>(prop));
1071 }
1072
1073 template <typename Poly, typename Ex, class Prop>
1074 static Poly require_fn_impl(const void*, const void*, ...)
1075 {
1076 return Poly();
1077 }
1078
1079 template <typename Poly, typename Ex, class Prop>
1080 static Poly require_fn(const void* ex, const void* prop)
1081 {
1082 return require_fn_impl<Poly, Ex, Prop>(ex, prop, 0);
1083 }
1084
1085 template <typename Poly, typename Ex, class Prop>
1086 static Poly prefer_fn_impl(const void*, const void*,
1087 typename enable_if<
1088 is_same<Ex, void>::value
1089 >::type*)
1090 {
1091 bad_executor ex;
1092 boost::asio::detail::throw_exception(ex);
1093 return Poly();
1094 }
1095
1096 template <typename Poly, typename Ex, class Prop>
1097 static Poly prefer_fn_impl(const void* ex, const void* prop,
1098 typename enable_if<
1099 !is_same<Ex, void>::value && Prop::is_preferable
1100 >::type*)
1101 {
1102 return boost::asio::prefer(*static_cast<const Ex*>(ex),
1103 *static_cast<const Prop*>(prop));
1104 }
1105
1106 template <typename Poly, typename Ex, class Prop>
1107 static Poly prefer_fn_impl(const void*, const void*, ...)
1108 {
1109 return Poly();
1110 }
1111
1112 template <typename Poly, typename Ex, class Prop>
1113 static Poly prefer_fn(const void* ex, const void* prop)
1114 {
1115 return prefer_fn_impl<Poly, Ex, Prop>(ex, prop, 0);
1116 }
1117
1118 template <typename Poly>
1119 struct prop_fns
1120 {
1121 void (*query)(void*, const void*, const void*);
1122 Poly (*require)(const void*, const void*);
1123 Poly (*prefer)(const void*, const void*);
1124 };
1125
1126 #if defined(BOOST_ASIO_MSVC)
1127 # pragma warning (pop)
1128 #endif // defined(BOOST_ASIO_MSVC)
1129
1130 private:
1131 template <typename Executor>
1132 static execution::blocking_t query_blocking(const Executor& ex, true_type)
1133 {
1134 return boost::asio::query(ex, execution::blocking);
1135 }
1136
1137 template <typename Executor>
1138 static execution::blocking_t query_blocking(const Executor&, false_type)
1139 {
1140 return execution::blocking_t();
1141 }
1142
1143 template <typename Executor>
1144 void construct_object(Executor& ex, true_type)
1145 {
1146 object_fns_ = object_fns_table<Executor>();
1147 target_ = new (&object_) Executor(BOOST_ASIO_MOVE_CAST(Executor)(ex));
1148 }
1149
1150 template <typename Executor>
1151 void construct_object(Executor& ex, false_type)
1152 {
1153 object_fns_ = object_fns_table<boost::asio::detail::shared_ptr<void> >();
1154 boost::asio::detail::shared_ptr<Executor> p =
1155 boost::asio::detail::make_shared<Executor>(
1156 BOOST_ASIO_MOVE_CAST(Executor)(ex));
1157 target_ = p.get();
1158 new (&object_) boost::asio::detail::shared_ptr<void>(
1159 BOOST_ASIO_MOVE_CAST(boost::asio::detail::shared_ptr<Executor>)(p));
1160 }
1161
1162 /*private:*/public:
1163 // template <typename...> friend class any_executor;
1164
1165 typedef aligned_storage<
1166 sizeof(boost::asio::detail::shared_ptr<void>),
1167 alignment_of<boost::asio::detail::shared_ptr<void> >::value
1168 >::type object_type;
1169
1170 object_type object_;
1171 const object_fns* object_fns_;
1172 void* target_;
1173 const target_fns* target_fns_;
1174 };
1175
1176 template <typename Derived, typename Property, typename = void>
1177 struct any_executor_context
1178 {
1179 };
1180
1181 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
1182
1183 template <typename Derived, typename Property>
1184 struct any_executor_context<Derived, Property,
1185 typename enable_if<Property::value>::type>
1186 {
1187 typename Property::query_result_type context() const
1188 {
1189 return static_cast<const Derived*>(this)->query(typename Property::type());
1190 }
1191 };
1192
1193 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
1194
1195 } // namespace detail
1196
1197 template <>
1198 class any_executor<> : public detail::any_executor_base
1199 {
1200 public:
1201 any_executor() BOOST_ASIO_NOEXCEPT
1202 : detail::any_executor_base()
1203 {
1204 }
1205
1206 any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT
1207 : detail::any_executor_base()
1208 {
1209 }
1210
1211 template <typename Executor>
1212 any_executor(Executor ex,
1213 typename enable_if<
1214 conditional<
1215 !is_same<Executor, any_executor>::value
1216 && !is_base_of<detail::any_executor_base, Executor>::value,
1217 is_executor<Executor>,
1218 false_type
1219 >::type::value
1220 >::type* = 0)
1221 : detail::any_executor_base(
1222 BOOST_ASIO_MOVE_CAST(Executor)(ex), false_type())
1223 {
1224 }
1225
1226 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1227
1228 template <typename... OtherSupportableProperties>
1229 any_executor(any_executor<OtherSupportableProperties...> other)
1230 : detail::any_executor_base(
1231 static_cast<const detail::any_executor_base&>(other))
1232 {
1233 }
1234
1235 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1236
1237 template <typename U0, typename U1, typename U2, typename U3,
1238 typename U4, typename U5, typename U6, typename U7>
1239 any_executor(any_executor<U0, U1, U2, U3, U4, U5, U6, U7> other)
1240 : detail::any_executor_base(
1241 static_cast<const detail::any_executor_base&>(other))
1242 {
1243 }
1244
1245 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1246
1247 any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT
1248 : detail::any_executor_base(
1249 static_cast<const detail::any_executor_base&>(other))
1250 {
1251 }
1252
1253 any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT
1254 {
1255 if (this != &other)
1256 {
1257 detail::any_executor_base::operator=(
1258 static_cast<const detail::any_executor_base&>(other));
1259 }
1260 return *this;
1261 }
1262
1263 any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT
1264 {
1265 detail::any_executor_base::operator=(p);
1266 return *this;
1267 }
1268
1269 #if defined(BOOST_ASIO_HAS_MOVE)
1270
1271 any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT
1272 : detail::any_executor_base(
1273 static_cast<any_executor_base&&>(
1274 static_cast<any_executor_base&>(other)))
1275 {
1276 }
1277
1278 any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT
1279 {
1280 if (this != &other)
1281 {
1282 detail::any_executor_base::operator=(
1283 static_cast<detail::any_executor_base&&>(
1284 static_cast<detail::any_executor_base&>(other)));
1285 }
1286 return *this;
1287 }
1288
1289 #endif // defined(BOOST_ASIO_HAS_MOVE)
1290
1291 void swap(any_executor& other) BOOST_ASIO_NOEXCEPT
1292 {
1293 detail::any_executor_base::swap(
1294 static_cast<detail::any_executor_base&>(other));
1295 }
1296
1297 using detail::any_executor_base::execute;
1298 using detail::any_executor_base::target;
1299 using detail::any_executor_base::target_type;
1300 using detail::any_executor_base::operator unspecified_bool_type;
1301 using detail::any_executor_base::operator!;
1302
1303 bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT
1304 {
1305 return any_executor_base::equality_helper(other);
1306 }
1307
1308 template <typename AnyExecutor1, typename AnyExecutor2>
1309 friend typename enable_if<
1310 is_same<AnyExecutor1, any_executor>::value
1311 || is_same<AnyExecutor2, any_executor>::value,
1312 bool
1313 >::type operator==(const AnyExecutor1& a,
1314 const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT
1315 {
1316 return static_cast<const any_executor&>(a).equality_helper(b);
1317 }
1318
1319 template <typename AnyExecutor>
1320 friend typename enable_if<
1321 is_same<AnyExecutor, any_executor>::value,
1322 bool
1323 >::type operator==(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1324 {
1325 return !a;
1326 }
1327
1328 template <typename AnyExecutor>
1329 friend typename enable_if<
1330 is_same<AnyExecutor, any_executor>::value,
1331 bool
1332 >::type operator==(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT
1333 {
1334 return !b;
1335 }
1336
1337 template <typename AnyExecutor1, typename AnyExecutor2>
1338 friend typename enable_if<
1339 is_same<AnyExecutor1, any_executor>::value
1340 || is_same<AnyExecutor2, any_executor>::value,
1341 bool
1342 >::type operator!=(const AnyExecutor1& a,
1343 const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT
1344 {
1345 return !static_cast<const any_executor&>(a).equality_helper(b);
1346 }
1347
1348 template <typename AnyExecutor>
1349 friend typename enable_if<
1350 is_same<AnyExecutor, any_executor>::value,
1351 bool
1352 >::type operator!=(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1353 {
1354 return !!a;
1355 }
1356
1357 template <typename AnyExecutor>
1358 friend typename enable_if<
1359 is_same<AnyExecutor, any_executor>::value,
1360 bool
1361 >::type operator!=(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT
1362 {
1363 return !!b;
1364 }
1365 };
1366
1367 inline void swap(any_executor<>& a, any_executor<>& b) BOOST_ASIO_NOEXCEPT
1368 {
1369 return a.swap(b);
1370 }
1371
1372 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1373
1374 template <typename... SupportableProperties>
1375 class any_executor :
1376 public detail::any_executor_base,
1377 public detail::any_executor_context<
1378 any_executor<SupportableProperties...>,
1379 typename detail::supportable_properties<
1380 0, void(SupportableProperties...)>::find_context_as_property>
1381 {
1382 public:
1383 any_executor() BOOST_ASIO_NOEXCEPT
1384 : detail::any_executor_base(),
1385 prop_fns_(prop_fns_table<void>())
1386 {
1387 }
1388
1389 any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT
1390 : detail::any_executor_base(),
1391 prop_fns_(prop_fns_table<void>())
1392 {
1393 }
1394
1395 template <typename Executor>
1396 any_executor(Executor ex,
1397 typename enable_if<
1398 conditional<
1399 !is_same<Executor, any_executor>::value
1400 && !is_base_of<detail::any_executor_base, Executor>::value,
1401 detail::is_valid_target_executor<
1402 Executor, void(SupportableProperties...)>,
1403 false_type
1404 >::type::value
1405 >::type* = 0)
1406 : detail::any_executor_base(
1407 BOOST_ASIO_MOVE_CAST(Executor)(ex), false_type()),
1408 prop_fns_(prop_fns_table<Executor>())
1409 {
1410 }
1411
1412 template <typename... OtherSupportableProperties>
1413 any_executor(any_executor<OtherSupportableProperties...> other,
1414 typename enable_if<
1415 conditional<
1416 !is_same<
1417 any_executor<OtherSupportableProperties...>,
1418 any_executor
1419 >::value,
1420 typename detail::supportable_properties<
1421 0, void(SupportableProperties...)>::template is_valid_target<
1422 any_executor<OtherSupportableProperties...> >,
1423 false_type
1424 >::type::value
1425 >::type* = 0)
1426 : detail::any_executor_base(BOOST_ASIO_MOVE_CAST(
1427 any_executor<OtherSupportableProperties...>)(other), true_type()),
1428 prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...> >())
1429 {
1430 }
1431
1432 any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT
1433 : detail::any_executor_base(
1434 static_cast<const detail::any_executor_base&>(other)),
1435 prop_fns_(other.prop_fns_)
1436 {
1437 }
1438
1439 any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT
1440 {
1441 if (this != &other)
1442 {
1443 prop_fns_ = other.prop_fns_;
1444 detail::any_executor_base::operator=(
1445 static_cast<const detail::any_executor_base&>(other));
1446 }
1447 return *this;
1448 }
1449
1450 any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT
1451 {
1452 prop_fns_ = prop_fns_table<void>();
1453 detail::any_executor_base::operator=(p);
1454 return *this;
1455 }
1456
1457 #if defined(BOOST_ASIO_HAS_MOVE)
1458
1459 any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT
1460 : detail::any_executor_base(
1461 static_cast<any_executor_base&&>(
1462 static_cast<any_executor_base&>(other))),
1463 prop_fns_(other.prop_fns_)
1464 {
1465 other.prop_fns_ = prop_fns_table<void>();
1466 }
1467
1468 any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT
1469 {
1470 if (this != &other)
1471 {
1472 prop_fns_ = other.prop_fns_;
1473 detail::any_executor_base::operator=(
1474 static_cast<detail::any_executor_base&&>(
1475 static_cast<detail::any_executor_base&>(other)));
1476 }
1477 return *this;
1478 }
1479
1480 #endif // defined(BOOST_ASIO_HAS_MOVE)
1481
1482 void swap(any_executor& other) BOOST_ASIO_NOEXCEPT
1483 {
1484 if (this != &other)
1485 {
1486 detail::any_executor_base::swap(
1487 static_cast<detail::any_executor_base&>(other));
1488 const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_;
1489 other.prop_fns_ = prop_fns_;
1490 prop_fns_ = tmp_prop_fns;
1491 }
1492 }
1493
1494 using detail::any_executor_base::execute;
1495 using detail::any_executor_base::target;
1496 using detail::any_executor_base::target_type;
1497 using detail::any_executor_base::operator unspecified_bool_type;
1498 using detail::any_executor_base::operator!;
1499
1500 bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT
1501 {
1502 return any_executor_base::equality_helper(other);
1503 }
1504
1505 template <typename AnyExecutor1, typename AnyExecutor2>
1506 friend typename enable_if<
1507 is_same<AnyExecutor1, any_executor>::value
1508 || is_same<AnyExecutor2, any_executor>::value,
1509 bool
1510 >::type operator==(const AnyExecutor1& a,
1511 const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT
1512 {
1513 return static_cast<const any_executor&>(a).equality_helper(b);
1514 }
1515
1516 template <typename AnyExecutor>
1517 friend typename enable_if<
1518 is_same<AnyExecutor, any_executor>::value,
1519 bool
1520 >::type operator==(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1521 {
1522 return !a;
1523 }
1524
1525 template <typename AnyExecutor>
1526 friend typename enable_if<
1527 is_same<AnyExecutor, any_executor>::value,
1528 bool
1529 >::type operator==(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT
1530 {
1531 return !b;
1532 }
1533
1534 template <typename AnyExecutor1, typename AnyExecutor2>
1535 friend typename enable_if<
1536 is_same<AnyExecutor1, any_executor>::value
1537 || is_same<AnyExecutor2, any_executor>::value,
1538 bool
1539 >::type operator!=(const AnyExecutor1& a,
1540 const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT
1541 {
1542 return !static_cast<const any_executor&>(a).equality_helper(b);
1543 }
1544
1545 template <typename AnyExecutor>
1546 friend typename enable_if<
1547 is_same<AnyExecutor, any_executor>::value,
1548 bool
1549 >::type operator!=(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1550 {
1551 return !!a;
1552 }
1553
1554 template <typename AnyExecutor>
1555 friend typename enable_if<
1556 is_same<AnyExecutor, any_executor>::value,
1557 bool
1558 >::type operator!=(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT
1559 {
1560 return !!b;
1561 }
1562
1563 template <typename T>
1564 struct find_convertible_property :
1565 detail::supportable_properties<
1566 0, void(SupportableProperties...)>::template
1567 find_convertible_property<T> {};
1568
1569 template <typename Property>
1570 void query(const Property& p,
1571 typename enable_if<
1572 is_same<
1573 typename find_convertible_property<Property>::query_result_type,
1574 void
1575 >::value
1576 >::type* = 0) const
1577 {
1578 typedef find_convertible_property<Property> found;
1579 prop_fns_[found::index].query(0, object_fns_->target(*this),
1580 &static_cast<const typename found::type&>(p));
1581 }
1582
1583 template <typename Property>
1584 typename find_convertible_property<Property>::query_result_type
1585 query(const Property& p,
1586 typename enable_if<
1587 !is_same<
1588 typename find_convertible_property<Property>::query_result_type,
1589 void
1590 >::value
1591 &&
1592 is_reference<
1593 typename find_convertible_property<Property>::query_result_type
1594 >::value
1595 >::type* = 0) const
1596 {
1597 typedef find_convertible_property<Property> found;
1598 typename remove_reference<
1599 typename found::query_result_type>::type* result = 0;
1600 prop_fns_[found::index].query(&result, object_fns_->target(*this),
1601 &static_cast<const typename found::type&>(p));
1602 return *result;
1603 }
1604
1605 template <typename Property>
1606 typename find_convertible_property<Property>::query_result_type
1607 query(const Property& p,
1608 typename enable_if<
1609 !is_same<
1610 typename find_convertible_property<Property>::query_result_type,
1611 void
1612 >::value
1613 &&
1614 is_scalar<
1615 typename find_convertible_property<Property>::query_result_type
1616 >::value
1617 >::type* = 0) const
1618 {
1619 typedef find_convertible_property<Property> found;
1620 typename found::query_result_type result;
1621 prop_fns_[found::index].query(&result, object_fns_->target(*this),
1622 &static_cast<const typename found::type&>(p));
1623 return result;
1624 }
1625
1626 template <typename Property>
1627 typename find_convertible_property<Property>::query_result_type
1628 query(const Property& p,
1629 typename enable_if<
1630 !is_same<
1631 typename find_convertible_property<Property>::query_result_type,
1632 void
1633 >::value
1634 &&
1635 !is_reference<
1636 typename find_convertible_property<Property>::query_result_type
1637 >::value
1638 &&
1639 !is_scalar<
1640 typename find_convertible_property<Property>::query_result_type
1641 >::value
1642 >::type* = 0) const
1643 {
1644 typedef find_convertible_property<Property> found;
1645 typename found::query_result_type* result;
1646 prop_fns_[found::index].query(&result, object_fns_->target(*this),
1647 &static_cast<const typename found::type&>(p));
1648 return *boost::asio::detail::scoped_ptr<
1649 typename found::query_result_type>(result);
1650 }
1651
1652 template <typename T>
1653 struct find_convertible_requirable_property :
1654 detail::supportable_properties<
1655 0, void(SupportableProperties...)>::template
1656 find_convertible_requirable_property<T> {};
1657
1658 template <typename Property>
1659 any_executor require(const Property& p,
1660 typename enable_if<
1661 find_convertible_requirable_property<Property>::value
1662 >::type* = 0) const
1663 {
1664 typedef find_convertible_requirable_property<Property> found;
1665 return prop_fns_[found::index].require(object_fns_->target(*this),
1666 &static_cast<const typename found::type&>(p));
1667 }
1668
1669 template <typename T>
1670 struct find_convertible_preferable_property :
1671 detail::supportable_properties<
1672 0, void(SupportableProperties...)>::template
1673 find_convertible_preferable_property<T> {};
1674
1675 template <typename Property>
1676 any_executor prefer(const Property& p,
1677 typename enable_if<
1678 find_convertible_preferable_property<Property>::value
1679 >::type* = 0) const
1680 {
1681 typedef find_convertible_preferable_property<Property> found;
1682 return prop_fns_[found::index].prefer(object_fns_->target(*this),
1683 &static_cast<const typename found::type&>(p));
1684 }
1685
1686 //private:
1687 template <typename Ex>
1688 static const prop_fns<any_executor>* prop_fns_table()
1689 {
1690 static const prop_fns<any_executor> fns[] =
1691 {
1692 {
1693 &detail::any_executor_base::query_fn<
1694 Ex, SupportableProperties>,
1695 &detail::any_executor_base::require_fn<
1696 any_executor, Ex, SupportableProperties>,
1697 &detail::any_executor_base::prefer_fn<
1698 any_executor, Ex, SupportableProperties>
1699 }...
1700 };
1701 return fns;
1702 }
1703
1704 const prop_fns<any_executor>* prop_fns_;
1705 };
1706
1707 template <typename... SupportableProperties>
1708 inline void swap(any_executor<SupportableProperties...>& a,
1709 any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT
1710 {
1711 return a.swap(b);
1712 }
1713
1714 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1715
1716 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \
1717 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_##n
1718
1719 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 \
1720 { \
1721 &detail::any_executor_base::query_fn<Ex, T1>, \
1722 &detail::any_executor_base::require_fn<any_executor, Ex, T1>, \
1723 &detail::any_executor_base::prefer_fn<any_executor, Ex, T1> \
1724 }
1725 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 \
1726 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1, \
1727 { \
1728 &detail::any_executor_base::query_fn<Ex, T2>, \
1729 &detail::any_executor_base::require_fn<any_executor, Ex, T2>, \
1730 &detail::any_executor_base::prefer_fn<any_executor, Ex, T2> \
1731 }
1732 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 \
1733 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2, \
1734 { \
1735 &detail::any_executor_base::query_fn<Ex, T3>, \
1736 &detail::any_executor_base::require_fn<any_executor, Ex, T3>, \
1737 &detail::any_executor_base::prefer_fn<any_executor, Ex, T3> \
1738 }
1739 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 \
1740 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3, \
1741 { \
1742 &detail::any_executor_base::query_fn<Ex, T4>, \
1743 &detail::any_executor_base::require_fn<any_executor, Ex, T4>, \
1744 &detail::any_executor_base::prefer_fn<any_executor, Ex, T4> \
1745 }
1746 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 \
1747 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4, \
1748 { \
1749 &detail::any_executor_base::query_fn<Ex, T5>, \
1750 &detail::any_executor_base::require_fn<any_executor, Ex, T5>, \
1751 &detail::any_executor_base::prefer_fn<any_executor, Ex, T5> \
1752 }
1753 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 \
1754 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5, \
1755 { \
1756 &detail::any_executor_base::query_fn<Ex, T6>, \
1757 &detail::any_executor_base::require_fn<any_executor, Ex, T6>, \
1758 &detail::any_executor_base::prefer_fn<any_executor, Ex, T6> \
1759 }
1760 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 \
1761 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6, \
1762 { \
1763 &detail::any_executor_base::query_fn<Ex, T7>, \
1764 &detail::any_executor_base::require_fn<any_executor, Ex, T7>, \
1765 &detail::any_executor_base::prefer_fn<any_executor, Ex, T7> \
1766 }
1767 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 \
1768 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7, \
1769 { \
1770 &detail::any_executor_base::query_fn<Ex, T8>, \
1771 &detail::any_executor_base::require_fn<any_executor, Ex, T8>, \
1772 &detail::any_executor_base::prefer_fn<any_executor, Ex, T8> \
1773 }
1774
1775 #if defined(BOOST_ASIO_HAS_MOVE)
1776
1777 # define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \
1778 any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT \
1779 : detail::any_executor_base( \
1780 static_cast<any_executor_base&&>( \
1781 static_cast<any_executor_base&>(other))), \
1782 prop_fns_(other.prop_fns_) \
1783 { \
1784 other.prop_fns_ = prop_fns_table<void>(); \
1785 } \
1786 \
1787 any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT \
1788 { \
1789 if (this != &other) \
1790 { \
1791 prop_fns_ = other.prop_fns_; \
1792 detail::any_executor_base::operator=( \
1793 static_cast<detail::any_executor_base&&>( \
1794 static_cast<detail::any_executor_base&>(other))); \
1795 } \
1796 return *this; \
1797 } \
1798 /**/
1799 #else // defined(BOOST_ASIO_HAS_MOVE)
1800
1801 # define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS
1802
1803 #endif // defined(BOOST_ASIO_HAS_MOVE)
1804
1805 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF(n) \
1806 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
1807 class any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> : \
1808 public detail::any_executor_base, \
1809 public detail::any_executor_context< \
1810 any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, \
1811 typename detail::supportable_properties< \
1812 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::find_context_as_property> \
1813 { \
1814 public: \
1815 any_executor() BOOST_ASIO_NOEXCEPT \
1816 : detail::any_executor_base(), \
1817 prop_fns_(prop_fns_table<void>()) \
1818 { \
1819 } \
1820 \
1821 any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT \
1822 : detail::any_executor_base(), \
1823 prop_fns_(prop_fns_table<void>()) \
1824 { \
1825 } \
1826 \
1827 template <BOOST_ASIO_EXECUTION_EXECUTOR Executor> \
1828 any_executor(Executor ex, \
1829 typename enable_if< \
1830 conditional< \
1831 !is_same<Executor, any_executor>::value \
1832 && !is_base_of<detail::any_executor_base, Executor>::value, \
1833 detail::is_valid_target_executor< \
1834 Executor, void(BOOST_ASIO_VARIADIC_TARGS(n))>, \
1835 false_type \
1836 >::type::value \
1837 >::type* = 0) \
1838 : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \
1839 Executor)(ex), false_type()), \
1840 prop_fns_(prop_fns_table<Executor>()) \
1841 { \
1842 } \
1843 \
1844 any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT \
1845 : detail::any_executor_base( \
1846 static_cast<const detail::any_executor_base&>(other)), \
1847 prop_fns_(other.prop_fns_) \
1848 { \
1849 } \
1850 \
1851 any_executor(any_executor<> other) \
1852 : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \
1853 any_executor<>)(other), true_type()), \
1854 prop_fns_(prop_fns_table<any_executor<> >()) \
1855 { \
1856 } \
1857 \
1858 template <typename OtherAnyExecutor> \
1859 any_executor(OtherAnyExecutor other, \
1860 typename enable_if< \
1861 conditional< \
1862 !is_same<OtherAnyExecutor, any_executor>::value \
1863 && is_base_of<detail::any_executor_base, \
1864 OtherAnyExecutor>::value, \
1865 typename detail::supportable_properties< \
1866 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
1867 is_valid_target<OtherAnyExecutor>, \
1868 false_type \
1869 >::type::value \
1870 >::type* = 0) \
1871 : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \
1872 OtherAnyExecutor)(other), true_type()), \
1873 prop_fns_(prop_fns_table<OtherAnyExecutor>()) \
1874 { \
1875 } \
1876 \
1877 any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT \
1878 { \
1879 if (this != &other) \
1880 { \
1881 prop_fns_ = other.prop_fns_; \
1882 detail::any_executor_base::operator=( \
1883 static_cast<const detail::any_executor_base&>(other)); \
1884 } \
1885 return *this; \
1886 } \
1887 \
1888 any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT \
1889 { \
1890 prop_fns_ = prop_fns_table<void>(); \
1891 detail::any_executor_base::operator=(p); \
1892 return *this; \
1893 } \
1894 \
1895 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \
1896 \
1897 void swap(any_executor& other) BOOST_ASIO_NOEXCEPT \
1898 { \
1899 if (this != &other) \
1900 { \
1901 detail::any_executor_base::swap( \
1902 static_cast<detail::any_executor_base&>(other)); \
1903 const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_; \
1904 other.prop_fns_ = prop_fns_; \
1905 prop_fns_ = tmp_prop_fns; \
1906 } \
1907 } \
1908 \
1909 using detail::any_executor_base::execute; \
1910 using detail::any_executor_base::target; \
1911 using detail::any_executor_base::target_type; \
1912 using detail::any_executor_base::operator unspecified_bool_type; \
1913 using detail::any_executor_base::operator!; \
1914 \
1915 bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT \
1916 { \
1917 return any_executor_base::equality_helper(other); \
1918 } \
1919 \
1920 template <typename AnyExecutor1, typename AnyExecutor2> \
1921 friend typename enable_if< \
1922 is_same<AnyExecutor1, any_executor>::value \
1923 || is_same<AnyExecutor2, any_executor>::value, \
1924 bool \
1925 >::type operator==(const AnyExecutor1& a, \
1926 const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT \
1927 { \
1928 return static_cast<const any_executor&>(a).equality_helper(b); \
1929 } \
1930 \
1931 template <typename AnyExecutor> \
1932 friend typename enable_if< \
1933 is_same<AnyExecutor, any_executor>::value, \
1934 bool \
1935 >::type operator==(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT \
1936 { \
1937 return !a; \
1938 } \
1939 \
1940 template <typename AnyExecutor> \
1941 friend typename enable_if< \
1942 is_same<AnyExecutor, any_executor>::value, \
1943 bool \
1944 >::type operator==(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT \
1945 { \
1946 return !b; \
1947 } \
1948 \
1949 template <typename AnyExecutor1, typename AnyExecutor2> \
1950 friend typename enable_if< \
1951 is_same<AnyExecutor1, any_executor>::value \
1952 || is_same<AnyExecutor2, any_executor>::value, \
1953 bool \
1954 >::type operator!=(const AnyExecutor1& a, \
1955 const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT \
1956 { \
1957 return !static_cast<const any_executor&>(a).equality_helper(b); \
1958 } \
1959 \
1960 template <typename AnyExecutor> \
1961 friend typename enable_if< \
1962 is_same<AnyExecutor, any_executor>::value, \
1963 bool \
1964 >::type operator!=(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT \
1965 { \
1966 return !!a; \
1967 } \
1968 \
1969 template <typename AnyExecutor> \
1970 friend typename enable_if< \
1971 is_same<AnyExecutor, any_executor>::value, \
1972 bool \
1973 >::type operator!=(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT \
1974 { \
1975 return !!b; \
1976 } \
1977 \
1978 template <typename T> \
1979 struct find_convertible_property : \
1980 detail::supportable_properties< \
1981 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
1982 find_convertible_property<T> {}; \
1983 \
1984 template <typename Property> \
1985 void query(const Property& p, \
1986 typename enable_if< \
1987 is_same< \
1988 typename find_convertible_property<Property>::query_result_type, \
1989 void \
1990 >::value \
1991 >::type* = 0) const \
1992 { \
1993 typedef find_convertible_property<Property> found; \
1994 prop_fns_[found::index].query(0, object_fns_->target(*this), \
1995 &static_cast<const typename found::type&>(p)); \
1996 } \
1997 \
1998 template <typename Property> \
1999 typename find_convertible_property<Property>::query_result_type \
2000 query(const Property& p, \
2001 typename enable_if< \
2002 !is_same< \
2003 typename find_convertible_property<Property>::query_result_type, \
2004 void \
2005 >::value \
2006 && \
2007 is_reference< \
2008 typename find_convertible_property<Property>::query_result_type \
2009 >::value \
2010 >::type* = 0) const \
2011 { \
2012 typedef find_convertible_property<Property> found; \
2013 typename remove_reference< \
2014 typename found::query_result_type>::type* result; \
2015 prop_fns_[found::index].query(&result, object_fns_->target(*this), \
2016 &static_cast<const typename found::type&>(p)); \
2017 return *result; \
2018 } \
2019 \
2020 template <typename Property> \
2021 typename find_convertible_property<Property>::query_result_type \
2022 query(const Property& p, \
2023 typename enable_if< \
2024 !is_same< \
2025 typename find_convertible_property<Property>::query_result_type, \
2026 void \
2027 >::value \
2028 && \
2029 is_scalar< \
2030 typename find_convertible_property<Property>::query_result_type \
2031 >::value \
2032 >::type* = 0) const \
2033 { \
2034 typedef find_convertible_property<Property> found; \
2035 typename found::query_result_type result; \
2036 prop_fns_[found::index].query(&result, object_fns_->target(*this), \
2037 &static_cast<const typename found::type&>(p)); \
2038 return result; \
2039 } \
2040 \
2041 template <typename Property> \
2042 typename find_convertible_property<Property>::query_result_type \
2043 query(const Property& p, \
2044 typename enable_if< \
2045 !is_same< \
2046 typename find_convertible_property<Property>::query_result_type, \
2047 void \
2048 >::value \
2049 && \
2050 !is_reference< \
2051 typename find_convertible_property<Property>::query_result_type \
2052 >::value \
2053 && \
2054 !is_scalar< \
2055 typename find_convertible_property<Property>::query_result_type \
2056 >::value \
2057 >::type* = 0) const \
2058 { \
2059 typedef find_convertible_property<Property> found; \
2060 typename found::query_result_type* result; \
2061 prop_fns_[found::index].query(&result, object_fns_->target(*this), \
2062 &static_cast<const typename found::type&>(p)); \
2063 return *boost::asio::detail::scoped_ptr< \
2064 typename found::query_result_type>(result); \
2065 } \
2066 \
2067 template <typename T> \
2068 struct find_convertible_requirable_property : \
2069 detail::supportable_properties< \
2070 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2071 find_convertible_requirable_property<T> {}; \
2072 \
2073 template <typename Property> \
2074 any_executor require(const Property& p, \
2075 typename enable_if< \
2076 find_convertible_requirable_property<Property>::value \
2077 >::type* = 0) const \
2078 { \
2079 typedef find_convertible_requirable_property<Property> found; \
2080 return prop_fns_[found::index].require(object_fns_->target(*this), \
2081 &static_cast<const typename found::type&>(p)); \
2082 } \
2083 \
2084 template <typename T> \
2085 struct find_convertible_preferable_property : \
2086 detail::supportable_properties< \
2087 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2088 find_convertible_preferable_property<T> {}; \
2089 \
2090 template <typename Property> \
2091 any_executor prefer(const Property& p, \
2092 typename enable_if< \
2093 find_convertible_preferable_property<Property>::value \
2094 >::type* = 0) const \
2095 { \
2096 typedef find_convertible_preferable_property<Property> found; \
2097 return prop_fns_[found::index].prefer(object_fns_->target(*this), \
2098 &static_cast<const typename found::type&>(p)); \
2099 } \
2100 \
2101 template <typename Ex> \
2102 static const prop_fns<any_executor>* prop_fns_table() \
2103 { \
2104 static const prop_fns<any_executor> fns[] = \
2105 { \
2106 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \
2107 }; \
2108 return fns; \
2109 } \
2110 \
2111 const prop_fns<any_executor>* prop_fns_; \
2112 typedef detail::supportable_properties<0, \
2113 void(BOOST_ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \
2114 }; \
2115 \
2116 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2117 inline void swap(any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \
2118 any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \
2119 { \
2120 return a.swap(b); \
2121 } \
2122 /**/
2123 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF)
2124 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF
2125 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS
2126 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS
2127 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1
2128 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2
2129 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3
2130 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4
2131 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5
2132 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6
2133 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7
2134 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8
2135
2136 #endif // if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2137
2138 } // namespace execution
2139 namespace traits {
2140
2141 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
2142 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2143
2144 template <typename... SupportableProperties>
2145 struct equality_comparable<execution::any_executor<SupportableProperties...> >
2146 {
2147 static const bool is_valid = true;
2148 static const bool is_noexcept = true;
2149 };
2150
2151 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2152
2153 template <>
2154 struct equality_comparable<execution::any_executor<> >
2155 {
2156 static const bool is_valid = true;
2157 static const bool is_noexcept = true;
2158 };
2159
2160 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF(n) \
2161 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2162 struct equality_comparable< \
2163 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> > \
2164 { \
2165 static const bool is_valid = true; \
2166 static const bool is_noexcept = true; \
2167 }; \
2168 /**/
2169 BOOST_ASIO_VARIADIC_GENERATE(
2170 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF)
2171 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF
2172
2173 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2174 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
2175
2176 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
2177 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2178
2179 template <typename F, typename... SupportableProperties>
2180 struct execute_member<execution::any_executor<SupportableProperties...>, F>
2181 {
2182 static const bool is_valid = true;
2183 static const bool is_noexcept = false;
2184 typedef void result_type;
2185 };
2186
2187 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2188
2189 template <typename F>
2190 struct execute_member<execution::any_executor<>, F>
2191 {
2192 static const bool is_valid = true;
2193 static const bool is_noexcept = false;
2194 typedef void result_type;
2195 };
2196
2197 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF(n) \
2198 template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2199 struct execute_member< \
2200 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, F> \
2201 { \
2202 static const bool is_valid = true; \
2203 static const bool is_noexcept = false; \
2204 typedef void result_type; \
2205 }; \
2206 /**/
2207 BOOST_ASIO_VARIADIC_GENERATE(
2208 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF)
2209 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF
2210
2211 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2212 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
2213
2214 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
2215 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2216
2217 template <typename Prop, typename... SupportableProperties>
2218 struct query_member<
2219 execution::any_executor<SupportableProperties...>, Prop,
2220 typename enable_if<
2221 execution::detail::supportable_properties<
2222 0, void(SupportableProperties...)>::template
2223 find_convertible_property<Prop>::value
2224 >::type>
2225 {
2226 static const bool is_valid = true;
2227 static const bool is_noexcept = false;
2228 typedef typename execution::detail::supportable_properties<
2229 0, void(SupportableProperties...)>::template
2230 find_convertible_property<Prop>::query_result_type result_type;
2231 };
2232
2233 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2234
2235 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF(n) \
2236 template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2237 struct query_member< \
2238 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \
2239 typename enable_if< \
2240 execution::detail::supportable_properties< \
2241 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2242 find_convertible_property<Prop>::value \
2243 >::type> \
2244 { \
2245 static const bool is_valid = true; \
2246 static const bool is_noexcept = false; \
2247 typedef typename execution::detail::supportable_properties< \
2248 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2249 find_convertible_property<Prop>::query_result_type result_type; \
2250 }; \
2251 /**/
2252 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF)
2253 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF
2254
2255 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2256 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
2257
2258 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
2259 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2260
2261 template <typename Prop, typename... SupportableProperties>
2262 struct require_member<
2263 execution::any_executor<SupportableProperties...>, Prop,
2264 typename enable_if<
2265 execution::detail::supportable_properties<
2266 0, void(SupportableProperties...)>::template
2267 find_convertible_requirable_property<Prop>::value
2268 >::type>
2269 {
2270 static const bool is_valid = true;
2271 static const bool is_noexcept = false;
2272 typedef execution::any_executor<SupportableProperties...> result_type;
2273 };
2274
2275 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2276
2277 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF(n) \
2278 template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2279 struct require_member< \
2280 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \
2281 typename enable_if< \
2282 execution::detail::supportable_properties< \
2283 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2284 find_convertible_requirable_property<Prop>::value \
2285 >::type> \
2286 { \
2287 static const bool is_valid = true; \
2288 static const bool is_noexcept = false; \
2289 typedef execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> result_type; \
2290 }; \
2291 /**/
2292 BOOST_ASIO_VARIADIC_GENERATE(
2293 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF)
2294 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF
2295
2296 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2297 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
2298
2299 #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
2300 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2301
2302 template <typename Prop, typename... SupportableProperties>
2303 struct prefer_member<
2304 execution::any_executor<SupportableProperties...>, Prop,
2305 typename enable_if<
2306 execution::detail::supportable_properties<
2307 0, void(SupportableProperties...)>::template
2308 find_convertible_preferable_property<Prop>::value
2309 >::type>
2310 {
2311 static const bool is_valid = true;
2312 static const bool is_noexcept = false;
2313 typedef execution::any_executor<SupportableProperties...> result_type;
2314 };
2315
2316 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2317
2318 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF(n) \
2319 template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2320 struct prefer_member< \
2321 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \
2322 typename enable_if< \
2323 execution::detail::supportable_properties< \
2324 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2325 find_convertible_preferable_property<Prop>::value \
2326 >::type> \
2327 { \
2328 static const bool is_valid = true; \
2329 static const bool is_noexcept = false; \
2330 typedef execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> result_type; \
2331 }; \
2332 /**/
2333 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF)
2334 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF
2335
2336 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2337 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
2338
2339 } // namespace traits
2340
2341 #endif // defined(GENERATING_DOCUMENTATION)
2342
2343 } // namespace asio
2344 } // namespace boost
2345
2346 #include <boost/asio/detail/pop_options.hpp>
2347
2348 #endif // BOOST_ASIO_EXECUTION_ANY_EXECUTOR_HPP