1 // 2 // execution/blocking.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_BLOCKING_HPP 12 #define BOOST_ASIO_EXECUTION_BLOCKING_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/execute.hpp> 21 #include <boost/asio/execution/executor.hpp> 22 #include <boost/asio/execution/scheduler.hpp> 23 #include <boost/asio/execution/sender.hpp> 24 #include <boost/asio/is_applicable_property.hpp> 25 #include <boost/asio/prefer.hpp> 26 #include <boost/asio/query.hpp> 27 #include <boost/asio/require.hpp> 28 #include <boost/asio/traits/query_free.hpp> 29 #include <boost/asio/traits/query_member.hpp> 30 #include <boost/asio/traits/query_static_constexpr_member.hpp> 31 #include <boost/asio/traits/static_query.hpp> 32 #include <boost/asio/traits/static_require.hpp> 33 34 #include <boost/asio/detail/push_options.hpp> 35 36 namespace boost { 37 namespace asio { 38 39 #if defined(GENERATING_DOCUMENTATION) 40 41 namespace execution { 42 43 /// A property to describe what guarantees an executor makes about the blocking 44 /// behaviour of their execution functions. 45 struct blocking_t 46 { 47 /// The blocking_t property applies to executors, senders, and schedulers. 48 template <typename T> 49 static constexpr bool is_applicable_property_v = 50 is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; 51 52 /// The top-level blocking_t property cannot be required. 53 static constexpr bool is_requirable = false; 54 55 /// The top-level blocking_t property cannot be preferred. 56 static constexpr bool is_preferable = false; 57 58 /// The type returned by queries against an @c any_executor. 59 typedef blocking_t polymorphic_query_result_type; 60 61 /// A sub-property that indicates that invocation of an executor's execution 62 /// function may block pending completion of one or more invocations of the 63 /// submitted function object. 64 struct possibly_t 65 { 66 /// The blocking_t::possibly_t property applies to executors, senders, and 67 /// schedulers. 68 template <typename T> 69 static constexpr bool is_applicable_property_v = 70 is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; 71 72 /// The blocking_t::possibly_t property can be required. 73 static constexpr bool is_requirable = true; 74 75 /// The blocking_t::possibly_t property can be preferred. 76 static constexpr bool is_preferable = true; 77 78 /// The type returned by queries against an @c any_executor. 79 typedef blocking_t polymorphic_query_result_type; 80 81 /// Default constructor. 82 constexpr possibly_t(); 83 84 /// Get the value associated with a property object. 85 /** 86 * @returns possibly_t(); 87 */ 88 static constexpr blocking_t value(); 89 }; 90 91 /// A sub-property that indicates that invocation of an executor's execution 92 /// function shall block until completion of all invocations of the submitted 93 /// function object. 94 struct always_t 95 { 96 /// The blocking_t::always_t property applies to executors, senders, and 97 /// schedulers. 98 template <typename T> 99 static constexpr bool is_applicable_property_v = 100 is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; 101 102 /// The blocking_t::always_t property can be required. 103 static constexpr bool is_requirable = true; 104 105 /// The blocking_t::always_t property can be preferred. 106 static constexpr bool is_preferable = false; 107 108 /// The type returned by queries against an @c any_executor. 109 typedef blocking_t polymorphic_query_result_type; 110 111 /// Default constructor. 112 constexpr always_t(); 113 114 /// Get the value associated with a property object. 115 /** 116 * @returns always_t(); 117 */ 118 static constexpr blocking_t value(); 119 }; 120 121 /// A sub-property that indicates that invocation of an executor's execution 122 /// function shall not block pending completion of the invocations of the 123 /// submitted function object. 124 struct never_t 125 { 126 /// The blocking_t::never_t property applies to executors, senders, and 127 /// schedulers. 128 template <typename T> 129 static constexpr bool is_applicable_property_v = 130 is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; 131 132 /// The blocking_t::never_t property can be required. 133 static constexpr bool is_requirable = true; 134 135 /// The blocking_t::never_t property can be preferred. 136 static constexpr bool is_preferable = true; 137 138 /// The type returned by queries against an @c any_executor. 139 typedef blocking_t polymorphic_query_result_type; 140 141 /// Default constructor. 142 constexpr never_t(); 143 144 /// Get the value associated with a property object. 145 /** 146 * @returns never_t(); 147 */ 148 static constexpr blocking_t value(); 149 }; 150 151 /// A special value used for accessing the blocking_t::possibly_t property. 152 static constexpr possibly_t possibly; 153 154 /// A special value used for accessing the blocking_t::always_t property. 155 static constexpr always_t always; 156 157 /// A special value used for accessing the blocking_t::never_t property. 158 static constexpr never_t never; 159 160 /// Default constructor. 161 constexpr blocking_t(); 162 163 /// Construct from a sub-property value. 164 constexpr blocking_t(possibly_t); 165 166 /// Construct from a sub-property value. 167 constexpr blocking_t(always_t); 168 169 /// Construct from a sub-property value. 170 constexpr blocking_t(never_t); 171 172 /// Compare property values for equality. 173 friend constexpr bool operator==( 174 const blocking_t& a, const blocking_t& b) noexcept; 175 176 /// Compare property values for inequality. 177 friend constexpr bool operator!=( 178 const blocking_t& a, const blocking_t& b) noexcept; 179 }; 180 181 /// A special value used for accessing the blocking_t property. 182 constexpr blocking_t blocking; 183 184 } // namespace execution 185 186 #else // defined(GENERATING_DOCUMENTATION) 187 188 namespace execution { 189 namespace detail { 190 namespace blocking { 191 192 template <int I> struct possibly_t; 193 template <int I> struct always_t; 194 template <int I> struct never_t; 195 196 } // namespace blocking 197 namespace blocking_adaptation { 198 199 template <int I> struct allowed_t; 200 201 template <typename Executor, typename Function> 202 void blocking_execute( 203 BOOST_ASIO_MOVE_ARG(Executor) ex, 204 BOOST_ASIO_MOVE_ARG(Function) func); 205 206 } // namespace blocking_adaptation 207 208 template <int I = 0> 209 struct blocking_t 210 { 211 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 212 template <typename T> 213 BOOST_ASIO_STATIC_CONSTEXPR(bool, 214 is_applicable_property_v = ( 215 is_executor<T>::value 216 || conditional< 217 is_executor<T>::value, 218 false_type, 219 is_sender<T> 220 >::type::value 221 || conditional< 222 is_executor<T>::value, 223 false_type, 224 is_scheduler<T> 225 >::type::value)); 226 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 227 228 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); 229 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); 230 typedef blocking_t polymorphic_query_result_type; 231 232 typedef detail::blocking::possibly_t<I> possibly_t; 233 typedef detail::blocking::always_t<I> always_t; 234 typedef detail::blocking::never_t<I> never_t; 235 236 BOOST_ASIO_CONSTEXPR blocking_t() 237 : value_(-1) 238 { 239 } 240 241 BOOST_ASIO_CONSTEXPR blocking_t(possibly_t) 242 : value_(0) 243 { 244 } 245 246 BOOST_ASIO_CONSTEXPR blocking_t(always_t) 247 : value_(1) 248 { 249 } 250 251 BOOST_ASIO_CONSTEXPR blocking_t(never_t) 252 : value_(2) 253 { 254 } 255 256 template <typename T> 257 struct proxy 258 { 259 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 260 struct type 261 { 262 template <typename P> 263 auto query(BOOST_ASIO_MOVE_ARG(P) p) const 264 noexcept( 265 noexcept( 266 declval<typename conditional<true, T, P>::type>().query( 267 BOOST_ASIO_MOVE_CAST(P)(p)) 268 ) 269 ) 270 -> decltype( 271 declval<typename conditional<true, T, P>::type>().query( 272 BOOST_ASIO_MOVE_CAST(P)(p)) 273 ); 274 }; 275 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 276 typedef T type; 277 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 278 }; 279 280 template <typename T> 281 struct static_proxy 282 { 283 #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 284 struct type 285 { 286 template <typename P> 287 static constexpr auto query(BOOST_ASIO_MOVE_ARG(P) p) 288 noexcept( 289 noexcept( 290 conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p)) 291 ) 292 ) 293 -> decltype( 294 conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p)) 295 ) 296 { 297 return T::query(BOOST_ASIO_MOVE_CAST(P)(p)); 298 } 299 }; 300 #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 301 typedef T type; 302 #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 303 }; 304 305 template <typename T> 306 struct query_member : 307 traits::query_member<typename proxy<T>::type, blocking_t> {}; 308 309 template <typename T> 310 struct query_static_constexpr_member : 311 traits::query_static_constexpr_member< 312 typename static_proxy<T>::type, blocking_t> {}; 313 314 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 315 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 316 template <typename T> 317 static BOOST_ASIO_CONSTEXPR 318 typename query_static_constexpr_member<T>::result_type 319 static_query() 320 BOOST_ASIO_NOEXCEPT_IF(( 321 query_static_constexpr_member<T>::is_noexcept)) 322 { 323 return query_static_constexpr_member<T>::value(); 324 } 325 326 template <typename T> 327 static BOOST_ASIO_CONSTEXPR 328 typename traits::static_query<T, possibly_t>::result_type 329 static_query( 330 typename enable_if< 331 !query_static_constexpr_member<T>::is_valid 332 >::type* = 0, 333 typename enable_if< 334 !query_member<T>::is_valid 335 >::type* = 0, 336 typename enable_if< 337 traits::static_query<T, possibly_t>::is_valid 338 >::type* = 0) BOOST_ASIO_NOEXCEPT 339 { 340 return traits::static_query<T, possibly_t>::value(); 341 } 342 343 template <typename T> 344 static BOOST_ASIO_CONSTEXPR 345 typename traits::static_query<T, always_t>::result_type 346 static_query( 347 typename enable_if< 348 !query_static_constexpr_member<T>::is_valid 349 >::type* = 0, 350 typename enable_if< 351 !query_member<T>::is_valid 352 >::type* = 0, 353 typename enable_if< 354 !traits::static_query<T, possibly_t>::is_valid 355 >::type* = 0, 356 typename enable_if< 357 traits::static_query<T, always_t>::is_valid 358 >::type* = 0) BOOST_ASIO_NOEXCEPT 359 { 360 return traits::static_query<T, always_t>::value(); 361 } 362 363 template <typename T> 364 static BOOST_ASIO_CONSTEXPR 365 typename traits::static_query<T, never_t>::result_type 366 static_query( 367 typename enable_if< 368 !query_static_constexpr_member<T>::is_valid 369 >::type* = 0, 370 typename enable_if< 371 !query_member<T>::is_valid 372 >::type* = 0, 373 typename enable_if< 374 !traits::static_query<T, possibly_t>::is_valid 375 >::type* = 0, 376 typename enable_if< 377 !traits::static_query<T, always_t>::is_valid 378 >::type* = 0, 379 typename enable_if< 380 traits::static_query<T, never_t>::is_valid 381 >::type* = 0) BOOST_ASIO_NOEXCEPT 382 { 383 return traits::static_query<T, never_t>::value(); 384 } 385 386 template <typename E, typename T = decltype(blocking_t::static_query<E>())> 387 static BOOST_ASIO_CONSTEXPR const T static_query_v 388 = blocking_t::static_query<E>(); 389 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 390 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 391 392 friend BOOST_ASIO_CONSTEXPR bool operator==( 393 const blocking_t& a, const blocking_t& b) 394 { 395 return a.value_ == b.value_; 396 } 397 398 friend BOOST_ASIO_CONSTEXPR bool operator!=( 399 const blocking_t& a, const blocking_t& b) 400 { 401 return a.value_ != b.value_; 402 } 403 404 struct convertible_from_blocking_t 405 { 406 BOOST_ASIO_CONSTEXPR convertible_from_blocking_t(blocking_t) {} 407 }; 408 409 template <typename Executor> 410 friend BOOST_ASIO_CONSTEXPR blocking_t query( 411 const Executor& ex, convertible_from_blocking_t, 412 typename enable_if< 413 can_query<const Executor&, possibly_t>::value 414 >::type* = 0) 415 #if !defined(__clang__) // Clang crashes if noexcept is used here. 416 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. 417 BOOST_ASIO_NOEXCEPT_IF(( 418 is_nothrow_query<const Executor&, blocking_t<>::possibly_t>::value)) 419 #else // defined(BOOST_ASIO_MSVC) 420 BOOST_ASIO_NOEXCEPT_IF(( 421 is_nothrow_query<const Executor&, possibly_t>::value)) 422 #endif // defined(BOOST_ASIO_MSVC) 423 #endif // !defined(__clang__) 424 { 425 return boost::asio::query(ex, possibly_t()); 426 } 427 428 template <typename Executor> 429 friend BOOST_ASIO_CONSTEXPR blocking_t query( 430 const Executor& ex, convertible_from_blocking_t, 431 typename enable_if< 432 !can_query<const Executor&, possibly_t>::value 433 >::type* = 0, 434 typename enable_if< 435 can_query<const Executor&, always_t>::value 436 >::type* = 0) 437 #if !defined(__clang__) // Clang crashes if noexcept is used here. 438 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. 439 BOOST_ASIO_NOEXCEPT_IF(( 440 is_nothrow_query<const Executor&, blocking_t<>::always_t>::value)) 441 #else // defined(BOOST_ASIO_MSVC) 442 BOOST_ASIO_NOEXCEPT_IF(( 443 is_nothrow_query<const Executor&, always_t>::value)) 444 #endif // defined(BOOST_ASIO_MSVC) 445 #endif // !defined(__clang__) 446 { 447 return boost::asio::query(ex, always_t()); 448 } 449 450 template <typename Executor> 451 friend BOOST_ASIO_CONSTEXPR blocking_t query( 452 const Executor& ex, convertible_from_blocking_t, 453 typename enable_if< 454 !can_query<const Executor&, possibly_t>::value 455 >::type* = 0, 456 typename enable_if< 457 !can_query<const Executor&, always_t>::value 458 >::type* = 0, 459 typename enable_if< 460 can_query<const Executor&, never_t>::value 461 >::type* = 0) 462 #if !defined(__clang__) // Clang crashes if noexcept is used here. 463 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. 464 BOOST_ASIO_NOEXCEPT_IF(( 465 is_nothrow_query<const Executor&, blocking_t<>::never_t>::value)) 466 #else // defined(BOOST_ASIO_MSVC) 467 BOOST_ASIO_NOEXCEPT_IF(( 468 is_nothrow_query<const Executor&, never_t>::value)) 469 #endif // defined(BOOST_ASIO_MSVC) 470 #endif // !defined(__clang__) 471 { 472 return boost::asio::query(ex, never_t()); 473 } 474 475 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(possibly_t, possibly); 476 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(always_t, always); 477 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(never_t, never); 478 479 #if !defined(BOOST_ASIO_HAS_CONSTEXPR) 480 static const blocking_t instance; 481 #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR) 482 483 private: 484 int value_; 485 }; 486 487 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 488 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 489 template <int I> template <typename E, typename T> 490 const T blocking_t<I>::static_query_v; 491 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 492 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 493 494 #if !defined(BOOST_ASIO_HAS_CONSTEXPR) 495 template <int I> 496 const blocking_t<I> blocking_t<I>::instance; 497 #endif 498 499 template <int I> 500 const typename blocking_t<I>::possibly_t blocking_t<I>::possibly; 501 502 template <int I> 503 const typename blocking_t<I>::always_t blocking_t<I>::always; 504 505 template <int I> 506 const typename blocking_t<I>::never_t blocking_t<I>::never; 507 508 namespace blocking { 509 510 template <int I = 0> 511 struct possibly_t 512 { 513 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 514 template <typename T> 515 BOOST_ASIO_STATIC_CONSTEXPR(bool, 516 is_applicable_property_v = ( 517 is_executor<T>::value 518 || conditional< 519 is_executor<T>::value, 520 false_type, 521 is_sender<T> 522 >::type::value 523 || conditional< 524 is_executor<T>::value, 525 false_type, 526 is_scheduler<T> 527 >::type::value)); 528 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 529 530 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); 531 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); 532 typedef blocking_t<I> polymorphic_query_result_type; 533 534 BOOST_ASIO_CONSTEXPR possibly_t() 535 { 536 } 537 538 template <typename T> 539 struct query_member : 540 traits::query_member< 541 typename blocking_t<I>::template proxy<T>::type, possibly_t> {}; 542 543 template <typename T> 544 struct query_static_constexpr_member : 545 traits::query_static_constexpr_member< 546 typename blocking_t<I>::template static_proxy<T>::type, possibly_t> {}; 547 548 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 549 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 550 template <typename T> 551 static BOOST_ASIO_CONSTEXPR 552 typename query_static_constexpr_member<T>::result_type 553 static_query() 554 BOOST_ASIO_NOEXCEPT_IF(( 555 query_static_constexpr_member<T>::is_noexcept)) 556 { 557 return query_static_constexpr_member<T>::value(); 558 } 559 560 template <typename T> 561 static BOOST_ASIO_CONSTEXPR possibly_t static_query( 562 typename enable_if< 563 !query_static_constexpr_member<T>::is_valid 564 >::type* = 0, 565 typename enable_if< 566 !query_member<T>::is_valid 567 >::type* = 0, 568 typename enable_if< 569 !traits::query_free<T, possibly_t>::is_valid 570 >::type* = 0, 571 typename enable_if< 572 !can_query<T, always_t<I> >::value 573 >::type* = 0, 574 typename enable_if< 575 !can_query<T, never_t<I> >::value 576 >::type* = 0) BOOST_ASIO_NOEXCEPT 577 { 578 return possibly_t(); 579 } 580 581 template <typename E, typename T = decltype(possibly_t::static_query<E>())> 582 static BOOST_ASIO_CONSTEXPR const T static_query_v 583 = possibly_t::static_query<E>(); 584 #endif // defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 585 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 586 587 static BOOST_ASIO_CONSTEXPR blocking_t<I> value() 588 { 589 return possibly_t(); 590 } 591 592 friend BOOST_ASIO_CONSTEXPR bool operator==( 593 const possibly_t&, const possibly_t&) 594 { 595 return true; 596 } 597 598 friend BOOST_ASIO_CONSTEXPR bool operator!=( 599 const possibly_t&, const possibly_t&) 600 { 601 return false; 602 } 603 604 friend BOOST_ASIO_CONSTEXPR bool operator==( 605 const possibly_t&, const always_t<I>&) 606 { 607 return false; 608 } 609 610 friend BOOST_ASIO_CONSTEXPR bool operator!=( 611 const possibly_t&, const always_t<I>&) 612 { 613 return true; 614 } 615 616 friend BOOST_ASIO_CONSTEXPR bool operator==( 617 const possibly_t&, const never_t<I>&) 618 { 619 return false; 620 } 621 622 friend BOOST_ASIO_CONSTEXPR bool operator!=( 623 const possibly_t&, const never_t<I>&) 624 { 625 return true; 626 } 627 }; 628 629 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 630 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 631 template <int I> template <typename E, typename T> 632 const T possibly_t<I>::static_query_v; 633 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 634 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 635 636 template <typename Executor> 637 class adapter 638 { 639 public: 640 adapter(int, const Executor& e) BOOST_ASIO_NOEXCEPT 641 : executor_(e) 642 { 643 } 644 645 adapter(const adapter& other) BOOST_ASIO_NOEXCEPT 646 : executor_(other.executor_) 647 { 648 } 649 650 #if defined(BOOST_ASIO_HAS_MOVE) 651 adapter(adapter&& other) BOOST_ASIO_NOEXCEPT 652 : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_)) 653 { 654 } 655 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 656 657 template <int I> 658 static BOOST_ASIO_CONSTEXPR always_t<I> query( 659 blocking_t<I>) BOOST_ASIO_NOEXCEPT 660 { 661 return always_t<I>(); 662 } 663 664 template <int I> 665 static BOOST_ASIO_CONSTEXPR always_t<I> query( 666 possibly_t<I>) BOOST_ASIO_NOEXCEPT 667 { 668 return always_t<I>(); 669 } 670 671 template <int I> 672 static BOOST_ASIO_CONSTEXPR always_t<I> query( 673 always_t<I>) BOOST_ASIO_NOEXCEPT 674 { 675 return always_t<I>(); 676 } 677 678 template <int I> 679 static BOOST_ASIO_CONSTEXPR always_t<I> query( 680 never_t<I>) BOOST_ASIO_NOEXCEPT 681 { 682 return always_t<I>(); 683 } 684 685 template <typename Property> 686 typename enable_if< 687 can_query<const Executor&, Property>::value, 688 typename query_result<const Executor&, Property>::type 689 >::type query(const Property& p) const 690 BOOST_ASIO_NOEXCEPT_IF(( 691 is_nothrow_query<const Executor&, Property>::value)) 692 { 693 return boost::asio::query(executor_, p); 694 } 695 696 template <int I> 697 typename enable_if< 698 can_require<const Executor&, possibly_t<I> >::value, 699 typename require_result<const Executor&, possibly_t<I> >::type 700 >::type require(possibly_t<I>) const BOOST_ASIO_NOEXCEPT 701 { 702 return boost::asio::require(executor_, possibly_t<I>()); 703 } 704 705 template <int I> 706 typename enable_if< 707 can_require<const Executor&, never_t<I> >::value, 708 typename require_result<const Executor&, never_t<I> >::type 709 >::type require(never_t<I>) const BOOST_ASIO_NOEXCEPT 710 { 711 return boost::asio::require(executor_, never_t<I>()); 712 } 713 714 template <typename Property> 715 typename enable_if< 716 can_require<const Executor&, Property>::value, 717 adapter<typename decay< 718 typename require_result<const Executor&, Property>::type 719 >::type> 720 >::type require(const Property& p) const 721 BOOST_ASIO_NOEXCEPT_IF(( 722 is_nothrow_require<const Executor&, Property>::value)) 723 { 724 return adapter<typename decay< 725 typename require_result<const Executor&, Property>::type 726 >::type>(0, boost::asio::require(executor_, p)); 727 } 728 729 template <typename Property> 730 typename enable_if< 731 can_prefer<const Executor&, Property>::value, 732 adapter<typename decay< 733 typename prefer_result<const Executor&, Property>::type 734 >::type> 735 >::type prefer(const Property& p) const 736 BOOST_ASIO_NOEXCEPT_IF(( 737 is_nothrow_prefer<const Executor&, Property>::value)) 738 { 739 return adapter<typename decay< 740 typename prefer_result<const Executor&, Property>::type 741 >::type>(0, boost::asio::prefer(executor_, p)); 742 } 743 744 template <typename Function> 745 typename enable_if< 746 execution::can_execute<const Executor&, Function>::value 747 >::type execute(BOOST_ASIO_MOVE_ARG(Function) f) const 748 { 749 blocking_adaptation::blocking_execute( 750 executor_, BOOST_ASIO_MOVE_CAST(Function)(f)); 751 } 752 753 friend bool operator==(const adapter& a, const adapter& b) BOOST_ASIO_NOEXCEPT 754 { 755 return a.executor_ == b.executor_; 756 } 757 758 friend bool operator!=(const adapter& a, const adapter& b) BOOST_ASIO_NOEXCEPT 759 { 760 return a.executor_ != b.executor_; 761 } 762 763 private: 764 Executor executor_; 765 }; 766 767 template <int I = 0> 768 struct always_t 769 { 770 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 771 template <typename T> 772 BOOST_ASIO_STATIC_CONSTEXPR(bool, 773 is_applicable_property_v = ( 774 is_executor<T>::value 775 || conditional< 776 is_executor<T>::value, 777 false_type, 778 is_sender<T> 779 >::type::value 780 || conditional< 781 is_executor<T>::value, 782 false_type, 783 is_scheduler<T> 784 >::type::value)); 785 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 786 787 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); 788 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); 789 typedef blocking_t<I> polymorphic_query_result_type; 790 791 BOOST_ASIO_CONSTEXPR always_t() 792 { 793 } 794 795 template <typename T> 796 struct query_member : 797 traits::query_member< 798 typename blocking_t<I>::template proxy<T>::type, always_t> {}; 799 800 template <typename T> 801 struct query_static_constexpr_member : 802 traits::query_static_constexpr_member< 803 typename blocking_t<I>::template static_proxy<T>::type, always_t> {}; 804 805 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 806 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 807 template <typename T> 808 static BOOST_ASIO_CONSTEXPR 809 typename query_static_constexpr_member<T>::result_type 810 static_query() 811 BOOST_ASIO_NOEXCEPT_IF(( 812 query_static_constexpr_member<T>::is_noexcept)) 813 { 814 return query_static_constexpr_member<T>::value(); 815 } 816 817 template <typename E, typename T = decltype(always_t::static_query<E>())> 818 static BOOST_ASIO_CONSTEXPR const T static_query_v 819 = always_t::static_query<E>(); 820 #endif // defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 821 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 822 823 static BOOST_ASIO_CONSTEXPR blocking_t<I> value() 824 { 825 return always_t(); 826 } 827 828 friend BOOST_ASIO_CONSTEXPR bool operator==( 829 const always_t&, const always_t&) 830 { 831 return true; 832 } 833 834 friend BOOST_ASIO_CONSTEXPR bool operator!=( 835 const always_t&, const always_t&) 836 { 837 return false; 838 } 839 840 friend BOOST_ASIO_CONSTEXPR bool operator==( 841 const always_t&, const possibly_t<I>&) 842 { 843 return false; 844 } 845 846 friend BOOST_ASIO_CONSTEXPR bool operator!=( 847 const always_t&, const possibly_t<I>&) 848 { 849 return true; 850 } 851 852 friend BOOST_ASIO_CONSTEXPR bool operator==( 853 const always_t&, const never_t<I>&) 854 { 855 return false; 856 } 857 858 friend BOOST_ASIO_CONSTEXPR bool operator!=( 859 const always_t&, const never_t<I>&) 860 { 861 return true; 862 } 863 864 template <typename Executor> 865 friend adapter<Executor> require( 866 const Executor& e, const always_t&, 867 typename enable_if< 868 is_executor<Executor>::value 869 >::type* = 0, 870 typename enable_if< 871 traits::static_require< 872 const Executor&, 873 blocking_adaptation::allowed_t<0> 874 >::is_valid 875 >::type* = 0) 876 { 877 return adapter<Executor>(0, e); 878 } 879 }; 880 881 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 882 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 883 template <int I> template <typename E, typename T> 884 const T always_t<I>::static_query_v; 885 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 886 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 887 888 template <int I> 889 struct never_t 890 { 891 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 892 template <typename T> 893 BOOST_ASIO_STATIC_CONSTEXPR(bool, 894 is_applicable_property_v = ( 895 is_executor<T>::value 896 || conditional< 897 is_executor<T>::value, 898 false_type, 899 is_sender<T> 900 >::type::value 901 || conditional< 902 is_executor<T>::value, 903 false_type, 904 is_scheduler<T> 905 >::type::value)); 906 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 907 908 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); 909 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); 910 typedef blocking_t<I> polymorphic_query_result_type; 911 912 BOOST_ASIO_CONSTEXPR never_t() 913 { 914 } 915 916 template <typename T> 917 struct query_member : 918 traits::query_member< 919 typename blocking_t<I>::template proxy<T>::type, never_t> {}; 920 921 template <typename T> 922 struct query_static_constexpr_member : 923 traits::query_static_constexpr_member< 924 typename blocking_t<I>::template static_proxy<T>::type, never_t> {}; 925 926 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 927 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 928 template <typename T> 929 static BOOST_ASIO_CONSTEXPR 930 typename query_static_constexpr_member<T>::result_type 931 static_query() 932 BOOST_ASIO_NOEXCEPT_IF(( 933 query_static_constexpr_member<T>::is_noexcept)) 934 { 935 return query_static_constexpr_member<T>::value(); 936 } 937 938 template <typename E, typename T = decltype(never_t::static_query<E>())> 939 static BOOST_ASIO_CONSTEXPR const T static_query_v 940 = never_t::static_query<E>(); 941 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 942 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 943 944 static BOOST_ASIO_CONSTEXPR blocking_t<I> value() 945 { 946 return never_t(); 947 } 948 949 friend BOOST_ASIO_CONSTEXPR bool operator==( 950 const never_t&, const never_t&) 951 { 952 return true; 953 } 954 955 friend BOOST_ASIO_CONSTEXPR bool operator!=( 956 const never_t&, const never_t&) 957 { 958 return false; 959 } 960 961 friend BOOST_ASIO_CONSTEXPR bool operator==( 962 const never_t&, const possibly_t<I>&) 963 { 964 return false; 965 } 966 967 friend BOOST_ASIO_CONSTEXPR bool operator!=( 968 const never_t&, const possibly_t<I>&) 969 { 970 return true; 971 } 972 973 friend BOOST_ASIO_CONSTEXPR bool operator==( 974 const never_t&, const always_t<I>&) 975 { 976 return false; 977 } 978 979 friend BOOST_ASIO_CONSTEXPR bool operator!=( 980 const never_t&, const always_t<I>&) 981 { 982 return true; 983 } 984 }; 985 986 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 987 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 988 template <int I> template <typename E, typename T> 989 const T never_t<I>::static_query_v; 990 #endif // defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 991 992 } // namespace blocking 993 } // namespace detail 994 995 typedef detail::blocking_t<> blocking_t; 996 997 #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) 998 constexpr blocking_t blocking; 999 #else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) 1000 namespace { static const blocking_t& blocking = blocking_t::instance; } 1001 #endif 1002 1003 } // namespace execution 1004 1005 #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 1006 1007 template <typename T> 1008 struct is_applicable_property<T, execution::blocking_t> 1009 : integral_constant<bool, 1010 execution::is_executor<T>::value 1011 || conditional< 1012 execution::is_executor<T>::value, 1013 false_type, 1014 execution::is_sender<T> 1015 >::type::value 1016 || conditional< 1017 execution::is_executor<T>::value, 1018 false_type, 1019 execution::is_scheduler<T> 1020 >::type::value> 1021 { 1022 }; 1023 1024 template <typename T> 1025 struct is_applicable_property<T, execution::blocking_t::possibly_t> 1026 : integral_constant<bool, 1027 execution::is_executor<T>::value 1028 || conditional< 1029 execution::is_executor<T>::value, 1030 false_type, 1031 execution::is_sender<T> 1032 >::type::value 1033 || conditional< 1034 execution::is_executor<T>::value, 1035 false_type, 1036 execution::is_scheduler<T> 1037 >::type::value> 1038 { 1039 }; 1040 1041 template <typename T> 1042 struct is_applicable_property<T, execution::blocking_t::always_t> 1043 : integral_constant<bool, 1044 execution::is_executor<T>::value 1045 || conditional< 1046 execution::is_executor<T>::value, 1047 false_type, 1048 execution::is_sender<T> 1049 >::type::value 1050 || conditional< 1051 execution::is_executor<T>::value, 1052 false_type, 1053 execution::is_scheduler<T> 1054 >::type::value> 1055 { 1056 }; 1057 1058 template <typename T> 1059 struct is_applicable_property<T, execution::blocking_t::never_t> 1060 : integral_constant<bool, 1061 execution::is_executor<T>::value 1062 || conditional< 1063 execution::is_executor<T>::value, 1064 false_type, 1065 execution::is_sender<T> 1066 >::type::value 1067 || conditional< 1068 execution::is_executor<T>::value, 1069 false_type, 1070 execution::is_scheduler<T> 1071 >::type::value> 1072 { 1073 }; 1074 1075 #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 1076 1077 namespace traits { 1078 1079 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) 1080 1081 template <typename T> 1082 struct query_free_default<T, execution::blocking_t, 1083 typename enable_if< 1084 can_query<T, execution::blocking_t::possibly_t>::value 1085 >::type> 1086 { 1087 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1088 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1089 (is_nothrow_query<T, execution::blocking_t::possibly_t>::value)); 1090 1091 typedef execution::blocking_t result_type; 1092 }; 1093 1094 template <typename T> 1095 struct query_free_default<T, execution::blocking_t, 1096 typename enable_if< 1097 !can_query<T, execution::blocking_t::possibly_t>::value 1098 && can_query<T, execution::blocking_t::always_t>::value 1099 >::type> 1100 { 1101 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1102 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1103 (is_nothrow_query<T, execution::blocking_t::always_t>::value)); 1104 1105 typedef execution::blocking_t result_type; 1106 }; 1107 1108 template <typename T> 1109 struct query_free_default<T, execution::blocking_t, 1110 typename enable_if< 1111 !can_query<T, execution::blocking_t::possibly_t>::value 1112 && !can_query<T, execution::blocking_t::always_t>::value 1113 && can_query<T, execution::blocking_t::never_t>::value 1114 >::type> 1115 { 1116 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1117 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1118 (is_nothrow_query<T, execution::blocking_t::never_t>::value)); 1119 1120 typedef execution::blocking_t result_type; 1121 }; 1122 1123 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) 1124 1125 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 1126 || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 1127 1128 template <typename T> 1129 struct static_query<T, execution::blocking_t, 1130 typename enable_if< 1131 execution::detail::blocking_t<0>:: 1132 query_static_constexpr_member<T>::is_valid 1133 >::type> 1134 { 1135 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1136 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1137 1138 typedef typename execution::detail::blocking_t<0>:: 1139 query_static_constexpr_member<T>::result_type result_type; 1140 1141 static BOOST_ASIO_CONSTEXPR result_type value() 1142 { 1143 return execution::blocking_t::query_static_constexpr_member<T>::value(); 1144 } 1145 }; 1146 1147 template <typename T> 1148 struct static_query<T, execution::blocking_t, 1149 typename enable_if< 1150 !execution::detail::blocking_t<0>:: 1151 query_static_constexpr_member<T>::is_valid 1152 && !execution::detail::blocking_t<0>:: 1153 query_member<T>::is_valid 1154 && traits::static_query<T, execution::blocking_t::possibly_t>::is_valid 1155 >::type> 1156 { 1157 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1158 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1159 1160 typedef typename traits::static_query<T, 1161 execution::blocking_t::possibly_t>::result_type result_type; 1162 1163 static BOOST_ASIO_CONSTEXPR result_type value() 1164 { 1165 return traits::static_query<T, execution::blocking_t::possibly_t>::value(); 1166 } 1167 }; 1168 1169 template <typename T> 1170 struct static_query<T, execution::blocking_t, 1171 typename enable_if< 1172 !execution::detail::blocking_t<0>:: 1173 query_static_constexpr_member<T>::is_valid 1174 && !execution::detail::blocking_t<0>:: 1175 query_member<T>::is_valid 1176 && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid 1177 && traits::static_query<T, execution::blocking_t::always_t>::is_valid 1178 >::type> 1179 { 1180 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1181 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1182 1183 typedef typename traits::static_query<T, 1184 execution::blocking_t::always_t>::result_type result_type; 1185 1186 static BOOST_ASIO_CONSTEXPR result_type value() 1187 { 1188 return traits::static_query<T, execution::blocking_t::always_t>::value(); 1189 } 1190 }; 1191 1192 template <typename T> 1193 struct static_query<T, execution::blocking_t, 1194 typename enable_if< 1195 !execution::detail::blocking_t<0>:: 1196 query_static_constexpr_member<T>::is_valid 1197 && !execution::detail::blocking_t<0>:: 1198 query_member<T>::is_valid 1199 && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid 1200 && !traits::static_query<T, execution::blocking_t::always_t>::is_valid 1201 && traits::static_query<T, execution::blocking_t::never_t>::is_valid 1202 >::type> 1203 { 1204 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1205 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1206 1207 typedef typename traits::static_query<T, 1208 execution::blocking_t::never_t>::result_type result_type; 1209 1210 static BOOST_ASIO_CONSTEXPR result_type value() 1211 { 1212 return traits::static_query<T, execution::blocking_t::never_t>::value(); 1213 } 1214 }; 1215 1216 template <typename T> 1217 struct static_query<T, execution::blocking_t::possibly_t, 1218 typename enable_if< 1219 execution::detail::blocking::possibly_t<0>:: 1220 query_static_constexpr_member<T>::is_valid 1221 >::type> 1222 { 1223 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1224 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1225 1226 typedef typename execution::detail::blocking::possibly_t<0>:: 1227 query_static_constexpr_member<T>::result_type result_type; 1228 1229 static BOOST_ASIO_CONSTEXPR result_type value() 1230 { 1231 return execution::detail::blocking::possibly_t<0>:: 1232 query_static_constexpr_member<T>::value(); 1233 } 1234 }; 1235 1236 template <typename T> 1237 struct static_query<T, execution::blocking_t::possibly_t, 1238 typename enable_if< 1239 !execution::detail::blocking::possibly_t<0>:: 1240 query_static_constexpr_member<T>::is_valid 1241 && !execution::detail::blocking::possibly_t<0>:: 1242 query_member<T>::is_valid 1243 && !traits::query_free<T, execution::blocking_t::possibly_t>::is_valid 1244 && !can_query<T, execution::blocking_t::always_t>::value 1245 && !can_query<T, execution::blocking_t::never_t>::value 1246 >::type> 1247 { 1248 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1249 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1250 1251 typedef execution::blocking_t::possibly_t result_type; 1252 1253 static BOOST_ASIO_CONSTEXPR result_type value() 1254 { 1255 return result_type(); 1256 } 1257 }; 1258 1259 template <typename T> 1260 struct static_query<T, execution::blocking_t::always_t, 1261 typename enable_if< 1262 execution::detail::blocking::always_t<0>:: 1263 query_static_constexpr_member<T>::is_valid 1264 >::type> 1265 { 1266 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1267 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1268 1269 typedef typename execution::detail::blocking::always_t<0>:: 1270 query_static_constexpr_member<T>::result_type result_type; 1271 1272 static BOOST_ASIO_CONSTEXPR result_type value() 1273 { 1274 return execution::detail::blocking::always_t<0>:: 1275 query_static_constexpr_member<T>::value(); 1276 } 1277 }; 1278 1279 template <typename T> 1280 struct static_query<T, execution::blocking_t::never_t, 1281 typename enable_if< 1282 execution::detail::blocking::never_t<0>:: 1283 query_static_constexpr_member<T>::is_valid 1284 >::type> 1285 { 1286 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1287 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1288 1289 typedef typename execution::detail::blocking::never_t<0>:: 1290 query_static_constexpr_member<T>::result_type result_type; 1291 1292 static BOOST_ASIO_CONSTEXPR result_type value() 1293 { 1294 return execution::detail::blocking::never_t<0>:: 1295 query_static_constexpr_member<T>::value(); 1296 } 1297 }; 1298 1299 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 1300 // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 1301 1302 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) 1303 1304 template <typename T> 1305 struct static_require<T, execution::blocking_t::possibly_t, 1306 typename enable_if< 1307 static_query<T, execution::blocking_t::possibly_t>::is_valid 1308 >::type> 1309 { 1310 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = 1311 (is_same<typename static_query<T, 1312 execution::blocking_t::possibly_t>::result_type, 1313 execution::blocking_t::possibly_t>::value)); 1314 }; 1315 1316 template <typename T> 1317 struct static_require<T, execution::blocking_t::always_t, 1318 typename enable_if< 1319 static_query<T, execution::blocking_t::always_t>::is_valid 1320 >::type> 1321 { 1322 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = 1323 (is_same<typename static_query<T, 1324 execution::blocking_t::always_t>::result_type, 1325 execution::blocking_t::always_t>::value)); 1326 }; 1327 1328 template <typename T> 1329 struct static_require<T, execution::blocking_t::never_t, 1330 typename enable_if< 1331 static_query<T, execution::blocking_t::never_t>::is_valid 1332 >::type> 1333 { 1334 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = 1335 (is_same<typename static_query<T, 1336 execution::blocking_t::never_t>::result_type, 1337 execution::blocking_t::never_t>::value)); 1338 }; 1339 1340 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) 1341 1342 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) 1343 1344 template <typename T> 1345 struct require_free_default<T, execution::blocking_t::always_t, 1346 typename enable_if< 1347 is_same<T, typename decay<T>::type>::value 1348 && execution::is_executor<T>::value 1349 && traits::static_require< 1350 const T&, 1351 execution::detail::blocking_adaptation::allowed_t<0> 1352 >::is_valid 1353 >::type> 1354 { 1355 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1356 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 1357 typedef execution::detail::blocking::adapter<T> result_type; 1358 }; 1359 1360 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) 1361 1362 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 1363 1364 template <typename Executor> 1365 struct equality_comparable< 1366 execution::detail::blocking::adapter<Executor> > 1367 { 1368 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1369 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1370 }; 1371 1372 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 1373 1374 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 1375 1376 template <typename Executor, typename Function> 1377 struct execute_member< 1378 execution::detail::blocking::adapter<Executor>, Function> 1379 { 1380 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1381 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 1382 typedef void result_type; 1383 }; 1384 1385 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 1386 1387 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 1388 1389 template <typename Executor, int I> 1390 struct query_static_constexpr_member< 1391 execution::detail::blocking::adapter<Executor>, 1392 execution::detail::blocking_t<I> > 1393 { 1394 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1395 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1396 typedef execution::blocking_t::always_t result_type; 1397 1398 static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT 1399 { 1400 return result_type(); 1401 } 1402 }; 1403 1404 template <typename Executor, int I> 1405 struct query_static_constexpr_member< 1406 execution::detail::blocking::adapter<Executor>, 1407 execution::detail::blocking::always_t<I> > 1408 { 1409 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1410 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1411 typedef execution::blocking_t::always_t result_type; 1412 1413 static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT 1414 { 1415 return result_type(); 1416 } 1417 }; 1418 1419 template <typename Executor, int I> 1420 struct query_static_constexpr_member< 1421 execution::detail::blocking::adapter<Executor>, 1422 execution::detail::blocking::possibly_t<I> > 1423 { 1424 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1425 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1426 typedef execution::blocking_t::always_t result_type; 1427 1428 static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT 1429 { 1430 return result_type(); 1431 } 1432 }; 1433 1434 template <typename Executor, int I> 1435 struct query_static_constexpr_member< 1436 execution::detail::blocking::adapter<Executor>, 1437 execution::detail::blocking::never_t<I> > 1438 { 1439 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1440 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1441 typedef execution::blocking_t::always_t result_type; 1442 1443 static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT 1444 { 1445 return result_type(); 1446 } 1447 }; 1448 1449 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 1450 1451 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 1452 1453 template <typename Executor, typename Property> 1454 struct query_member< 1455 execution::detail::blocking::adapter<Executor>, Property, 1456 typename enable_if< 1457 can_query<const Executor&, Property>::value 1458 >::type> 1459 { 1460 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1461 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1462 (is_nothrow_query<Executor, Property>::value)); 1463 typedef typename query_result<Executor, Property>::type result_type; 1464 }; 1465 1466 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 1467 1468 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 1469 1470 template <typename Executor, int I> 1471 struct require_member< 1472 execution::detail::blocking::adapter<Executor>, 1473 execution::detail::blocking::possibly_t<I>, 1474 typename enable_if< 1475 can_require< 1476 const Executor&, 1477 execution::detail::blocking::possibly_t<I> 1478 >::value 1479 >::type> 1480 { 1481 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1482 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1483 (is_nothrow_require<const Executor&, 1484 execution::detail::blocking::possibly_t<I> >::value)); 1485 typedef typename require_result<const Executor&, 1486 execution::detail::blocking::possibly_t<I> >::type result_type; 1487 }; 1488 1489 template <typename Executor, int I> 1490 struct require_member< 1491 execution::detail::blocking::adapter<Executor>, 1492 execution::detail::blocking::never_t<I>, 1493 typename enable_if< 1494 can_require< 1495 const Executor&, 1496 execution::detail::blocking::never_t<I> 1497 >::value 1498 >::type> 1499 { 1500 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1501 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1502 (is_nothrow_require<const Executor&, 1503 execution::detail::blocking::never_t<I> >::value)); 1504 typedef typename require_result<const Executor&, 1505 execution::detail::blocking::never_t<I> >::type result_type; 1506 }; 1507 1508 template <typename Executor, typename Property> 1509 struct require_member< 1510 execution::detail::blocking::adapter<Executor>, Property, 1511 typename enable_if< 1512 can_require<const Executor&, Property>::value 1513 >::type> 1514 { 1515 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1516 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1517 (is_nothrow_require<Executor, Property>::value)); 1518 typedef execution::detail::blocking::adapter<typename decay< 1519 typename require_result<Executor, Property>::type 1520 >::type> result_type; 1521 }; 1522 1523 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 1524 1525 #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) 1526 1527 template <typename Executor, typename Property> 1528 struct prefer_member< 1529 execution::detail::blocking::adapter<Executor>, Property, 1530 typename enable_if< 1531 can_prefer<const Executor&, Property>::value 1532 >::type> 1533 { 1534 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1535 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1536 (is_nothrow_prefer<Executor, Property>::value)); 1537 typedef execution::detail::blocking::adapter<typename decay< 1538 typename prefer_result<Executor, Property>::type 1539 >::type> result_type; 1540 }; 1541 1542 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) 1543 1544 } // namespace traits 1545 1546 #endif // defined(GENERATING_DOCUMENTATION) 1547 1548 } // namespace asio 1549 } // namespace boost 1550 1551 #include <boost/asio/detail/pop_options.hpp> 1552 1553 #endif // BOOST_ASIO_EXECUTION_BLOCKING_HPP 1554