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