1 // 2 // execution/mapping.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_MAPPING_HPP 12 #define BOOST_ASIO_EXECUTION_MAPPING_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 #include <boost/asio/detail/type_traits.hpp> 20 #include <boost/asio/execution/executor.hpp> 21 #include <boost/asio/execution/scheduler.hpp> 22 #include <boost/asio/execution/sender.hpp> 23 #include <boost/asio/is_applicable_property.hpp> 24 #include <boost/asio/query.hpp> 25 #include <boost/asio/traits/query_free.hpp> 26 #include <boost/asio/traits/query_member.hpp> 27 #include <boost/asio/traits/query_static_constexpr_member.hpp> 28 #include <boost/asio/traits/static_query.hpp> 29 #include <boost/asio/traits/static_require.hpp> 30 31 #include <boost/asio/detail/push_options.hpp> 32 33 namespace boost { 34 namespace asio { 35 36 #if defined(GENERATING_DOCUMENTATION) 37 38 namespace execution { 39 40 /// A property to describe what guarantees an executor makes about the mapping 41 /// of execution agents on to threads of execution. 42 struct mapping_t 43 { 44 /// The mapping_t property applies to executors, senders, and schedulers. 45 template <typename T> 46 static constexpr bool is_applicable_property_v = 47 is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; 48 49 /// The top-level mapping_t property cannot be required. 50 static constexpr bool is_requirable = false; 51 52 /// The top-level mapping_t property cannot be preferred. 53 static constexpr bool is_preferable = false; 54 55 /// The type returned by queries against an @c any_executor. 56 typedef mapping_t polymorphic_query_result_type; 57 58 /// A sub-property that indicates that execution agents are mapped on to 59 /// threads of execution. 60 struct thread_t 61 { 62 /// The mapping_t::thread_t property applies to executors, senders, and 63 /// schedulers. 64 template <typename T> 65 static constexpr bool is_applicable_property_v = 66 is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; 67 68 /// The mapping_t::thread_t property can be required. 69 static constexpr bool is_requirable = true; 70 71 /// The mapping_t::thread_t property can be preferred. 72 static constexpr bool is_preferable = true; 73 74 /// The type returned by queries against an @c any_executor. 75 typedef mapping_t polymorphic_query_result_type; 76 77 /// Default constructor. 78 constexpr thread_t(); 79 80 /// Get the value associated with a property object. 81 /** 82 * @returns thread_t(); 83 */ 84 static constexpr mapping_t value(); 85 }; 86 87 /// A sub-property that indicates that execution agents are mapped on to 88 /// new threads of execution. 89 struct new_thread_t 90 { 91 /// The mapping_t::new_thread_t property applies to executors, senders, and 92 /// schedulers. 93 template <typename T> 94 static constexpr bool is_applicable_property_v = 95 is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; 96 97 /// The mapping_t::new_thread_t property can be required. 98 static constexpr bool is_requirable = true; 99 100 /// The mapping_t::new_thread_t property can be preferred. 101 static constexpr bool is_preferable = true; 102 103 /// The type returned by queries against an @c any_executor. 104 typedef mapping_t polymorphic_query_result_type; 105 106 /// Default constructor. 107 constexpr new_thread_t(); 108 109 /// Get the value associated with a property object. 110 /** 111 * @returns new_thread_t(); 112 */ 113 static constexpr mapping_t value(); 114 }; 115 116 /// A sub-property that indicates that the mapping of execution agents is 117 /// implementation-defined. 118 struct other_t 119 { 120 /// The mapping_t::other_t property applies to executors, senders, and 121 /// schedulers. 122 template <typename T> 123 static constexpr bool is_applicable_property_v = 124 is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; 125 126 /// The mapping_t::other_t property can be required. 127 static constexpr bool is_requirable = true; 128 129 /// The mapping_t::other_t property can be preferred. 130 static constexpr bool is_preferable = true; 131 132 /// The type returned by queries against an @c any_executor. 133 typedef mapping_t polymorphic_query_result_type; 134 135 /// Default constructor. 136 constexpr other_t(); 137 138 /// Get the value associated with a property object. 139 /** 140 * @returns other_t(); 141 */ 142 static constexpr mapping_t value(); 143 }; 144 145 /// A special value used for accessing the mapping_t::thread_t property. 146 static constexpr thread_t thread; 147 148 /// A special value used for accessing the mapping_t::new_thread_t property. 149 static constexpr new_thread_t new_thread; 150 151 /// A special value used for accessing the mapping_t::other_t property. 152 static constexpr other_t other; 153 154 /// Default constructor. 155 constexpr mapping_t(); 156 157 /// Construct from a sub-property value. 158 constexpr mapping_t(thread_t); 159 160 /// Construct from a sub-property value. 161 constexpr mapping_t(new_thread_t); 162 163 /// Construct from a sub-property value. 164 constexpr mapping_t(other_t); 165 166 /// Compare property values for equality. 167 friend constexpr bool operator==( 168 const mapping_t& a, const mapping_t& b) noexcept; 169 170 /// Compare property values for inequality. 171 friend constexpr bool operator!=( 172 const mapping_t& a, const mapping_t& b) noexcept; 173 }; 174 175 /// A special value used for accessing the mapping_t property. 176 constexpr mapping_t mapping; 177 178 } // namespace execution 179 180 #else // defined(GENERATING_DOCUMENTATION) 181 182 namespace execution { 183 namespace detail { 184 namespace mapping { 185 186 template <int I> struct thread_t; 187 template <int I> struct new_thread_t; 188 template <int I> struct other_t; 189 190 } // namespace mapping 191 192 template <int I = 0> 193 struct mapping_t 194 { 195 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 196 template <typename T> 197 BOOST_ASIO_STATIC_CONSTEXPR(bool, 198 is_applicable_property_v = ( 199 is_executor<T>::value 200 || conditional< 201 is_executor<T>::value, 202 false_type, 203 is_sender<T> 204 >::type::value 205 || conditional< 206 is_executor<T>::value, 207 false_type, 208 is_scheduler<T> 209 >::type::value)); 210 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 211 212 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); 213 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); 214 typedef mapping_t polymorphic_query_result_type; 215 216 typedef detail::mapping::thread_t<I> thread_t; 217 typedef detail::mapping::new_thread_t<I> new_thread_t; 218 typedef detail::mapping::other_t<I> other_t; 219 220 BOOST_ASIO_CONSTEXPR mapping_t() 221 : value_(-1) 222 { 223 } 224 225 BOOST_ASIO_CONSTEXPR mapping_t(thread_t) 226 : value_(0) 227 { 228 } 229 230 BOOST_ASIO_CONSTEXPR mapping_t(new_thread_t) 231 : value_(1) 232 { 233 } 234 235 BOOST_ASIO_CONSTEXPR mapping_t(other_t) 236 : value_(2) 237 { 238 } 239 240 template <typename T> 241 struct proxy 242 { 243 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 244 struct type 245 { 246 template <typename P> 247 auto query(BOOST_ASIO_MOVE_ARG(P) p) const 248 noexcept( 249 noexcept( 250 declval<typename conditional<true, T, P>::type>().query( 251 BOOST_ASIO_MOVE_CAST(P)(p)) 252 ) 253 ) 254 -> decltype( 255 declval<typename conditional<true, T, P>::type>().query( 256 BOOST_ASIO_MOVE_CAST(P)(p)) 257 ); 258 }; 259 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 260 typedef T type; 261 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 262 }; 263 264 template <typename T> 265 struct static_proxy 266 { 267 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 268 struct type 269 { 270 template <typename P> 271 static constexpr auto query(BOOST_ASIO_MOVE_ARG(P) p) 272 noexcept( 273 noexcept( 274 conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p)) 275 ) 276 ) 277 -> decltype( 278 conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p)) 279 ) 280 { 281 return T::query(BOOST_ASIO_MOVE_CAST(P)(p)); 282 } 283 }; 284 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 285 typedef T type; 286 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 287 }; 288 289 template <typename T> 290 struct query_member : 291 traits::query_member<typename proxy<T>::type, mapping_t> {}; 292 293 template <typename T> 294 struct query_static_constexpr_member : 295 traits::query_static_constexpr_member< 296 typename static_proxy<T>::type, mapping_t> {}; 297 298 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 299 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 300 template <typename T> 301 static BOOST_ASIO_CONSTEXPR 302 typename query_static_constexpr_member<T>::result_type 303 static_query() 304 BOOST_ASIO_NOEXCEPT_IF(( 305 query_static_constexpr_member<T>::is_noexcept)) 306 { 307 return query_static_constexpr_member<T>::value(); 308 } 309 310 template <typename T> 311 static BOOST_ASIO_CONSTEXPR 312 typename traits::static_query<T, thread_t>::result_type 313 static_query( 314 typename enable_if< 315 !query_static_constexpr_member<T>::is_valid 316 >::type* = 0, 317 typename enable_if< 318 !query_member<T>::is_valid 319 >::type* = 0, 320 typename enable_if< 321 traits::static_query<T, thread_t>::is_valid 322 >::type* = 0) BOOST_ASIO_NOEXCEPT 323 { 324 return traits::static_query<T, thread_t>::value(); 325 } 326 327 template <typename T> 328 static BOOST_ASIO_CONSTEXPR 329 typename traits::static_query<T, new_thread_t>::result_type 330 static_query( 331 typename enable_if< 332 !query_static_constexpr_member<T>::is_valid 333 >::type* = 0, 334 typename enable_if< 335 !query_member<T>::is_valid 336 >::type* = 0, 337 typename enable_if< 338 !traits::static_query<T, thread_t>::is_valid 339 >::type* = 0, 340 typename enable_if< 341 traits::static_query<T, new_thread_t>::is_valid 342 >::type* = 0) BOOST_ASIO_NOEXCEPT 343 { 344 return traits::static_query<T, new_thread_t>::value(); 345 } 346 347 template <typename T> 348 static BOOST_ASIO_CONSTEXPR 349 typename traits::static_query<T, other_t>::result_type 350 static_query( 351 typename enable_if< 352 !query_static_constexpr_member<T>::is_valid 353 >::type* = 0, 354 typename enable_if< 355 !query_member<T>::is_valid 356 >::type* = 0, 357 typename enable_if< 358 !traits::static_query<T, thread_t>::is_valid 359 >::type* = 0, 360 typename enable_if< 361 !traits::static_query<T, new_thread_t>::is_valid 362 >::type* = 0, 363 typename enable_if< 364 traits::static_query<T, other_t>::is_valid 365 >::type* = 0) BOOST_ASIO_NOEXCEPT 366 { 367 return traits::static_query<T, other_t>::value(); 368 } 369 370 template <typename E, typename T = decltype(mapping_t::static_query<E>())> 371 static BOOST_ASIO_CONSTEXPR const T static_query_v 372 = mapping_t::static_query<E>(); 373 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 374 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 375 376 friend BOOST_ASIO_CONSTEXPR bool operator==( 377 const mapping_t& a, const mapping_t& b) 378 { 379 return a.value_ == b.value_; 380 } 381 382 friend BOOST_ASIO_CONSTEXPR bool operator!=( 383 const mapping_t& a, const mapping_t& b) 384 { 385 return a.value_ != b.value_; 386 } 387 388 struct convertible_from_mapping_t 389 { 390 BOOST_ASIO_CONSTEXPR convertible_from_mapping_t(mapping_t) {} 391 }; 392 393 template <typename Executor> 394 friend BOOST_ASIO_CONSTEXPR mapping_t query( 395 const Executor& ex, convertible_from_mapping_t, 396 typename enable_if< 397 can_query<const Executor&, thread_t>::value 398 >::type* = 0) 399 #if !defined(__clang__) // Clang crashes if noexcept is used here. 400 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. 401 BOOST_ASIO_NOEXCEPT_IF(( 402 is_nothrow_query<const Executor&, mapping_t<>::thread_t>::value)) 403 #else // defined(BOOST_ASIO_MSVC) 404 BOOST_ASIO_NOEXCEPT_IF(( 405 is_nothrow_query<const Executor&, thread_t>::value)) 406 #endif // defined(BOOST_ASIO_MSVC) 407 #endif // !defined(__clang__) 408 { 409 return boost::asio::query(ex, thread_t()); 410 } 411 412 template <typename Executor> 413 friend BOOST_ASIO_CONSTEXPR mapping_t query( 414 const Executor& ex, convertible_from_mapping_t, 415 typename enable_if< 416 !can_query<const Executor&, thread_t>::value 417 >::type* = 0, 418 typename enable_if< 419 can_query<const Executor&, new_thread_t>::value 420 >::type* = 0) 421 #if !defined(__clang__) // Clang crashes if noexcept is used here. 422 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. 423 BOOST_ASIO_NOEXCEPT_IF(( 424 is_nothrow_query<const Executor&, mapping_t<>::new_thread_t>::value)) 425 #else // defined(BOOST_ASIO_MSVC) 426 BOOST_ASIO_NOEXCEPT_IF(( 427 is_nothrow_query<const Executor&, new_thread_t>::value)) 428 #endif // defined(BOOST_ASIO_MSVC) 429 #endif // !defined(__clang__) 430 { 431 return boost::asio::query(ex, new_thread_t()); 432 } 433 434 template <typename Executor> 435 friend BOOST_ASIO_CONSTEXPR mapping_t query( 436 const Executor& ex, convertible_from_mapping_t, 437 typename enable_if< 438 !can_query<const Executor&, thread_t>::value 439 >::type* = 0, 440 typename enable_if< 441 !can_query<const Executor&, new_thread_t>::value 442 >::type* = 0, 443 typename enable_if< 444 can_query<const Executor&, other_t>::value 445 >::type* = 0) 446 #if !defined(__clang__) // Clang crashes if noexcept is used here. 447 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. 448 BOOST_ASIO_NOEXCEPT_IF(( 449 is_nothrow_query<const Executor&, mapping_t<>::other_t>::value)) 450 #else // defined(BOOST_ASIO_MSVC) 451 BOOST_ASIO_NOEXCEPT_IF(( 452 is_nothrow_query<const Executor&, other_t>::value)) 453 #endif // defined(BOOST_ASIO_MSVC) 454 #endif // !defined(__clang__) 455 { 456 return boost::asio::query(ex, other_t()); 457 } 458 459 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(thread_t, thread); 460 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(new_thread_t, new_thread); 461 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(other_t, other); 462 463 #if !defined(BOOST_ASIO_HAS_CONSTEXPR) 464 static const mapping_t instance; 465 #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR) 466 467 private: 468 int value_; 469 }; 470 471 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 472 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 473 template <int I> template <typename E, typename T> 474 const T mapping_t<I>::static_query_v; 475 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 476 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 477 478 #if !defined(BOOST_ASIO_HAS_CONSTEXPR) 479 template <int I> 480 const mapping_t<I> mapping_t<I>::instance; 481 #endif 482 483 template <int I> 484 const typename mapping_t<I>::thread_t mapping_t<I>::thread; 485 486 template <int I> 487 const typename mapping_t<I>::new_thread_t mapping_t<I>::new_thread; 488 489 template <int I> 490 const typename mapping_t<I>::other_t mapping_t<I>::other; 491 492 namespace mapping { 493 494 template <int I = 0> 495 struct thread_t 496 { 497 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 498 template <typename T> 499 BOOST_ASIO_STATIC_CONSTEXPR(bool, 500 is_applicable_property_v = ( 501 is_executor<T>::value 502 || conditional< 503 is_executor<T>::value, 504 false_type, 505 is_sender<T> 506 >::type::value 507 || conditional< 508 is_executor<T>::value, 509 false_type, 510 is_scheduler<T> 511 >::type::value)); 512 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 513 514 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); 515 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); 516 typedef mapping_t<I> polymorphic_query_result_type; 517 518 BOOST_ASIO_CONSTEXPR thread_t() 519 { 520 } 521 522 template <typename T> 523 struct query_member : 524 traits::query_member< 525 typename mapping_t<I>::template proxy<T>::type, thread_t> {}; 526 527 template <typename T> 528 struct query_static_constexpr_member : 529 traits::query_static_constexpr_member< 530 typename mapping_t<I>::template static_proxy<T>::type, thread_t> {}; 531 532 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 533 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 534 template <typename T> 535 static BOOST_ASIO_CONSTEXPR 536 typename query_static_constexpr_member<T>::result_type 537 static_query() 538 BOOST_ASIO_NOEXCEPT_IF(( 539 query_static_constexpr_member<T>::is_noexcept)) 540 { 541 return query_static_constexpr_member<T>::value(); 542 } 543 544 template <typename T> 545 static BOOST_ASIO_CONSTEXPR thread_t static_query( 546 typename enable_if< 547 !query_static_constexpr_member<T>::is_valid 548 >::type* = 0, 549 typename enable_if< 550 !query_member<T>::is_valid 551 >::type* = 0, 552 typename enable_if< 553 !traits::query_free<T, thread_t>::is_valid 554 >::type* = 0, 555 typename enable_if< 556 !can_query<T, new_thread_t<I> >::value 557 >::type* = 0, 558 typename enable_if< 559 !can_query<T, other_t<I> >::value 560 >::type* = 0) BOOST_ASIO_NOEXCEPT 561 { 562 return thread_t(); 563 } 564 565 template <typename E, typename T = decltype(thread_t::static_query<E>())> 566 static BOOST_ASIO_CONSTEXPR const T static_query_v 567 = thread_t::static_query<E>(); 568 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 569 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 570 571 static BOOST_ASIO_CONSTEXPR mapping_t<I> value() 572 { 573 return thread_t(); 574 } 575 576 friend BOOST_ASIO_CONSTEXPR bool operator==( 577 const thread_t&, const thread_t&) 578 { 579 return true; 580 } 581 582 friend BOOST_ASIO_CONSTEXPR bool operator!=( 583 const thread_t&, const thread_t&) 584 { 585 return false; 586 } 587 }; 588 589 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 590 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 591 template <int I> template <typename E, typename T> 592 const T thread_t<I>::static_query_v; 593 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 594 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 595 596 template <int I = 0> 597 struct new_thread_t 598 { 599 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 600 template <typename T> 601 BOOST_ASIO_STATIC_CONSTEXPR(bool, 602 is_applicable_property_v = ( 603 is_executor<T>::value 604 || conditional< 605 is_executor<T>::value, 606 false_type, 607 is_sender<T> 608 >::type::value 609 || conditional< 610 is_executor<T>::value, 611 false_type, 612 is_scheduler<T> 613 >::type::value)); 614 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 615 616 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); 617 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); 618 typedef mapping_t<I> polymorphic_query_result_type; 619 620 BOOST_ASIO_CONSTEXPR new_thread_t() 621 { 622 } 623 624 template <typename T> 625 struct query_member : 626 traits::query_member< 627 typename mapping_t<I>::template proxy<T>::type, new_thread_t> {}; 628 629 template <typename T> 630 struct query_static_constexpr_member : 631 traits::query_static_constexpr_member< 632 typename mapping_t<I>::template static_proxy<T>::type, new_thread_t> {}; 633 634 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 635 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 636 template <typename T> 637 static BOOST_ASIO_CONSTEXPR 638 typename query_static_constexpr_member<T>::result_type 639 static_query() 640 BOOST_ASIO_NOEXCEPT_IF(( 641 query_static_constexpr_member<T>::is_noexcept)) 642 { 643 return query_static_constexpr_member<T>::value(); 644 } 645 646 template <typename E, typename T = decltype(new_thread_t::static_query<E>())> 647 static BOOST_ASIO_CONSTEXPR const T static_query_v 648 = new_thread_t::static_query<E>(); 649 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 650 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 651 652 static BOOST_ASIO_CONSTEXPR mapping_t<I> value() 653 { 654 return new_thread_t(); 655 } 656 657 friend BOOST_ASIO_CONSTEXPR bool operator==( 658 const new_thread_t&, const new_thread_t&) 659 { 660 return true; 661 } 662 663 friend BOOST_ASIO_CONSTEXPR bool operator!=( 664 const new_thread_t&, const new_thread_t&) 665 { 666 return false; 667 } 668 }; 669 670 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 671 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 672 template <int I> template <typename E, typename T> 673 const T new_thread_t<I>::static_query_v; 674 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 675 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 676 677 template <int I> 678 struct other_t 679 { 680 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 681 template <typename T> 682 BOOST_ASIO_STATIC_CONSTEXPR(bool, 683 is_applicable_property_v = ( 684 is_executor<T>::value 685 || conditional< 686 is_executor<T>::value, 687 false_type, 688 is_sender<T> 689 >::type::value 690 || conditional< 691 is_executor<T>::value, 692 false_type, 693 is_scheduler<T> 694 >::type::value)); 695 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 696 697 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); 698 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); 699 typedef mapping_t<I> polymorphic_query_result_type; 700 701 BOOST_ASIO_CONSTEXPR other_t() 702 { 703 } 704 705 template <typename T> 706 struct query_member : 707 traits::query_member< 708 typename mapping_t<I>::template proxy<T>::type, other_t> {}; 709 710 template <typename T> 711 struct query_static_constexpr_member : 712 traits::query_static_constexpr_member< 713 typename mapping_t<I>::template static_proxy<T>::type, other_t> {}; 714 715 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 716 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 717 template <typename T> 718 static BOOST_ASIO_CONSTEXPR 719 typename query_static_constexpr_member<T>::result_type 720 static_query() 721 BOOST_ASIO_NOEXCEPT_IF(( 722 query_static_constexpr_member<T>::is_noexcept)) 723 { 724 return query_static_constexpr_member<T>::value(); 725 } 726 727 template <typename E, typename T = decltype(other_t::static_query<E>())> 728 static BOOST_ASIO_CONSTEXPR const T static_query_v 729 = other_t::static_query<E>(); 730 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 731 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 732 733 static BOOST_ASIO_CONSTEXPR mapping_t<I> value() 734 { 735 return other_t(); 736 } 737 738 friend BOOST_ASIO_CONSTEXPR bool operator==( 739 const other_t&, const other_t&) 740 { 741 return true; 742 } 743 744 friend BOOST_ASIO_CONSTEXPR bool operator!=( 745 const other_t&, const other_t&) 746 { 747 return false; 748 } 749 }; 750 751 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 752 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 753 template <int I> template <typename E, typename T> 754 const T other_t<I>::static_query_v; 755 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 756 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 757 758 } // namespace mapping 759 } // namespace detail 760 761 typedef detail::mapping_t<> mapping_t; 762 763 #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) 764 constexpr mapping_t mapping; 765 #else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) 766 namespace { static const mapping_t& mapping = mapping_t::instance; } 767 #endif 768 769 } // namespace execution 770 771 #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 772 773 template <typename T> 774 struct is_applicable_property<T, execution::mapping_t> 775 : integral_constant<bool, 776 execution::is_executor<T>::value 777 || conditional< 778 execution::is_executor<T>::value, 779 false_type, 780 execution::is_sender<T> 781 >::type::value 782 || conditional< 783 execution::is_executor<T>::value, 784 false_type, 785 execution::is_scheduler<T> 786 >::type::value> 787 { 788 }; 789 790 template <typename T> 791 struct is_applicable_property<T, execution::mapping_t::thread_t> 792 : integral_constant<bool, 793 execution::is_executor<T>::value 794 || conditional< 795 execution::is_executor<T>::value, 796 false_type, 797 execution::is_sender<T> 798 >::type::value 799 || conditional< 800 execution::is_executor<T>::value, 801 false_type, 802 execution::is_scheduler<T> 803 >::type::value> 804 { 805 }; 806 807 template <typename T> 808 struct is_applicable_property<T, execution::mapping_t::new_thread_t> 809 : integral_constant<bool, 810 execution::is_executor<T>::value 811 || conditional< 812 execution::is_executor<T>::value, 813 false_type, 814 execution::is_sender<T> 815 >::type::value 816 || conditional< 817 execution::is_executor<T>::value, 818 false_type, 819 execution::is_scheduler<T> 820 >::type::value> 821 { 822 }; 823 824 template <typename T> 825 struct is_applicable_property<T, execution::mapping_t::other_t> 826 : integral_constant<bool, 827 execution::is_executor<T>::value 828 || conditional< 829 execution::is_executor<T>::value, 830 false_type, 831 execution::is_sender<T> 832 >::type::value 833 || conditional< 834 execution::is_executor<T>::value, 835 false_type, 836 execution::is_scheduler<T> 837 >::type::value> 838 { 839 }; 840 841 #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 842 843 namespace traits { 844 845 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) 846 847 template <typename T> 848 struct query_free_default<T, execution::mapping_t, 849 typename enable_if< 850 can_query<T, execution::mapping_t::thread_t>::value 851 >::type> 852 { 853 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 854 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 855 (is_nothrow_query<T, execution::mapping_t::thread_t>::value)); 856 857 typedef execution::mapping_t result_type; 858 }; 859 860 template <typename T> 861 struct query_free_default<T, execution::mapping_t, 862 typename enable_if< 863 !can_query<T, execution::mapping_t::thread_t>::value 864 && can_query<T, execution::mapping_t::new_thread_t>::value 865 >::type> 866 { 867 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 868 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 869 (is_nothrow_query<T, execution::mapping_t::new_thread_t>::value)); 870 871 typedef execution::mapping_t result_type; 872 }; 873 874 template <typename T> 875 struct query_free_default<T, execution::mapping_t, 876 typename enable_if< 877 !can_query<T, execution::mapping_t::thread_t>::value 878 && !can_query<T, execution::mapping_t::new_thread_t>::value 879 && can_query<T, execution::mapping_t::other_t>::value 880 >::type> 881 { 882 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 883 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 884 (is_nothrow_query<T, execution::mapping_t::other_t>::value)); 885 886 typedef execution::mapping_t result_type; 887 }; 888 889 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) 890 891 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 892 || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 893 894 template <typename T> 895 struct static_query<T, execution::mapping_t, 896 typename enable_if< 897 execution::detail::mapping_t<0>:: 898 query_static_constexpr_member<T>::is_valid 899 >::type> 900 { 901 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 902 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 903 904 typedef typename execution::detail::mapping_t<0>:: 905 query_static_constexpr_member<T>::result_type result_type; 906 907 static BOOST_ASIO_CONSTEXPR result_type value() 908 { 909 return execution::detail::mapping_t<0>:: 910 query_static_constexpr_member<T>::value(); 911 } 912 }; 913 914 template <typename T> 915 struct static_query<T, execution::mapping_t, 916 typename enable_if< 917 !execution::detail::mapping_t<0>:: 918 query_static_constexpr_member<T>::is_valid 919 && !execution::detail::mapping_t<0>:: 920 query_member<T>::is_valid 921 && traits::static_query<T, execution::mapping_t::thread_t>::is_valid 922 >::type> 923 { 924 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 925 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 926 927 typedef typename traits::static_query<T, 928 execution::mapping_t::thread_t>::result_type result_type; 929 930 static BOOST_ASIO_CONSTEXPR result_type value() 931 { 932 return traits::static_query<T, execution::mapping_t::thread_t>::value(); 933 } 934 }; 935 936 template <typename T> 937 struct static_query<T, execution::mapping_t, 938 typename enable_if< 939 !execution::detail::mapping_t<0>:: 940 query_static_constexpr_member<T>::is_valid 941 && !execution::detail::mapping_t<0>:: 942 query_member<T>::is_valid 943 && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid 944 && traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid 945 >::type> 946 { 947 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 948 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 949 950 typedef typename traits::static_query<T, 951 execution::mapping_t::new_thread_t>::result_type result_type; 952 953 static BOOST_ASIO_CONSTEXPR result_type value() 954 { 955 return traits::static_query<T, execution::mapping_t::new_thread_t>::value(); 956 } 957 }; 958 959 template <typename T> 960 struct static_query<T, execution::mapping_t, 961 typename enable_if< 962 !execution::detail::mapping_t<0>:: 963 query_static_constexpr_member<T>::is_valid 964 && !execution::detail::mapping_t<0>:: 965 query_member<T>::is_valid 966 && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid 967 && !traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid 968 && traits::static_query<T, execution::mapping_t::other_t>::is_valid 969 >::type> 970 { 971 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 972 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 973 974 typedef typename traits::static_query<T, 975 execution::mapping_t::other_t>::result_type result_type; 976 977 static BOOST_ASIO_CONSTEXPR result_type value() 978 { 979 return traits::static_query<T, execution::mapping_t::other_t>::value(); 980 } 981 }; 982 983 template <typename T> 984 struct static_query<T, execution::mapping_t::thread_t, 985 typename enable_if< 986 execution::detail::mapping::thread_t<0>:: 987 query_static_constexpr_member<T>::is_valid 988 >::type> 989 { 990 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 991 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 992 993 typedef typename execution::detail::mapping::thread_t<0>:: 994 query_static_constexpr_member<T>::result_type result_type; 995 996 static BOOST_ASIO_CONSTEXPR result_type value() 997 { 998 return execution::detail::mapping::thread_t<0>:: 999 query_static_constexpr_member<T>::value(); 1000 } 1001 }; 1002 1003 template <typename T> 1004 struct static_query<T, execution::mapping_t::thread_t, 1005 typename enable_if< 1006 !execution::detail::mapping::thread_t<0>:: 1007 query_static_constexpr_member<T>::is_valid 1008 && !execution::detail::mapping::thread_t<0>:: 1009 query_member<T>::is_valid 1010 && !traits::query_free<T, execution::mapping_t::thread_t>::is_valid 1011 && !can_query<T, execution::mapping_t::new_thread_t>::value 1012 && !can_query<T, execution::mapping_t::other_t>::value 1013 >::type> 1014 { 1015 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1016 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1017 1018 typedef execution::mapping_t::thread_t result_type; 1019 1020 static BOOST_ASIO_CONSTEXPR result_type value() 1021 { 1022 return result_type(); 1023 } 1024 }; 1025 1026 template <typename T> 1027 struct static_query<T, execution::mapping_t::new_thread_t, 1028 typename enable_if< 1029 execution::detail::mapping::new_thread_t<0>:: 1030 query_static_constexpr_member<T>::is_valid 1031 >::type> 1032 { 1033 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1034 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1035 1036 typedef typename execution::detail::mapping::new_thread_t<0>:: 1037 query_static_constexpr_member<T>::result_type result_type; 1038 1039 static BOOST_ASIO_CONSTEXPR result_type value() 1040 { 1041 return execution::detail::mapping::new_thread_t<0>:: 1042 query_static_constexpr_member<T>::value(); 1043 } 1044 }; 1045 1046 template <typename T> 1047 struct static_query<T, execution::mapping_t::other_t, 1048 typename enable_if< 1049 execution::detail::mapping::other_t<0>:: 1050 query_static_constexpr_member<T>::is_valid 1051 >::type> 1052 { 1053 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1054 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1055 1056 typedef typename execution::detail::mapping::other_t<0>:: 1057 query_static_constexpr_member<T>::result_type result_type; 1058 1059 static BOOST_ASIO_CONSTEXPR result_type value() 1060 { 1061 return execution::detail::mapping::other_t<0>:: 1062 query_static_constexpr_member<T>::value(); 1063 } 1064 }; 1065 1066 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 1067 // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 1068 1069 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) 1070 1071 template <typename T> 1072 struct static_require<T, execution::mapping_t::thread_t, 1073 typename enable_if< 1074 static_query<T, execution::mapping_t::thread_t>::is_valid 1075 >::type> 1076 { 1077 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = 1078 (is_same<typename static_query<T, 1079 execution::mapping_t::thread_t>::result_type, 1080 execution::mapping_t::thread_t>::value)); 1081 }; 1082 1083 template <typename T> 1084 struct static_require<T, execution::mapping_t::new_thread_t, 1085 typename enable_if< 1086 static_query<T, execution::mapping_t::new_thread_t>::is_valid 1087 >::type> 1088 { 1089 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = 1090 (is_same<typename static_query<T, 1091 execution::mapping_t::new_thread_t>::result_type, 1092 execution::mapping_t::new_thread_t>::value)); 1093 }; 1094 1095 template <typename T> 1096 struct static_require<T, execution::mapping_t::other_t, 1097 typename enable_if< 1098 static_query<T, execution::mapping_t::other_t>::is_valid 1099 >::type> 1100 { 1101 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = 1102 (is_same<typename static_query<T, 1103 execution::mapping_t::other_t>::result_type, 1104 execution::mapping_t::other_t>::value)); 1105 }; 1106 1107 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) 1108 1109 } // namespace traits 1110 1111 #endif // defined(GENERATING_DOCUMENTATION) 1112 1113 } // namespace asio 1114 } // namespace boost 1115 1116 #include <boost/asio/detail/pop_options.hpp> 1117 1118 #endif // BOOST_ASIO_EXECUTION_MAPPING_HPP 1119