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 const std::type_info& target_type() const 624 { 625 return target_fns_->target_type(); 626 } 627 628 struct unspecified_bool_type_t {}; 629 typedef void (*unspecified_bool_type)(unspecified_bool_type_t); 630 static void unspecified_bool_true(unspecified_bool_type_t) {} 631 632 operator unspecified_bool_type() const BOOST_ASIO_NOEXCEPT 633 { 634 return target_ ? &any_executor_base::unspecified_bool_true : 0; 635 } 636 637 bool operator!() const BOOST_ASIO_NOEXCEPT 638 { 639 return target_ == 0; 640 } 641 642 protected: 643 bool equality_helper(const any_executor_base& other) const BOOST_ASIO_NOEXCEPT 644 { 645 if (target_ == other.target_) 646 return true; 647 if (target_ && !other.target_) 648 return false; 649 if (!target_ && other.target_) 650 return false; 651 if (target_fns_ != other.target_fns_) 652 return false; 653 return target_fns_->equal(*this, other); 654 } 655 656 template <typename Ex> 657 Ex& object() 658 { 659 return *static_cast<Ex*>(static_cast<void*>(&object_)); 660 } 661 662 template <typename Ex> 663 const Ex& object() const 664 { 665 return *static_cast<const Ex*>(static_cast<const void*>(&object_)); 666 } 667 668 struct object_fns 669 { 670 void (*destroy)(any_executor_base&); 671 void (*copy)(any_executor_base&, const any_executor_base&); 672 void (*move)(any_executor_base&, any_executor_base&); 673 const void* (*target)(const any_executor_base&); 674 }; 675 676 static void destroy_void(any_executor_base&) 677 { 678 } 679 680 static void copy_void(any_executor_base& ex1, const any_executor_base&) 681 { 682 ex1.target_ = 0; 683 } 684 685 static void move_void(any_executor_base& ex1, any_executor_base&) 686 { 687 ex1.target_ = 0; 688 } 689 690 static const void* target_void(const any_executor_base&) 691 { 692 return 0; 693 } 694 695 template <typename Obj> 696 static const object_fns* object_fns_table( 697 typename enable_if< 698 is_same<Obj, void>::value 699 >::type* = 0) 700 { 701 static const object_fns fns = 702 { 703 &any_executor_base::destroy_void, 704 &any_executor_base::copy_void, 705 &any_executor_base::move_void, 706 &any_executor_base::target_void 707 }; 708 return &fns; 709 } 710 711 static void destroy_shared(any_executor_base& ex) 712 { 713 typedef boost::asio::detail::shared_ptr<void> type; 714 ex.object<type>().~type(); 715 } 716 717 static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2) 718 { 719 typedef boost::asio::detail::shared_ptr<void> type; 720 new (&ex1.object_) type(ex2.object<type>()); 721 ex1.target_ = ex2.target_; 722 } 723 724 static void move_shared(any_executor_base& ex1, any_executor_base& ex2) 725 { 726 typedef boost::asio::detail::shared_ptr<void> type; 727 new (&ex1.object_) type(BOOST_ASIO_MOVE_CAST(type)(ex2.object<type>())); 728 ex1.target_ = ex2.target_; 729 ex2.object<type>().~type(); 730 } 731 732 static const void* target_shared(const any_executor_base& ex) 733 { 734 typedef boost::asio::detail::shared_ptr<void> type; 735 return ex.object<type>().get(); 736 } 737 738 template <typename Obj> 739 static const object_fns* object_fns_table( 740 typename enable_if< 741 is_same<Obj, boost::asio::detail::shared_ptr<void> >::value 742 >::type* = 0) 743 { 744 static const object_fns fns = 745 { 746 &any_executor_base::destroy_shared, 747 &any_executor_base::copy_shared, 748 &any_executor_base::move_shared, 749 &any_executor_base::target_shared 750 }; 751 return &fns; 752 } 753 754 template <typename Obj> 755 static void destroy_object(any_executor_base& ex) 756 { 757 ex.object<Obj>().~Obj(); 758 } 759 760 template <typename Obj> 761 static void copy_object(any_executor_base& ex1, const any_executor_base& ex2) 762 { 763 new (&ex1.object_) Obj(ex2.object<Obj>()); 764 ex1.target_ = &ex1.object<Obj>(); 765 } 766 767 template <typename Obj> 768 static void move_object(any_executor_base& ex1, any_executor_base& ex2) 769 { 770 new (&ex1.object_) Obj(BOOST_ASIO_MOVE_CAST(Obj)(ex2.object<Obj>())); 771 ex1.target_ = &ex1.object<Obj>(); 772 ex2.object<Obj>().~Obj(); 773 } 774 775 template <typename Obj> 776 static const void* target_object(const any_executor_base& ex) 777 { 778 return &ex.object<Obj>(); 779 } 780 781 template <typename Obj> 782 static const object_fns* object_fns_table( 783 typename enable_if< 784 !is_same<Obj, void>::value 785 && !is_same<Obj, boost::asio::detail::shared_ptr<void> >::value 786 >::type* = 0) 787 { 788 static const object_fns fns = 789 { 790 &any_executor_base::destroy_object<Obj>, 791 &any_executor_base::copy_object<Obj>, 792 &any_executor_base::move_object<Obj>, 793 &any_executor_base::target_object<Obj> 794 }; 795 return &fns; 796 } 797 798 typedef boost::asio::detail::executor_function function; 799 typedef boost::asio::detail::executor_function_view function_view; 800 801 struct target_fns 802 { 803 const std::type_info& (*target_type)(); 804 bool (*equal)(const any_executor_base&, const any_executor_base&); 805 void (*execute)(const any_executor_base&, BOOST_ASIO_MOVE_ARG(function)); 806 void (*blocking_execute)(const any_executor_base&, function_view); 807 }; 808 809 static const std::type_info& target_type_void() 810 { 811 return typeid(void); 812 } 813 814 static bool equal_void(const any_executor_base&, const any_executor_base&) 815 { 816 return true; 817 } 818 819 static void execute_void(const any_executor_base&, 820 BOOST_ASIO_MOVE_ARG(function)) 821 { 822 bad_executor ex; 823 boost::asio::detail::throw_exception(ex); 824 } 825 826 static void blocking_execute_void(const any_executor_base&, function_view) 827 { 828 bad_executor ex; 829 boost::asio::detail::throw_exception(ex); 830 } 831 832 template <typename Ex> 833 static const target_fns* target_fns_table( 834 typename enable_if< 835 is_same<Ex, void>::value 836 >::type* = 0) 837 { 838 static const target_fns fns = 839 { 840 &any_executor_base::target_type_void, 841 &any_executor_base::equal_void, 842 &any_executor_base::execute_void, 843 &any_executor_base::blocking_execute_void 844 }; 845 return &fns; 846 } 847 848 template <typename Ex> 849 static const std::type_info& target_type_ex() 850 { 851 return typeid(Ex); 852 } 853 854 template <typename Ex> 855 static bool equal_ex(const any_executor_base& ex1, 856 const any_executor_base& ex2) 857 { 858 return *ex1.target<Ex>() == *ex2.target<Ex>(); 859 } 860 861 template <typename Ex> 862 static void execute_ex(const any_executor_base& ex, 863 BOOST_ASIO_MOVE_ARG(function) f) 864 { 865 execution::execute(*ex.target<Ex>(), BOOST_ASIO_MOVE_CAST(function)(f)); 866 } 867 868 template <typename Ex> 869 static void blocking_execute_ex(const any_executor_base& ex, function_view f) 870 { 871 execution::execute(*ex.target<Ex>(), f); 872 } 873 874 template <typename Ex> 875 static const target_fns* target_fns_table(bool is_always_blocking, 876 typename enable_if< 877 !is_same<Ex, void>::value 878 >::type* = 0) 879 { 880 static const target_fns fns_with_execute = 881 { 882 &any_executor_base::target_type_ex<Ex>, 883 &any_executor_base::equal_ex<Ex>, 884 &any_executor_base::execute_ex<Ex>, 885 0 886 }; 887 888 static const target_fns fns_with_blocking_execute = 889 { 890 &any_executor_base::target_type_ex<Ex>, 891 &any_executor_base::equal_ex<Ex>, 892 0, 893 &any_executor_base::blocking_execute_ex<Ex> 894 }; 895 896 return is_always_blocking ? &fns_with_blocking_execute : &fns_with_execute; 897 } 898 899 #if defined(BOOST_ASIO_MSVC) 900 # pragma warning (push) 901 # pragma warning (disable:4702) 902 #endif // defined(BOOST_ASIO_MSVC) 903 904 static void query_fn_void(void*, const void*, const void*) 905 { 906 bad_executor ex; 907 boost::asio::detail::throw_exception(ex); 908 } 909 910 template <typename Ex, class Prop> 911 static void query_fn_non_void(void*, const void* ex, const void* prop, 912 typename enable_if< 913 boost::asio::can_query<const Ex&, const Prop&>::value 914 && is_same<typename Prop::polymorphic_query_result_type, void>::value 915 >::type*) 916 { 917 boost::asio::query(*static_cast<const Ex*>(ex), 918 *static_cast<const Prop*>(prop)); 919 } 920 921 template <typename Ex, class Prop> 922 static void query_fn_non_void(void*, const void*, const void*, 923 typename enable_if< 924 !boost::asio::can_query<const Ex&, const Prop&>::value 925 && is_same<typename Prop::polymorphic_query_result_type, void>::value 926 >::type*) 927 { 928 } 929 930 template <typename Ex, class Prop> 931 static void query_fn_non_void(void* result, const void* ex, const void* prop, 932 typename enable_if< 933 boost::asio::can_query<const Ex&, const Prop&>::value 934 && !is_same<typename Prop::polymorphic_query_result_type, void>::value 935 && is_reference<typename Prop::polymorphic_query_result_type>::value 936 >::type*) 937 { 938 *static_cast<typename remove_reference< 939 typename Prop::polymorphic_query_result_type>::type**>(result) 940 = &static_cast<typename Prop::polymorphic_query_result_type>( 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 && is_reference<typename Prop::polymorphic_query_result_type>::value 951 >::type*) 952 { 953 std::terminate(); // Combination should not be possible. 954 } 955 956 template <typename Ex, class Prop> 957 static void query_fn_non_void(void* result, const void* ex, const void* prop, 958 typename enable_if< 959 boost::asio::can_query<const Ex&, const Prop&>::value 960 && !is_same<typename Prop::polymorphic_query_result_type, void>::value 961 && is_scalar<typename Prop::polymorphic_query_result_type>::value 962 >::type*) 963 { 964 *static_cast<typename Prop::polymorphic_query_result_type*>(result) 965 = static_cast<typename Prop::polymorphic_query_result_type>( 966 boost::asio::query(*static_cast<const Ex*>(ex), 967 *static_cast<const Prop*>(prop))); 968 } 969 970 template <typename Ex, class Prop> 971 static void query_fn_non_void(void* result, const void*, const void*, 972 typename enable_if< 973 !boost::asio::can_query<const Ex&, const Prop&>::value 974 && !is_same<typename Prop::polymorphic_query_result_type, void>::value 975 && is_scalar<typename Prop::polymorphic_query_result_type>::value 976 >::type*) 977 { 978 *static_cast<typename Prop::polymorphic_query_result_type*>(result) 979 = typename Prop::polymorphic_query_result_type(); 980 } 981 982 template <typename Ex, class Prop> 983 static void query_fn_non_void(void* result, const void* ex, const void* prop, 984 typename enable_if< 985 boost::asio::can_query<const Ex&, const Prop&>::value 986 && !is_same<typename Prop::polymorphic_query_result_type, void>::value 987 && !is_reference<typename Prop::polymorphic_query_result_type>::value 988 && !is_scalar<typename Prop::polymorphic_query_result_type>::value 989 >::type*) 990 { 991 *static_cast<typename Prop::polymorphic_query_result_type**>(result) 992 = new typename Prop::polymorphic_query_result_type( 993 boost::asio::query(*static_cast<const Ex*>(ex), 994 *static_cast<const Prop*>(prop))); 995 } 996 997 template <typename Ex, class Prop> 998 static void query_fn_non_void(void* result, const void*, const void*, ...) 999 { 1000 *static_cast<typename Prop::polymorphic_query_result_type**>(result) 1001 = new typename Prop::polymorphic_query_result_type(); 1002 } 1003 1004 template <typename Ex, class Prop> 1005 static void query_fn_impl(void* result, const void* ex, const void* prop, 1006 typename enable_if< 1007 is_same<Ex, void>::value 1008 >::type*) 1009 { 1010 query_fn_void(result, ex, prop); 1011 } 1012 1013 template <typename Ex, class Prop> 1014 static void query_fn_impl(void* result, const void* ex, const void* prop, 1015 typename enable_if< 1016 !is_same<Ex, void>::value 1017 >::type*) 1018 { 1019 query_fn_non_void<Ex, Prop>(result, ex, prop, 0); 1020 } 1021 1022 template <typename Ex, class Prop> 1023 static void query_fn(void* result, const void* ex, const void* prop) 1024 { 1025 query_fn_impl<Ex, Prop>(result, ex, prop, 0); 1026 } 1027 1028 template <typename Poly, typename Ex, class Prop> 1029 static Poly require_fn_impl(const void*, const void*, 1030 typename enable_if< 1031 is_same<Ex, void>::value 1032 >::type*) 1033 { 1034 bad_executor ex; 1035 boost::asio::detail::throw_exception(ex); 1036 return Poly(); 1037 } 1038 1039 template <typename Poly, typename Ex, class Prop> 1040 static Poly require_fn_impl(const void* ex, const void* prop, 1041 typename enable_if< 1042 !is_same<Ex, void>::value && Prop::is_requirable 1043 >::type*) 1044 { 1045 return boost::asio::require(*static_cast<const Ex*>(ex), 1046 *static_cast<const Prop*>(prop)); 1047 } 1048 1049 template <typename Poly, typename Ex, class Prop> 1050 static Poly require_fn_impl(const void*, const void*, ...) 1051 { 1052 return Poly(); 1053 } 1054 1055 template <typename Poly, typename Ex, class Prop> 1056 static Poly require_fn(const void* ex, const void* prop) 1057 { 1058 return require_fn_impl<Poly, Ex, Prop>(ex, prop, 0); 1059 } 1060 1061 template <typename Poly, typename Ex, class Prop> 1062 static Poly prefer_fn_impl(const void*, const void*, 1063 typename enable_if< 1064 is_same<Ex, void>::value 1065 >::type*) 1066 { 1067 bad_executor ex; 1068 boost::asio::detail::throw_exception(ex); 1069 return Poly(); 1070 } 1071 1072 template <typename Poly, typename Ex, class Prop> 1073 static Poly prefer_fn_impl(const void* ex, const void* prop, 1074 typename enable_if< 1075 !is_same<Ex, void>::value && Prop::is_preferable 1076 >::type*) 1077 { 1078 return boost::asio::prefer(*static_cast<const Ex*>(ex), 1079 *static_cast<const Prop*>(prop)); 1080 } 1081 1082 template <typename Poly, typename Ex, class Prop> 1083 static Poly prefer_fn_impl(const void*, const void*, ...) 1084 { 1085 return Poly(); 1086 } 1087 1088 template <typename Poly, typename Ex, class Prop> 1089 static Poly prefer_fn(const void* ex, const void* prop) 1090 { 1091 return prefer_fn_impl<Poly, Ex, Prop>(ex, prop, 0); 1092 } 1093 1094 template <typename Poly> 1095 struct prop_fns 1096 { 1097 void (*query)(void*, const void*, const void*); 1098 Poly (*require)(const void*, const void*); 1099 Poly (*prefer)(const void*, const void*); 1100 }; 1101 1102 #if defined(BOOST_ASIO_MSVC) 1103 # pragma warning (pop) 1104 #endif // defined(BOOST_ASIO_MSVC) 1105 1106 private: 1107 template <typename Executor> 1108 static execution::blocking_t query_blocking(const Executor& ex, true_type) 1109 { 1110 return boost::asio::query(ex, execution::blocking); 1111 } 1112 1113 template <typename Executor> 1114 static execution::blocking_t query_blocking(const Executor&, false_type) 1115 { 1116 return execution::blocking_t(); 1117 } 1118 1119 template <typename Executor> 1120 void construct_object(Executor& ex, true_type) 1121 { 1122 object_fns_ = object_fns_table<Executor>(); 1123 target_ = new (&object_) Executor(BOOST_ASIO_MOVE_CAST(Executor)(ex)); 1124 } 1125 1126 template <typename Executor> 1127 void construct_object(Executor& ex, false_type) 1128 { 1129 object_fns_ = object_fns_table<boost::asio::detail::shared_ptr<void> >(); 1130 boost::asio::detail::shared_ptr<Executor> p = 1131 boost::asio::detail::make_shared<Executor>( 1132 BOOST_ASIO_MOVE_CAST(Executor)(ex)); 1133 target_ = p.get(); 1134 new (&object_) boost::asio::detail::shared_ptr<void>( 1135 BOOST_ASIO_MOVE_CAST(boost::asio::detail::shared_ptr<Executor>)(p)); 1136 } 1137 1138 /*private:*/public: 1139 // template <typename...> friend class any_executor; 1140 1141 typedef aligned_storage< 1142 sizeof(boost::asio::detail::shared_ptr<void>), 1143 alignment_of<boost::asio::detail::shared_ptr<void> >::value 1144 >::type object_type; 1145 1146 object_type object_; 1147 const object_fns* object_fns_; 1148 void* target_; 1149 const target_fns* target_fns_; 1150 }; 1151 1152 template <typename Derived, typename Property, typename = void> 1153 struct any_executor_context 1154 { 1155 }; 1156 1157 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS) 1158 1159 template <typename Derived, typename Property> 1160 struct any_executor_context<Derived, Property, 1161 typename enable_if<Property::value>::type> 1162 { 1163 typename Property::query_result_type context() const 1164 { 1165 return static_cast<const Derived*>(this)->query(typename Property::type()); 1166 } 1167 }; 1168 1169 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) 1170 1171 } // namespace detail 1172 1173 template <> 1174 class any_executor<> : public detail::any_executor_base 1175 { 1176 public: 1177 any_executor() BOOST_ASIO_NOEXCEPT 1178 : detail::any_executor_base() 1179 { 1180 } 1181 1182 any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT 1183 : detail::any_executor_base() 1184 { 1185 } 1186 1187 template <typename Executor> 1188 any_executor(Executor ex, 1189 typename enable_if< 1190 conditional< 1191 !is_same<Executor, any_executor>::value 1192 && !is_base_of<detail::any_executor_base, Executor>::value, 1193 is_executor<Executor>, 1194 false_type 1195 >::type::value 1196 >::type* = 0) 1197 : detail::any_executor_base( 1198 BOOST_ASIO_MOVE_CAST(Executor)(ex), false_type()) 1199 { 1200 } 1201 1202 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 1203 1204 template <typename... OtherSupportableProperties> 1205 any_executor(any_executor<OtherSupportableProperties...> other) 1206 : detail::any_executor_base( 1207 static_cast<const detail::any_executor_base&>(other)) 1208 { 1209 } 1210 1211 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 1212 1213 template <typename U0, typename U1, typename U2, typename U3, 1214 typename U4, typename U5, typename U6, typename U7> 1215 any_executor(any_executor<U0, U1, U2, U3, U4, U5, U6, U7> other) 1216 : detail::any_executor_base( 1217 static_cast<const detail::any_executor_base&>(other)) 1218 { 1219 } 1220 1221 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 1222 1223 any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT 1224 : detail::any_executor_base( 1225 static_cast<const detail::any_executor_base&>(other)) 1226 { 1227 } 1228 1229 any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT 1230 { 1231 if (this != &other) 1232 { 1233 detail::any_executor_base::operator=( 1234 static_cast<const detail::any_executor_base&>(other)); 1235 } 1236 return *this; 1237 } 1238 1239 any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT 1240 { 1241 detail::any_executor_base::operator=(p); 1242 return *this; 1243 } 1244 1245 #if defined(BOOST_ASIO_HAS_MOVE) 1246 1247 any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT 1248 : detail::any_executor_base( 1249 static_cast<any_executor_base&&>( 1250 static_cast<any_executor_base&>(other))) 1251 { 1252 } 1253 1254 any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT 1255 { 1256 if (this != &other) 1257 { 1258 detail::any_executor_base::operator=( 1259 static_cast<detail::any_executor_base&&>( 1260 static_cast<detail::any_executor_base&>(other))); 1261 } 1262 return *this; 1263 } 1264 1265 #endif // defined(BOOST_ASIO_HAS_MOVE) 1266 1267 void swap(any_executor& other) BOOST_ASIO_NOEXCEPT 1268 { 1269 detail::any_executor_base::swap( 1270 static_cast<detail::any_executor_base&>(other)); 1271 } 1272 1273 using detail::any_executor_base::execute; 1274 using detail::any_executor_base::target; 1275 using detail::any_executor_base::target_type; 1276 using detail::any_executor_base::operator unspecified_bool_type; 1277 using detail::any_executor_base::operator!; 1278 1279 bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT 1280 { 1281 return any_executor_base::equality_helper(other); 1282 } 1283 }; 1284 1285 inline bool operator==(const any_executor<>& a, 1286 const any_executor<>& b) BOOST_ASIO_NOEXCEPT 1287 { 1288 return a.equality_helper(b); 1289 } 1290 1291 inline bool operator==(const any_executor<>& a, nullptr_t) BOOST_ASIO_NOEXCEPT 1292 { 1293 return !a; 1294 } 1295 1296 inline bool operator==(nullptr_t, const any_executor<>& b) BOOST_ASIO_NOEXCEPT 1297 { 1298 return !b; 1299 } 1300 1301 inline bool operator!=(const any_executor<>& a, 1302 const any_executor<>& b) BOOST_ASIO_NOEXCEPT 1303 { 1304 return !a.equality_helper(b); 1305 } 1306 1307 inline bool operator!=(const any_executor<>& a, nullptr_t) BOOST_ASIO_NOEXCEPT 1308 { 1309 return !!a; 1310 } 1311 1312 inline bool operator!=(nullptr_t, const any_executor<>& b) BOOST_ASIO_NOEXCEPT 1313 { 1314 return !!b; 1315 } 1316 1317 inline void swap(any_executor<>& a, any_executor<>& b) BOOST_ASIO_NOEXCEPT 1318 { 1319 return a.swap(b); 1320 } 1321 1322 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 1323 1324 template <typename... SupportableProperties> 1325 class any_executor : 1326 public detail::any_executor_base, 1327 public detail::any_executor_context< 1328 any_executor<SupportableProperties...>, 1329 typename detail::supportable_properties< 1330 0, void(SupportableProperties...)>::find_context_as_property> 1331 { 1332 public: 1333 any_executor() BOOST_ASIO_NOEXCEPT 1334 : detail::any_executor_base(), 1335 prop_fns_(prop_fns_table<void>()) 1336 { 1337 } 1338 1339 any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT 1340 : detail::any_executor_base(), 1341 prop_fns_(prop_fns_table<void>()) 1342 { 1343 } 1344 1345 template <typename Executor> 1346 any_executor(Executor ex, 1347 typename enable_if< 1348 conditional< 1349 !is_same<Executor, any_executor>::value 1350 && !is_base_of<detail::any_executor_base, Executor>::value, 1351 detail::is_valid_target_executor< 1352 Executor, void(SupportableProperties...)>, 1353 false_type 1354 >::type::value 1355 >::type* = 0) 1356 : detail::any_executor_base( 1357 BOOST_ASIO_MOVE_CAST(Executor)(ex), false_type()), 1358 prop_fns_(prop_fns_table<Executor>()) 1359 { 1360 } 1361 1362 template <typename... OtherSupportableProperties> 1363 any_executor(any_executor<OtherSupportableProperties...> other, 1364 typename enable_if< 1365 conditional< 1366 !is_same< 1367 any_executor<OtherSupportableProperties...>, 1368 any_executor 1369 >::value, 1370 typename detail::supportable_properties< 1371 0, void(SupportableProperties...)>::template is_valid_target< 1372 any_executor<OtherSupportableProperties...> >, 1373 false_type 1374 >::type::value 1375 >::type* = 0) 1376 : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( 1377 any_executor<OtherSupportableProperties...>)(other), true_type()), 1378 prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...> >()) 1379 { 1380 } 1381 1382 any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT 1383 : detail::any_executor_base( 1384 static_cast<const detail::any_executor_base&>(other)), 1385 prop_fns_(other.prop_fns_) 1386 { 1387 } 1388 1389 any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT 1390 { 1391 if (this != &other) 1392 { 1393 prop_fns_ = other.prop_fns_; 1394 detail::any_executor_base::operator=( 1395 static_cast<const detail::any_executor_base&>(other)); 1396 } 1397 return *this; 1398 } 1399 1400 any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT 1401 { 1402 prop_fns_ = prop_fns_table<void>(); 1403 detail::any_executor_base::operator=(p); 1404 return *this; 1405 } 1406 1407 #if defined(BOOST_ASIO_HAS_MOVE) 1408 1409 any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT 1410 : detail::any_executor_base( 1411 static_cast<any_executor_base&&>( 1412 static_cast<any_executor_base&>(other))), 1413 prop_fns_(other.prop_fns_) 1414 { 1415 other.prop_fns_ = prop_fns_table<void>(); 1416 } 1417 1418 any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT 1419 { 1420 if (this != &other) 1421 { 1422 prop_fns_ = other.prop_fns_; 1423 detail::any_executor_base::operator=( 1424 static_cast<detail::any_executor_base&&>( 1425 static_cast<detail::any_executor_base&>(other))); 1426 } 1427 return *this; 1428 } 1429 1430 #endif // defined(BOOST_ASIO_HAS_MOVE) 1431 1432 void swap(any_executor& other) BOOST_ASIO_NOEXCEPT 1433 { 1434 if (this != &other) 1435 { 1436 detail::any_executor_base::swap( 1437 static_cast<detail::any_executor_base&>(other)); 1438 const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_; 1439 other.prop_fns_ = prop_fns_; 1440 prop_fns_ = tmp_prop_fns; 1441 } 1442 } 1443 1444 using detail::any_executor_base::execute; 1445 using detail::any_executor_base::target; 1446 using detail::any_executor_base::target_type; 1447 using detail::any_executor_base::operator unspecified_bool_type; 1448 using detail::any_executor_base::operator!; 1449 1450 bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT 1451 { 1452 return any_executor_base::equality_helper(other); 1453 } 1454 1455 template <typename T> 1456 struct find_convertible_property : 1457 detail::supportable_properties< 1458 0, void(SupportableProperties...)>::template 1459 find_convertible_property<T> {}; 1460 1461 template <typename Property> 1462 void query(const Property& p, 1463 typename enable_if< 1464 is_same< 1465 typename find_convertible_property<Property>::query_result_type, 1466 void 1467 >::value 1468 >::type* = 0) const 1469 { 1470 typedef find_convertible_property<Property> found; 1471 prop_fns_[found::index].query(0, object_fns_->target(*this), 1472 &static_cast<const typename found::type&>(p)); 1473 } 1474 1475 template <typename Property> 1476 typename find_convertible_property<Property>::query_result_type 1477 query(const Property& p, 1478 typename enable_if< 1479 !is_same< 1480 typename find_convertible_property<Property>::query_result_type, 1481 void 1482 >::value 1483 && 1484 is_reference< 1485 typename find_convertible_property<Property>::query_result_type 1486 >::value 1487 >::type* = 0) const 1488 { 1489 typedef find_convertible_property<Property> found; 1490 typename remove_reference< 1491 typename found::query_result_type>::type* result = 0; 1492 prop_fns_[found::index].query(&result, object_fns_->target(*this), 1493 &static_cast<const typename found::type&>(p)); 1494 return *result; 1495 } 1496 1497 template <typename Property> 1498 typename find_convertible_property<Property>::query_result_type 1499 query(const Property& p, 1500 typename enable_if< 1501 !is_same< 1502 typename find_convertible_property<Property>::query_result_type, 1503 void 1504 >::value 1505 && 1506 is_scalar< 1507 typename find_convertible_property<Property>::query_result_type 1508 >::value 1509 >::type* = 0) const 1510 { 1511 typedef find_convertible_property<Property> found; 1512 typename found::query_result_type result; 1513 prop_fns_[found::index].query(&result, object_fns_->target(*this), 1514 &static_cast<const typename found::type&>(p)); 1515 return result; 1516 } 1517 1518 template <typename Property> 1519 typename find_convertible_property<Property>::query_result_type 1520 query(const Property& p, 1521 typename enable_if< 1522 !is_same< 1523 typename find_convertible_property<Property>::query_result_type, 1524 void 1525 >::value 1526 && 1527 !is_reference< 1528 typename find_convertible_property<Property>::query_result_type 1529 >::value 1530 && 1531 !is_scalar< 1532 typename find_convertible_property<Property>::query_result_type 1533 >::value 1534 >::type* = 0) const 1535 { 1536 typedef find_convertible_property<Property> found; 1537 typename found::query_result_type* result; 1538 prop_fns_[found::index].query(&result, object_fns_->target(*this), 1539 &static_cast<const typename found::type&>(p)); 1540 return *boost::asio::detail::scoped_ptr< 1541 typename found::query_result_type>(result); 1542 } 1543 1544 template <typename T> 1545 struct find_convertible_requirable_property : 1546 detail::supportable_properties< 1547 0, void(SupportableProperties...)>::template 1548 find_convertible_requirable_property<T> {}; 1549 1550 template <typename Property> 1551 any_executor require(const Property& p, 1552 typename enable_if< 1553 find_convertible_requirable_property<Property>::value 1554 >::type* = 0) const 1555 { 1556 typedef find_convertible_requirable_property<Property> found; 1557 return prop_fns_[found::index].require(object_fns_->target(*this), 1558 &static_cast<const typename found::type&>(p)); 1559 } 1560 1561 template <typename T> 1562 struct find_convertible_preferable_property : 1563 detail::supportable_properties< 1564 0, void(SupportableProperties...)>::template 1565 find_convertible_preferable_property<T> {}; 1566 1567 template <typename Property> 1568 any_executor prefer(const Property& p, 1569 typename enable_if< 1570 find_convertible_preferable_property<Property>::value 1571 >::type* = 0) const 1572 { 1573 typedef find_convertible_preferable_property<Property> found; 1574 return prop_fns_[found::index].prefer(object_fns_->target(*this), 1575 &static_cast<const typename found::type&>(p)); 1576 } 1577 1578 //private: 1579 template <typename Ex> 1580 static const prop_fns<any_executor>* prop_fns_table() 1581 { 1582 static const prop_fns<any_executor> fns[] = 1583 { 1584 { 1585 &detail::any_executor_base::query_fn< 1586 Ex, SupportableProperties>, 1587 &detail::any_executor_base::require_fn< 1588 any_executor, Ex, SupportableProperties>, 1589 &detail::any_executor_base::prefer_fn< 1590 any_executor, Ex, SupportableProperties> 1591 }... 1592 }; 1593 return fns; 1594 } 1595 1596 const prop_fns<any_executor>* prop_fns_; 1597 }; 1598 1599 template <typename... SupportableProperties> 1600 inline bool operator==(const any_executor<SupportableProperties...>& a, 1601 const any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT 1602 { 1603 return a.equality_helper(b); 1604 } 1605 1606 template <typename... SupportableProperties> 1607 inline bool operator==(const any_executor<SupportableProperties...>& a, 1608 nullptr_t) BOOST_ASIO_NOEXCEPT 1609 { 1610 return !a; 1611 } 1612 1613 template <typename... SupportableProperties> 1614 inline bool operator==(nullptr_t, 1615 const any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT 1616 { 1617 return !b; 1618 } 1619 1620 template <typename... SupportableProperties> 1621 inline bool operator!=(const any_executor<SupportableProperties...>& a, 1622 const any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT 1623 { 1624 return !a.equality_helper(b); 1625 } 1626 1627 template <typename... SupportableProperties> 1628 inline bool operator!=(const any_executor<SupportableProperties...>& a, 1629 nullptr_t) BOOST_ASIO_NOEXCEPT 1630 { 1631 return !!a; 1632 } 1633 1634 template <typename... SupportableProperties> 1635 inline bool operator!=(nullptr_t, 1636 const any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT 1637 { 1638 return !!b; 1639 } 1640 1641 template <typename... SupportableProperties> 1642 inline void swap(any_executor<SupportableProperties...>& a, 1643 any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT 1644 { 1645 return a.swap(b); 1646 } 1647 1648 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 1649 1650 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \ 1651 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_##n 1652 1653 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 \ 1654 { \ 1655 &detail::any_executor_base::query_fn<Ex, T1>, \ 1656 &detail::any_executor_base::require_fn<any_executor, Ex, T1>, \ 1657 &detail::any_executor_base::prefer_fn<any_executor, Ex, T1> \ 1658 } 1659 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 \ 1660 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1, \ 1661 { \ 1662 &detail::any_executor_base::query_fn<Ex, T2>, \ 1663 &detail::any_executor_base::require_fn<any_executor, Ex, T2>, \ 1664 &detail::any_executor_base::prefer_fn<any_executor, Ex, T2> \ 1665 } 1666 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 \ 1667 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2, \ 1668 { \ 1669 &detail::any_executor_base::query_fn<Ex, T3>, \ 1670 &detail::any_executor_base::require_fn<any_executor, Ex, T3>, \ 1671 &detail::any_executor_base::prefer_fn<any_executor, Ex, T3> \ 1672 } 1673 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 \ 1674 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3, \ 1675 { \ 1676 &detail::any_executor_base::query_fn<Ex, T4>, \ 1677 &detail::any_executor_base::require_fn<any_executor, Ex, T4>, \ 1678 &detail::any_executor_base::prefer_fn<any_executor, Ex, T4> \ 1679 } 1680 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 \ 1681 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4, \ 1682 { \ 1683 &detail::any_executor_base::query_fn<Ex, T5>, \ 1684 &detail::any_executor_base::require_fn<any_executor, Ex, T5>, \ 1685 &detail::any_executor_base::prefer_fn<any_executor, Ex, T5> \ 1686 } 1687 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 \ 1688 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5, \ 1689 { \ 1690 &detail::any_executor_base::query_fn<Ex, T6>, \ 1691 &detail::any_executor_base::require_fn<any_executor, Ex, T6>, \ 1692 &detail::any_executor_base::prefer_fn<any_executor, Ex, T6> \ 1693 } 1694 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 \ 1695 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6, \ 1696 { \ 1697 &detail::any_executor_base::query_fn<Ex, T7>, \ 1698 &detail::any_executor_base::require_fn<any_executor, Ex, T7>, \ 1699 &detail::any_executor_base::prefer_fn<any_executor, Ex, T7> \ 1700 } 1701 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 \ 1702 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7, \ 1703 { \ 1704 &detail::any_executor_base::query_fn<Ex, T8>, \ 1705 &detail::any_executor_base::require_fn<any_executor, Ex, T8>, \ 1706 &detail::any_executor_base::prefer_fn<any_executor, Ex, T8> \ 1707 } 1708 1709 #if defined(BOOST_ASIO_HAS_MOVE) 1710 1711 # define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \ 1712 any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT \ 1713 : detail::any_executor_base( \ 1714 static_cast<any_executor_base&&>( \ 1715 static_cast<any_executor_base&>(other))), \ 1716 prop_fns_(other.prop_fns_) \ 1717 { \ 1718 other.prop_fns_ = prop_fns_table<void>(); \ 1719 } \ 1720 \ 1721 any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT \ 1722 { \ 1723 if (this != &other) \ 1724 { \ 1725 prop_fns_ = other.prop_fns_; \ 1726 detail::any_executor_base::operator=( \ 1727 static_cast<detail::any_executor_base&&>( \ 1728 static_cast<detail::any_executor_base&>(other))); \ 1729 } \ 1730 return *this; \ 1731 } \ 1732 /**/ 1733 #else // defined(BOOST_ASIO_HAS_MOVE) 1734 1735 # define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS 1736 1737 #endif // defined(BOOST_ASIO_HAS_MOVE) 1738 1739 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF(n) \ 1740 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 1741 class any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> : \ 1742 public detail::any_executor_base, \ 1743 public detail::any_executor_context< \ 1744 any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, \ 1745 typename detail::supportable_properties< \ 1746 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::find_context_as_property> \ 1747 { \ 1748 public: \ 1749 any_executor() BOOST_ASIO_NOEXCEPT \ 1750 : detail::any_executor_base(), \ 1751 prop_fns_(prop_fns_table<void>()) \ 1752 { \ 1753 } \ 1754 \ 1755 any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT \ 1756 : detail::any_executor_base(), \ 1757 prop_fns_(prop_fns_table<void>()) \ 1758 { \ 1759 } \ 1760 \ 1761 template <BOOST_ASIO_EXECUTION_EXECUTOR Executor> \ 1762 any_executor(Executor ex, \ 1763 typename enable_if< \ 1764 conditional< \ 1765 !is_same<Executor, any_executor>::value \ 1766 && !is_base_of<detail::any_executor_base, Executor>::value, \ 1767 detail::is_valid_target_executor< \ 1768 Executor, void(BOOST_ASIO_VARIADIC_TARGS(n))>, \ 1769 false_type \ 1770 >::type::value \ 1771 >::type* = 0) \ 1772 : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \ 1773 Executor)(ex), false_type()), \ 1774 prop_fns_(prop_fns_table<Executor>()) \ 1775 { \ 1776 } \ 1777 \ 1778 any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT \ 1779 : detail::any_executor_base( \ 1780 static_cast<const detail::any_executor_base&>(other)), \ 1781 prop_fns_(other.prop_fns_) \ 1782 { \ 1783 } \ 1784 \ 1785 any_executor(any_executor<> other) \ 1786 : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \ 1787 any_executor<>)(other), true_type()), \ 1788 prop_fns_(prop_fns_table<any_executor<> >()) \ 1789 { \ 1790 } \ 1791 \ 1792 template <typename OtherAnyExecutor> \ 1793 any_executor(OtherAnyExecutor other, \ 1794 typename enable_if< \ 1795 conditional< \ 1796 !is_same<OtherAnyExecutor, any_executor>::value \ 1797 && is_base_of<detail::any_executor_base, \ 1798 OtherAnyExecutor>::value, \ 1799 typename detail::supportable_properties< \ 1800 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \ 1801 is_valid_target<OtherAnyExecutor>, \ 1802 false_type \ 1803 >::type::value \ 1804 >::type* = 0) \ 1805 : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \ 1806 OtherAnyExecutor)(other), true_type()), \ 1807 prop_fns_(prop_fns_table<OtherAnyExecutor>()) \ 1808 { \ 1809 } \ 1810 \ 1811 any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT \ 1812 { \ 1813 if (this != &other) \ 1814 { \ 1815 prop_fns_ = other.prop_fns_; \ 1816 detail::any_executor_base::operator=( \ 1817 static_cast<const detail::any_executor_base&>(other)); \ 1818 } \ 1819 return *this; \ 1820 } \ 1821 \ 1822 any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT \ 1823 { \ 1824 prop_fns_ = prop_fns_table<void>(); \ 1825 detail::any_executor_base::operator=(p); \ 1826 return *this; \ 1827 } \ 1828 \ 1829 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \ 1830 \ 1831 void swap(any_executor& other) BOOST_ASIO_NOEXCEPT \ 1832 { \ 1833 if (this != &other) \ 1834 { \ 1835 detail::any_executor_base::swap( \ 1836 static_cast<detail::any_executor_base&>(other)); \ 1837 const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_; \ 1838 other.prop_fns_ = prop_fns_; \ 1839 prop_fns_ = tmp_prop_fns; \ 1840 } \ 1841 } \ 1842 \ 1843 using detail::any_executor_base::execute; \ 1844 using detail::any_executor_base::target; \ 1845 using detail::any_executor_base::target_type; \ 1846 using detail::any_executor_base::operator unspecified_bool_type; \ 1847 using detail::any_executor_base::operator!; \ 1848 \ 1849 bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT \ 1850 { \ 1851 return any_executor_base::equality_helper(other); \ 1852 } \ 1853 \ 1854 template <typename T> \ 1855 struct find_convertible_property : \ 1856 detail::supportable_properties< \ 1857 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \ 1858 find_convertible_property<T> {}; \ 1859 \ 1860 template <typename Property> \ 1861 void query(const Property& p, \ 1862 typename enable_if< \ 1863 is_same< \ 1864 typename find_convertible_property<Property>::query_result_type, \ 1865 void \ 1866 >::value \ 1867 >::type* = 0) const \ 1868 { \ 1869 typedef find_convertible_property<Property> found; \ 1870 prop_fns_[found::index].query(0, object_fns_->target(*this), \ 1871 &static_cast<const typename found::type&>(p)); \ 1872 } \ 1873 \ 1874 template <typename Property> \ 1875 typename find_convertible_property<Property>::query_result_type \ 1876 query(const Property& p, \ 1877 typename enable_if< \ 1878 !is_same< \ 1879 typename find_convertible_property<Property>::query_result_type, \ 1880 void \ 1881 >::value \ 1882 && \ 1883 is_reference< \ 1884 typename find_convertible_property<Property>::query_result_type \ 1885 >::value \ 1886 >::type* = 0) const \ 1887 { \ 1888 typedef find_convertible_property<Property> found; \ 1889 typename remove_reference< \ 1890 typename found::query_result_type>::type* result; \ 1891 prop_fns_[found::index].query(&result, object_fns_->target(*this), \ 1892 &static_cast<const typename found::type&>(p)); \ 1893 return *result; \ 1894 } \ 1895 \ 1896 template <typename Property> \ 1897 typename find_convertible_property<Property>::query_result_type \ 1898 query(const Property& p, \ 1899 typename enable_if< \ 1900 !is_same< \ 1901 typename find_convertible_property<Property>::query_result_type, \ 1902 void \ 1903 >::value \ 1904 && \ 1905 is_scalar< \ 1906 typename find_convertible_property<Property>::query_result_type \ 1907 >::value \ 1908 >::type* = 0) const \ 1909 { \ 1910 typedef find_convertible_property<Property> found; \ 1911 typename found::query_result_type result; \ 1912 prop_fns_[found::index].query(&result, object_fns_->target(*this), \ 1913 &static_cast<const typename found::type&>(p)); \ 1914 return result; \ 1915 } \ 1916 \ 1917 template <typename Property> \ 1918 typename find_convertible_property<Property>::query_result_type \ 1919 query(const Property& p, \ 1920 typename enable_if< \ 1921 !is_same< \ 1922 typename find_convertible_property<Property>::query_result_type, \ 1923 void \ 1924 >::value \ 1925 && \ 1926 !is_reference< \ 1927 typename find_convertible_property<Property>::query_result_type \ 1928 >::value \ 1929 && \ 1930 !is_scalar< \ 1931 typename find_convertible_property<Property>::query_result_type \ 1932 >::value \ 1933 >::type* = 0) const \ 1934 { \ 1935 typedef find_convertible_property<Property> found; \ 1936 typename found::query_result_type* result; \ 1937 prop_fns_[found::index].query(&result, object_fns_->target(*this), \ 1938 &static_cast<const typename found::type&>(p)); \ 1939 return *boost::asio::detail::scoped_ptr< \ 1940 typename found::query_result_type>(result); \ 1941 } \ 1942 \ 1943 template <typename T> \ 1944 struct find_convertible_requirable_property : \ 1945 detail::supportable_properties< \ 1946 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \ 1947 find_convertible_requirable_property<T> {}; \ 1948 \ 1949 template <typename Property> \ 1950 any_executor require(const Property& p, \ 1951 typename enable_if< \ 1952 find_convertible_requirable_property<Property>::value \ 1953 >::type* = 0) const \ 1954 { \ 1955 typedef find_convertible_requirable_property<Property> found; \ 1956 return prop_fns_[found::index].require(object_fns_->target(*this), \ 1957 &static_cast<const typename found::type&>(p)); \ 1958 } \ 1959 \ 1960 template <typename T> \ 1961 struct find_convertible_preferable_property : \ 1962 detail::supportable_properties< \ 1963 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \ 1964 find_convertible_preferable_property<T> {}; \ 1965 \ 1966 template <typename Property> \ 1967 any_executor prefer(const Property& p, \ 1968 typename enable_if< \ 1969 find_convertible_preferable_property<Property>::value \ 1970 >::type* = 0) const \ 1971 { \ 1972 typedef find_convertible_preferable_property<Property> found; \ 1973 return prop_fns_[found::index].prefer(object_fns_->target(*this), \ 1974 &static_cast<const typename found::type&>(p)); \ 1975 } \ 1976 \ 1977 template <typename Ex> \ 1978 static const prop_fns<any_executor>* prop_fns_table() \ 1979 { \ 1980 static const prop_fns<any_executor> fns[] = \ 1981 { \ 1982 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \ 1983 }; \ 1984 return fns; \ 1985 } \ 1986 \ 1987 const prop_fns<any_executor>* prop_fns_; \ 1988 typedef detail::supportable_properties<0, \ 1989 void(BOOST_ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \ 1990 }; \ 1991 \ 1992 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 1993 inline bool operator==(const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \ 1994 const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \ 1995 { \ 1996 return a.equality_helper(b); \ 1997 } \ 1998 \ 1999 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2000 inline bool operator==(const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \ 2001 nullptr_t) BOOST_ASIO_NOEXCEPT \ 2002 { \ 2003 return !a; \ 2004 } \ 2005 \ 2006 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2007 inline bool operator==(nullptr_t, \ 2008 const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \ 2009 { \ 2010 return !b; \ 2011 } \ 2012 \ 2013 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2014 inline bool operator!=(const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \ 2015 const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \ 2016 { \ 2017 return !a.equality_helper(b); \ 2018 } \ 2019 \ 2020 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2021 inline bool operator!=(const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \ 2022 nullptr_t) BOOST_ASIO_NOEXCEPT \ 2023 { \ 2024 return !!a; \ 2025 } \ 2026 \ 2027 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2028 inline bool operator!=(nullptr_t, \ 2029 const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \ 2030 { \ 2031 return !!b; \ 2032 } \ 2033 \ 2034 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2035 inline void swap(any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \ 2036 any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \ 2037 { \ 2038 return a.swap(b); \ 2039 } \ 2040 /**/ 2041 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF) 2042 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF 2043 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS 2044 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS 2045 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 2046 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 2047 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 2048 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 2049 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 2050 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 2051 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 2052 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 2053 2054 #endif // if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2055 2056 } // namespace execution 2057 namespace traits { 2058 2059 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 2060 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2061 2062 template <typename... SupportableProperties> 2063 struct equality_comparable<execution::any_executor<SupportableProperties...> > 2064 { 2065 static const bool is_valid = true; 2066 static const bool is_noexcept = true; 2067 }; 2068 2069 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2070 2071 template <> 2072 struct equality_comparable<execution::any_executor<> > 2073 { 2074 static const bool is_valid = true; 2075 static const bool is_noexcept = true; 2076 }; 2077 2078 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF(n) \ 2079 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2080 struct equality_comparable< \ 2081 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> > \ 2082 { \ 2083 static const bool is_valid = true; \ 2084 static const bool is_noexcept = true; \ 2085 }; \ 2086 /**/ 2087 BOOST_ASIO_VARIADIC_GENERATE( 2088 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF) 2089 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF 2090 2091 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2092 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 2093 2094 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 2095 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2096 2097 template <typename F, typename... SupportableProperties> 2098 struct execute_member<execution::any_executor<SupportableProperties...>, F> 2099 { 2100 static const bool is_valid = true; 2101 static const bool is_noexcept = false; 2102 typedef void result_type; 2103 }; 2104 2105 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2106 2107 template <typename F> 2108 struct execute_member<execution::any_executor<>, F> 2109 { 2110 static const bool is_valid = true; 2111 static const bool is_noexcept = false; 2112 typedef void result_type; 2113 }; 2114 2115 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF(n) \ 2116 template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2117 struct execute_member< \ 2118 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, F> \ 2119 { \ 2120 static const bool is_valid = true; \ 2121 static const bool is_noexcept = false; \ 2122 typedef void result_type; \ 2123 }; \ 2124 /**/ 2125 BOOST_ASIO_VARIADIC_GENERATE( 2126 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF) 2127 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF 2128 2129 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2130 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 2131 2132 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 2133 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2134 2135 template <typename Prop, typename... SupportableProperties> 2136 struct query_member< 2137 execution::any_executor<SupportableProperties...>, Prop, 2138 typename enable_if< 2139 execution::detail::supportable_properties< 2140 0, void(SupportableProperties...)>::template 2141 find_convertible_property<Prop>::value 2142 >::type> 2143 { 2144 static const bool is_valid = true; 2145 static const bool is_noexcept = false; 2146 typedef typename execution::detail::supportable_properties< 2147 0, void(SupportableProperties...)>::template 2148 find_convertible_property<Prop>::query_result_type result_type; 2149 }; 2150 2151 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2152 2153 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF(n) \ 2154 template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2155 struct query_member< \ 2156 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \ 2157 typename enable_if< \ 2158 execution::detail::supportable_properties< \ 2159 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \ 2160 find_convertible_property<Prop>::value \ 2161 >::type> \ 2162 { \ 2163 static const bool is_valid = true; \ 2164 static const bool is_noexcept = false; \ 2165 typedef typename execution::detail::supportable_properties< \ 2166 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \ 2167 find_convertible_property<Prop>::query_result_type result_type; \ 2168 }; \ 2169 /**/ 2170 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF) 2171 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF 2172 2173 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2174 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 2175 2176 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 2177 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2178 2179 template <typename Prop, typename... SupportableProperties> 2180 struct require_member< 2181 execution::any_executor<SupportableProperties...>, Prop, 2182 typename enable_if< 2183 execution::detail::supportable_properties< 2184 0, void(SupportableProperties...)>::template 2185 find_convertible_requirable_property<Prop>::value 2186 >::type> 2187 { 2188 static const bool is_valid = true; 2189 static const bool is_noexcept = false; 2190 typedef execution::any_executor<SupportableProperties...> result_type; 2191 }; 2192 2193 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2194 2195 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF(n) \ 2196 template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2197 struct require_member< \ 2198 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \ 2199 typename enable_if< \ 2200 execution::detail::supportable_properties< \ 2201 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \ 2202 find_convertible_requirable_property<Prop>::value \ 2203 >::type> \ 2204 { \ 2205 static const bool is_valid = true; \ 2206 static const bool is_noexcept = false; \ 2207 typedef execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> result_type; \ 2208 }; \ 2209 /**/ 2210 BOOST_ASIO_VARIADIC_GENERATE( 2211 BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF) 2212 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF 2213 2214 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2215 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 2216 2217 #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) 2218 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2219 2220 template <typename Prop, typename... SupportableProperties> 2221 struct prefer_member< 2222 execution::any_executor<SupportableProperties...>, Prop, 2223 typename enable_if< 2224 execution::detail::supportable_properties< 2225 0, void(SupportableProperties...)>::template 2226 find_convertible_preferable_property<Prop>::value 2227 >::type> 2228 { 2229 static const bool is_valid = true; 2230 static const bool is_noexcept = false; 2231 typedef execution::any_executor<SupportableProperties...> result_type; 2232 }; 2233 2234 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2235 2236 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF(n) \ 2237 template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 2238 struct prefer_member< \ 2239 execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \ 2240 typename enable_if< \ 2241 execution::detail::supportable_properties< \ 2242 0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \ 2243 find_convertible_preferable_property<Prop>::value \ 2244 >::type> \ 2245 { \ 2246 static const bool is_valid = true; \ 2247 static const bool is_noexcept = false; \ 2248 typedef execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> result_type; \ 2249 }; \ 2250 /**/ 2251 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF) 2252 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF 2253 2254 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 2255 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) 2256 2257 } // namespace traits 2258 2259 #endif // defined(GENERATING_DOCUMENTATION) 2260 2261 } // namespace asio 2262 } // namespace boost 2263 2264 #include <boost/asio/detail/pop_options.hpp> 2265 2266 #endif // BOOST_ASIO_EXECUTION_ANY_EXECUTOR_HPP 2267