1 // 2 // execution/any_executor.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 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 2349