1 // 2 // execution/blocking.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef BOOST_ASIO_EXECUTION_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 = is_executor<T>::value 215 || is_sender<T>::value || is_scheduler<T>::value); 216 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 217 218 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); 219 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); 220 typedef blocking_t polymorphic_query_result_type; 221 222 typedef detail::blocking::possibly_t<I> possibly_t; 223 typedef detail::blocking::always_t<I> always_t; 224 typedef detail::blocking::never_t<I> never_t; 225 226 BOOST_ASIO_CONSTEXPR blocking_t() 227 : value_(-1) 228 { 229 } 230 231 BOOST_ASIO_CONSTEXPR blocking_t(possibly_t) 232 : value_(0) 233 { 234 } 235 236 BOOST_ASIO_CONSTEXPR blocking_t(always_t) 237 : value_(1) 238 { 239 } 240 241 BOOST_ASIO_CONSTEXPR blocking_t(never_t) 242 : value_(2) 243 { 244 } 245 246 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 247 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 248 template <typename T> 249 static BOOST_ASIO_CONSTEXPR 250 typename traits::query_static_constexpr_member<T, blocking_t>::result_type 251 static_query() 252 BOOST_ASIO_NOEXCEPT_IF(( 253 traits::query_static_constexpr_member<T, blocking_t>::is_noexcept)) 254 { 255 return traits::query_static_constexpr_member<T, blocking_t>::value(); 256 } 257 258 template <typename T> 259 static BOOST_ASIO_CONSTEXPR 260 typename traits::static_query<T, possibly_t>::result_type 261 static_query( 262 typename enable_if< 263 !traits::query_static_constexpr_member<T, blocking_t>::is_valid 264 && !traits::query_member<T, blocking_t>::is_valid 265 && traits::static_query<T, possibly_t>::is_valid 266 >::type* = 0) BOOST_ASIO_NOEXCEPT 267 { 268 return traits::static_query<T, possibly_t>::value(); 269 } 270 271 template <typename T> 272 static BOOST_ASIO_CONSTEXPR 273 typename traits::static_query<T, always_t>::result_type 274 static_query( 275 typename enable_if< 276 !traits::query_static_constexpr_member<T, blocking_t>::is_valid 277 && !traits::query_member<T, blocking_t>::is_valid 278 && !traits::static_query<T, possibly_t>::is_valid 279 && traits::static_query<T, always_t>::is_valid 280 >::type* = 0) BOOST_ASIO_NOEXCEPT 281 { 282 return traits::static_query<T, always_t>::value(); 283 } 284 285 template <typename T> 286 static BOOST_ASIO_CONSTEXPR 287 typename traits::static_query<T, never_t>::result_type 288 static_query( 289 typename enable_if< 290 !traits::query_static_constexpr_member<T, blocking_t>::is_valid 291 && !traits::query_member<T, blocking_t>::is_valid 292 && !traits::static_query<T, possibly_t>::is_valid 293 && !traits::static_query<T, always_t>::is_valid 294 && traits::static_query<T, never_t>::is_valid 295 >::type* = 0) BOOST_ASIO_NOEXCEPT 296 { 297 return traits::static_query<T, never_t>::value(); 298 } 299 300 template <typename E, typename T = decltype(blocking_t::static_query<E>())> 301 static BOOST_ASIO_CONSTEXPR const T static_query_v 302 = blocking_t::static_query<E>(); 303 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 304 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 305 306 friend BOOST_ASIO_CONSTEXPR bool operator==( 307 const blocking_t& a, const blocking_t& b) 308 { 309 return a.value_ == b.value_; 310 } 311 312 friend BOOST_ASIO_CONSTEXPR bool operator!=( 313 const blocking_t& a, const blocking_t& b) 314 { 315 return a.value_ != b.value_; 316 } 317 318 struct convertible_from_blocking_t 319 { 320 BOOST_ASIO_CONSTEXPR convertible_from_blocking_t(blocking_t) {} 321 }; 322 323 template <typename Executor> 324 friend BOOST_ASIO_CONSTEXPR blocking_t query( 325 const Executor& ex, convertible_from_blocking_t, 326 typename enable_if< 327 can_query<const Executor&, possibly_t>::value 328 >::type* = 0) 329 #if !defined(__clang__) // Clang crashes if noexcept is used here. 330 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. 331 BOOST_ASIO_NOEXCEPT_IF(( 332 is_nothrow_query<const Executor&, blocking_t<>::possibly_t>::value)) 333 #else // defined(BOOST_ASIO_MSVC) 334 BOOST_ASIO_NOEXCEPT_IF(( 335 is_nothrow_query<const Executor&, possibly_t>::value)) 336 #endif // defined(BOOST_ASIO_MSVC) 337 #endif // !defined(__clang__) 338 { 339 return boost::asio::query(ex, possibly_t()); 340 } 341 342 template <typename Executor> 343 friend BOOST_ASIO_CONSTEXPR blocking_t query( 344 const Executor& ex, convertible_from_blocking_t, 345 typename enable_if< 346 !can_query<const Executor&, possibly_t>::value 347 && can_query<const Executor&, always_t>::value 348 >::type* = 0) 349 #if !defined(__clang__) // Clang crashes if noexcept is used here. 350 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. 351 BOOST_ASIO_NOEXCEPT_IF(( 352 is_nothrow_query<const Executor&, blocking_t<>::always_t>::value)) 353 #else // defined(BOOST_ASIO_MSVC) 354 BOOST_ASIO_NOEXCEPT_IF(( 355 is_nothrow_query<const Executor&, always_t>::value)) 356 #endif // defined(BOOST_ASIO_MSVC) 357 #endif // !defined(__clang__) 358 { 359 return boost::asio::query(ex, always_t()); 360 } 361 362 template <typename Executor> 363 friend BOOST_ASIO_CONSTEXPR blocking_t query( 364 const Executor& ex, convertible_from_blocking_t, 365 typename enable_if< 366 !can_query<const Executor&, possibly_t>::value 367 && !can_query<const Executor&, always_t>::value 368 && can_query<const Executor&, never_t>::value 369 >::type* = 0) 370 #if !defined(__clang__) // Clang crashes if noexcept is used here. 371 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. 372 BOOST_ASIO_NOEXCEPT_IF(( 373 is_nothrow_query<const Executor&, blocking_t<>::never_t>::value)) 374 #else // defined(BOOST_ASIO_MSVC) 375 BOOST_ASIO_NOEXCEPT_IF(( 376 is_nothrow_query<const Executor&, never_t>::value)) 377 #endif // defined(BOOST_ASIO_MSVC) 378 #endif // !defined(__clang__) 379 { 380 return boost::asio::query(ex, never_t()); 381 } 382 383 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(possibly_t, possibly); 384 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(always_t, always); 385 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(never_t, never); 386 387 #if !defined(BOOST_ASIO_HAS_CONSTEXPR) 388 static const blocking_t instance; 389 #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR) 390 391 private: 392 int value_; 393 }; 394 395 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 396 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 397 template <int I> template <typename E, typename T> 398 const T blocking_t<I>::static_query_v; 399 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 400 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 401 402 #if !defined(BOOST_ASIO_HAS_CONSTEXPR) 403 template <int I> 404 const blocking_t<I> blocking_t<I>::instance; 405 #endif 406 407 template <int I> 408 const typename blocking_t<I>::possibly_t blocking_t<I>::possibly; 409 410 template <int I> 411 const typename blocking_t<I>::always_t blocking_t<I>::always; 412 413 template <int I> 414 const typename blocking_t<I>::never_t blocking_t<I>::never; 415 416 namespace blocking { 417 418 template <int I = 0> 419 struct possibly_t 420 { 421 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 422 template <typename T> 423 BOOST_ASIO_STATIC_CONSTEXPR(bool, 424 is_applicable_property_v = is_executor<T>::value 425 || is_sender<T>::value || is_scheduler<T>::value); 426 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 427 428 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); 429 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); 430 typedef blocking_t<I> polymorphic_query_result_type; 431 432 BOOST_ASIO_CONSTEXPR possibly_t() 433 { 434 } 435 436 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 437 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 438 template <typename T> 439 static BOOST_ASIO_CONSTEXPR 440 typename traits::query_static_constexpr_member<T, possibly_t>::result_type 441 static_query() 442 BOOST_ASIO_NOEXCEPT_IF(( 443 traits::query_static_constexpr_member<T, possibly_t>::is_noexcept)) 444 { 445 return traits::query_static_constexpr_member<T, possibly_t>::value(); 446 } 447 448 template <typename T> 449 static BOOST_ASIO_CONSTEXPR possibly_t static_query( 450 typename enable_if< 451 !traits::query_static_constexpr_member<T, possibly_t>::is_valid 452 && !traits::query_member<T, possibly_t>::is_valid 453 && !traits::query_free<T, possibly_t>::is_valid 454 && !can_query<T, always_t<I> >::value 455 && !can_query<T, never_t<I> >::value 456 >::type* = 0) BOOST_ASIO_NOEXCEPT 457 { 458 return possibly_t(); 459 } 460 461 template <typename E, typename T = decltype(possibly_t::static_query<E>())> 462 static BOOST_ASIO_CONSTEXPR const T static_query_v 463 = possibly_t::static_query<E>(); 464 #endif // defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 465 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 466 467 static BOOST_ASIO_CONSTEXPR blocking_t<I> value() 468 { 469 return possibly_t(); 470 } 471 472 friend BOOST_ASIO_CONSTEXPR bool operator==( 473 const possibly_t&, const possibly_t&) 474 { 475 return true; 476 } 477 478 friend BOOST_ASIO_CONSTEXPR bool operator!=( 479 const possibly_t&, const possibly_t&) 480 { 481 return false; 482 } 483 484 friend BOOST_ASIO_CONSTEXPR bool operator==( 485 const possibly_t&, const always_t<I>&) 486 { 487 return false; 488 } 489 490 friend BOOST_ASIO_CONSTEXPR bool operator!=( 491 const possibly_t&, const always_t<I>&) 492 { 493 return true; 494 } 495 496 friend BOOST_ASIO_CONSTEXPR bool operator==( 497 const possibly_t&, const never_t<I>&) 498 { 499 return false; 500 } 501 502 friend BOOST_ASIO_CONSTEXPR bool operator!=( 503 const possibly_t&, const never_t<I>&) 504 { 505 return true; 506 } 507 }; 508 509 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 510 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 511 template <int I> template <typename E, typename T> 512 const T possibly_t<I>::static_query_v; 513 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 514 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 515 516 template <typename Executor> 517 class adapter 518 { 519 public: 520 adapter(int, const Executor& e) BOOST_ASIO_NOEXCEPT 521 : executor_(e) 522 { 523 } 524 525 adapter(const adapter& other) BOOST_ASIO_NOEXCEPT 526 : executor_(other.executor_) 527 { 528 } 529 530 #if defined(BOOST_ASIO_HAS_MOVE) 531 adapter(adapter&& other) BOOST_ASIO_NOEXCEPT 532 : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_)) 533 { 534 } 535 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 536 537 template <int I> 538 static BOOST_ASIO_CONSTEXPR always_t<I> query( 539 blocking_t<I>) BOOST_ASIO_NOEXCEPT 540 { 541 return always_t<I>(); 542 } 543 544 template <int I> 545 static BOOST_ASIO_CONSTEXPR always_t<I> query( 546 possibly_t<I>) BOOST_ASIO_NOEXCEPT 547 { 548 return always_t<I>(); 549 } 550 551 template <int I> 552 static BOOST_ASIO_CONSTEXPR always_t<I> query( 553 always_t<I>) BOOST_ASIO_NOEXCEPT 554 { 555 return always_t<I>(); 556 } 557 558 template <int I> 559 static BOOST_ASIO_CONSTEXPR always_t<I> query( 560 never_t<I>) BOOST_ASIO_NOEXCEPT 561 { 562 return always_t<I>(); 563 } 564 565 template <typename Property> 566 typename enable_if< 567 can_query<const Executor&, Property>::value, 568 typename query_result<const Executor&, Property>::type 569 >::type query(const Property& p) const 570 BOOST_ASIO_NOEXCEPT_IF(( 571 is_nothrow_query<const Executor&, Property>::value)) 572 { 573 return boost::asio::query(executor_, p); 574 } 575 576 template <int I> 577 typename enable_if< 578 can_require<const Executor&, possibly_t<I> >::value, 579 typename require_result<const Executor&, possibly_t<I> >::type 580 >::type require(possibly_t<I>) const BOOST_ASIO_NOEXCEPT 581 { 582 return boost::asio::require(executor_, possibly_t<I>()); 583 } 584 585 template <int I> 586 typename enable_if< 587 can_require<const Executor&, never_t<I> >::value, 588 typename require_result<const Executor&, never_t<I> >::type 589 >::type require(never_t<I>) const BOOST_ASIO_NOEXCEPT 590 { 591 return boost::asio::require(executor_, never_t<I>()); 592 } 593 594 template <typename Property> 595 typename enable_if< 596 can_require<const Executor&, Property>::value, 597 adapter<typename decay< 598 typename require_result<const Executor&, Property>::type 599 >::type> 600 >::type require(const Property& p) const 601 BOOST_ASIO_NOEXCEPT_IF(( 602 is_nothrow_require<const Executor&, Property>::value)) 603 { 604 return adapter<typename decay< 605 typename require_result<const Executor&, Property>::type 606 >::type>(0, boost::asio::require(executor_, p)); 607 } 608 609 template <typename Property> 610 typename enable_if< 611 can_prefer<const Executor&, Property>::value, 612 adapter<typename decay< 613 typename prefer_result<const Executor&, Property>::type 614 >::type> 615 >::type prefer(const Property& p) const 616 BOOST_ASIO_NOEXCEPT_IF(( 617 is_nothrow_prefer<const Executor&, Property>::value)) 618 { 619 return adapter<typename decay< 620 typename prefer_result<const Executor&, Property>::type 621 >::type>(0, boost::asio::prefer(executor_, p)); 622 } 623 624 template <typename Function> 625 typename enable_if< 626 execution::can_execute<const Executor&, Function>::value 627 >::type execute(BOOST_ASIO_MOVE_ARG(Function) f) const 628 { 629 blocking_adaptation::blocking_execute( 630 executor_, BOOST_ASIO_MOVE_CAST(Function)(f)); 631 } 632 633 friend bool operator==(const adapter& a, const adapter& b) BOOST_ASIO_NOEXCEPT 634 { 635 return a.executor_ == b.executor_; 636 } 637 638 friend bool operator!=(const adapter& a, const adapter& b) BOOST_ASIO_NOEXCEPT 639 { 640 return a.executor_ != b.executor_; 641 } 642 643 private: 644 Executor executor_; 645 }; 646 647 template <int I = 0> 648 struct always_t 649 { 650 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 651 template <typename T> 652 BOOST_ASIO_STATIC_CONSTEXPR(bool, 653 is_applicable_property_v = is_executor<T>::value 654 || is_sender<T>::value || is_scheduler<T>::value); 655 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 656 657 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); 658 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); 659 typedef blocking_t<I> polymorphic_query_result_type; 660 661 BOOST_ASIO_CONSTEXPR always_t() 662 { 663 } 664 665 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 666 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 667 template <typename T> 668 static BOOST_ASIO_CONSTEXPR 669 typename traits::query_static_constexpr_member<T, always_t>::result_type 670 static_query() 671 BOOST_ASIO_NOEXCEPT_IF(( 672 traits::query_static_constexpr_member<T, always_t>::is_noexcept)) 673 { 674 return traits::query_static_constexpr_member<T, always_t>::value(); 675 } 676 677 template <typename E, typename T = decltype(always_t::static_query<E>())> 678 static BOOST_ASIO_CONSTEXPR const T static_query_v 679 = always_t::static_query<E>(); 680 #endif // defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 681 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 682 683 static BOOST_ASIO_CONSTEXPR blocking_t<I> value() 684 { 685 return always_t(); 686 } 687 688 friend BOOST_ASIO_CONSTEXPR bool operator==( 689 const always_t&, const always_t&) 690 { 691 return true; 692 } 693 694 friend BOOST_ASIO_CONSTEXPR bool operator!=( 695 const always_t&, const always_t&) 696 { 697 return false; 698 } 699 700 friend BOOST_ASIO_CONSTEXPR bool operator==( 701 const always_t&, const possibly_t<I>&) 702 { 703 return false; 704 } 705 706 friend BOOST_ASIO_CONSTEXPR bool operator!=( 707 const always_t&, const possibly_t<I>&) 708 { 709 return true; 710 } 711 712 friend BOOST_ASIO_CONSTEXPR bool operator==( 713 const always_t&, const never_t<I>&) 714 { 715 return false; 716 } 717 718 friend BOOST_ASIO_CONSTEXPR bool operator!=( 719 const always_t&, const never_t<I>&) 720 { 721 return true; 722 } 723 724 template <typename Executor> 725 friend adapter<Executor> require( 726 const Executor& e, const always_t&, 727 typename enable_if< 728 is_executor<Executor>::value 729 && traits::static_require< 730 const Executor&, 731 blocking_adaptation::allowed_t<0> 732 >::is_valid 733 >::type* = 0) 734 { 735 return adapter<Executor>(0, e); 736 } 737 }; 738 739 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 740 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 741 template <int I> template <typename E, typename T> 742 const T always_t<I>::static_query_v; 743 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 744 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 745 746 template <int I> 747 struct never_t 748 { 749 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 750 template <typename T> 751 BOOST_ASIO_STATIC_CONSTEXPR(bool, 752 is_applicable_property_v = is_executor<T>::value 753 || is_sender<T>::value || is_scheduler<T>::value); 754 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 755 756 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); 757 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); 758 typedef blocking_t<I> polymorphic_query_result_type; 759 760 BOOST_ASIO_CONSTEXPR never_t() 761 { 762 } 763 764 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 765 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 766 template <typename T> 767 static BOOST_ASIO_CONSTEXPR 768 typename traits::query_static_constexpr_member<T, never_t>::result_type 769 static_query() 770 BOOST_ASIO_NOEXCEPT_IF(( 771 traits::query_static_constexpr_member<T, never_t>::is_noexcept)) 772 { 773 return traits::query_static_constexpr_member<T, never_t>::value(); 774 } 775 776 template <typename E, typename T = decltype(never_t::static_query<E>())> 777 static BOOST_ASIO_CONSTEXPR const T static_query_v 778 = never_t::static_query<E>(); 779 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 780 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 781 782 static BOOST_ASIO_CONSTEXPR blocking_t<I> value() 783 { 784 return never_t(); 785 } 786 787 friend BOOST_ASIO_CONSTEXPR bool operator==( 788 const never_t&, const never_t&) 789 { 790 return true; 791 } 792 793 friend BOOST_ASIO_CONSTEXPR bool operator!=( 794 const never_t&, const never_t&) 795 { 796 return false; 797 } 798 799 friend BOOST_ASIO_CONSTEXPR bool operator==( 800 const never_t&, const possibly_t<I>&) 801 { 802 return false; 803 } 804 805 friend BOOST_ASIO_CONSTEXPR bool operator!=( 806 const never_t&, const possibly_t<I>&) 807 { 808 return true; 809 } 810 811 friend BOOST_ASIO_CONSTEXPR bool operator==( 812 const never_t&, const always_t<I>&) 813 { 814 return false; 815 } 816 817 friend BOOST_ASIO_CONSTEXPR bool operator!=( 818 const never_t&, const always_t<I>&) 819 { 820 return true; 821 } 822 }; 823 824 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 825 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 826 template <int I> template <typename E, typename T> 827 const T never_t<I>::static_query_v; 828 #endif // defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 829 830 } // namespace blocking 831 } // namespace detail 832 833 typedef detail::blocking_t<> blocking_t; 834 835 #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) 836 constexpr blocking_t blocking; 837 #else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) 838 namespace { static const blocking_t& blocking = blocking_t::instance; } 839 #endif 840 841 } // namespace execution 842 843 #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 844 845 template <typename T> 846 struct is_applicable_property<T, execution::blocking_t> 847 : integral_constant<bool, 848 execution::is_executor<T>::value 849 || execution::is_sender<T>::value 850 || execution::is_scheduler<T>::value> 851 { 852 }; 853 854 template <typename T> 855 struct is_applicable_property<T, execution::blocking_t::possibly_t> 856 : integral_constant<bool, 857 execution::is_executor<T>::value 858 || execution::is_sender<T>::value 859 || execution::is_scheduler<T>::value> 860 { 861 }; 862 863 template <typename T> 864 struct is_applicable_property<T, execution::blocking_t::always_t> 865 : integral_constant<bool, 866 execution::is_executor<T>::value 867 || execution::is_sender<T>::value 868 || execution::is_scheduler<T>::value> 869 { 870 }; 871 872 template <typename T> 873 struct is_applicable_property<T, execution::blocking_t::never_t> 874 : integral_constant<bool, 875 execution::is_executor<T>::value 876 || execution::is_sender<T>::value 877 || execution::is_scheduler<T>::value> 878 { 879 }; 880 881 #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 882 883 namespace traits { 884 885 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) 886 887 template <typename T> 888 struct query_free_default<T, execution::blocking_t, 889 typename enable_if< 890 can_query<T, execution::blocking_t::possibly_t>::value 891 >::type> 892 { 893 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 894 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 895 (is_nothrow_query<T, execution::blocking_t::possibly_t>::value)); 896 897 typedef execution::blocking_t result_type; 898 }; 899 900 template <typename T> 901 struct query_free_default<T, execution::blocking_t, 902 typename enable_if< 903 !can_query<T, execution::blocking_t::possibly_t>::value 904 && can_query<T, execution::blocking_t::always_t>::value 905 >::type> 906 { 907 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 908 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 909 (is_nothrow_query<T, execution::blocking_t::always_t>::value)); 910 911 typedef execution::blocking_t result_type; 912 }; 913 914 template <typename T> 915 struct query_free_default<T, execution::blocking_t, 916 typename enable_if< 917 !can_query<T, execution::blocking_t::possibly_t>::value 918 && !can_query<T, execution::blocking_t::always_t>::value 919 && can_query<T, execution::blocking_t::never_t>::value 920 >::type> 921 { 922 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 923 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 924 (is_nothrow_query<T, execution::blocking_t::never_t>::value)); 925 926 typedef execution::blocking_t result_type; 927 }; 928 929 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) 930 931 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ 932 || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 933 934 template <typename T> 935 struct static_query<T, execution::blocking_t, 936 typename enable_if< 937 traits::query_static_constexpr_member<T, 938 execution::blocking_t>::is_valid 939 >::type> 940 { 941 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 942 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 943 944 typedef typename traits::query_static_constexpr_member<T, 945 execution::blocking_t>::result_type result_type; 946 947 static BOOST_ASIO_CONSTEXPR result_type value() 948 { 949 return traits::query_static_constexpr_member<T, 950 execution::blocking_t>::value(); 951 } 952 }; 953 954 template <typename T> 955 struct static_query<T, execution::blocking_t, 956 typename enable_if< 957 !traits::query_static_constexpr_member<T, execution::blocking_t>::is_valid 958 && !traits::query_member<T, execution::blocking_t>::is_valid 959 && traits::static_query<T, execution::blocking_t::possibly_t>::is_valid 960 >::type> 961 { 962 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 963 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 964 965 typedef typename traits::static_query<T, 966 execution::blocking_t::possibly_t>::result_type result_type; 967 968 static BOOST_ASIO_CONSTEXPR result_type value() 969 { 970 return traits::static_query<T, execution::blocking_t::possibly_t>::value(); 971 } 972 }; 973 974 template <typename T> 975 struct static_query<T, execution::blocking_t, 976 typename enable_if< 977 !traits::query_static_constexpr_member<T, execution::blocking_t>::is_valid 978 && !traits::query_member<T, execution::blocking_t>::is_valid 979 && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid 980 && traits::static_query<T, execution::blocking_t::always_t>::is_valid 981 >::type> 982 { 983 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 984 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 985 986 typedef typename traits::static_query<T, 987 execution::blocking_t::always_t>::result_type result_type; 988 989 static BOOST_ASIO_CONSTEXPR result_type value() 990 { 991 return traits::static_query<T, execution::blocking_t::always_t>::value(); 992 } 993 }; 994 995 template <typename T> 996 struct static_query<T, execution::blocking_t, 997 typename enable_if< 998 !traits::query_static_constexpr_member<T, execution::blocking_t>::is_valid 999 && !traits::query_member<T, execution::blocking_t>::is_valid 1000 && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid 1001 && !traits::static_query<T, execution::blocking_t::always_t>::is_valid 1002 && traits::static_query<T, execution::blocking_t::never_t>::is_valid 1003 >::type> 1004 { 1005 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1006 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1007 1008 typedef typename traits::static_query<T, 1009 execution::blocking_t::never_t>::result_type result_type; 1010 1011 static BOOST_ASIO_CONSTEXPR result_type value() 1012 { 1013 return traits::static_query<T, execution::blocking_t::never_t>::value(); 1014 } 1015 }; 1016 1017 template <typename T> 1018 struct static_query<T, execution::blocking_t::possibly_t, 1019 typename enable_if< 1020 traits::query_static_constexpr_member<T, 1021 execution::blocking_t::possibly_t>::is_valid 1022 >::type> 1023 { 1024 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1025 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1026 1027 typedef typename traits::query_static_constexpr_member<T, 1028 execution::blocking_t::possibly_t>::result_type result_type; 1029 1030 static BOOST_ASIO_CONSTEXPR result_type value() 1031 { 1032 return traits::query_static_constexpr_member<T, 1033 execution::blocking_t::possibly_t>::value(); 1034 } 1035 }; 1036 1037 template <typename T> 1038 struct static_query<T, execution::blocking_t::possibly_t, 1039 typename enable_if< 1040 !traits::query_static_constexpr_member<T, 1041 execution::blocking_t::possibly_t>::is_valid 1042 && !traits::query_member<T, execution::blocking_t::possibly_t>::is_valid 1043 && !traits::query_free<T, execution::blocking_t::possibly_t>::is_valid 1044 && !can_query<T, execution::blocking_t::always_t>::value 1045 && !can_query<T, execution::blocking_t::never_t>::value 1046 >::type> 1047 { 1048 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1049 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1050 1051 typedef execution::blocking_t::possibly_t result_type; 1052 1053 static BOOST_ASIO_CONSTEXPR result_type value() 1054 { 1055 return result_type(); 1056 } 1057 }; 1058 1059 template <typename T> 1060 struct static_query<T, execution::blocking_t::always_t, 1061 typename enable_if< 1062 traits::query_static_constexpr_member<T, 1063 execution::blocking_t::always_t>::is_valid 1064 >::type> 1065 { 1066 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1067 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1068 1069 typedef typename traits::query_static_constexpr_member<T, 1070 execution::blocking_t::always_t>::result_type result_type; 1071 1072 static BOOST_ASIO_CONSTEXPR result_type value() 1073 { 1074 return traits::query_static_constexpr_member<T, 1075 execution::blocking_t::always_t>::value(); 1076 } 1077 }; 1078 1079 template <typename T> 1080 struct static_query<T, execution::blocking_t::never_t, 1081 typename enable_if< 1082 traits::query_static_constexpr_member<T, 1083 execution::blocking_t::never_t>::is_valid 1084 >::type> 1085 { 1086 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1087 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1088 1089 typedef typename traits::query_static_constexpr_member<T, 1090 execution::blocking_t::never_t>::result_type result_type; 1091 1092 static BOOST_ASIO_CONSTEXPR result_type value() 1093 { 1094 return traits::query_static_constexpr_member<T, 1095 execution::blocking_t::never_t>::value(); 1096 } 1097 }; 1098 1099 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) 1100 // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) 1101 1102 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) 1103 1104 template <typename T> 1105 struct static_require<T, execution::blocking_t::possibly_t, 1106 typename enable_if< 1107 static_query<T, execution::blocking_t::possibly_t>::is_valid 1108 >::type> 1109 { 1110 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = 1111 (is_same<typename static_query<T, 1112 execution::blocking_t::possibly_t>::result_type, 1113 execution::blocking_t::possibly_t>::value)); 1114 }; 1115 1116 template <typename T> 1117 struct static_require<T, execution::blocking_t::always_t, 1118 typename enable_if< 1119 static_query<T, execution::blocking_t::always_t>::is_valid 1120 >::type> 1121 { 1122 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = 1123 (is_same<typename static_query<T, 1124 execution::blocking_t::always_t>::result_type, 1125 execution::blocking_t::always_t>::value)); 1126 }; 1127 1128 template <typename T> 1129 struct static_require<T, execution::blocking_t::never_t, 1130 typename enable_if< 1131 static_query<T, execution::blocking_t::never_t>::is_valid 1132 >::type> 1133 { 1134 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = 1135 (is_same<typename static_query<T, 1136 execution::blocking_t::never_t>::result_type, 1137 execution::blocking_t::never_t>::value)); 1138 }; 1139 1140 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) 1141 1142 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) 1143 1144 template <typename T> 1145 struct require_free_default<T, execution::blocking_t::always_t, 1146 typename enable_if< 1147 is_same<T, typename decay<T>::type>::value 1148 && execution::is_executor<T>::value 1149 && traits::static_require< 1150 const T&, 1151 execution::detail::blocking_adaptation::allowed_t<0> 1152 >::is_valid 1153 >::type> 1154 { 1155 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1156 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 1157 typedef execution::detail::blocking::adapter<T> result_type; 1158 }; 1159 1160 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) 1161 1162 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 1163 1164 template <typename Executor> 1165 struct equality_comparable< 1166 execution::detail::blocking::adapter<Executor> > 1167 { 1168 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1169 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1170 }; 1171 1172 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 1173 1174 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 1175 1176 template <typename Executor, typename Function> 1177 struct execute_member< 1178 execution::detail::blocking::adapter<Executor>, Function> 1179 { 1180 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1181 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 1182 typedef void result_type; 1183 }; 1184 1185 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 1186 1187 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 1188 1189 template <typename Executor, int I> 1190 struct query_static_constexpr_member< 1191 execution::detail::blocking::adapter<Executor>, 1192 execution::detail::blocking_t<I> > 1193 { 1194 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1195 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1196 typedef execution::blocking_t::always_t result_type; 1197 1198 static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT 1199 { 1200 return result_type(); 1201 } 1202 }; 1203 1204 template <typename Executor, int I> 1205 struct query_static_constexpr_member< 1206 execution::detail::blocking::adapter<Executor>, 1207 execution::detail::blocking::always_t<I> > 1208 { 1209 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1210 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1211 typedef execution::blocking_t::always_t result_type; 1212 1213 static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT 1214 { 1215 return result_type(); 1216 } 1217 }; 1218 1219 template <typename Executor, int I> 1220 struct query_static_constexpr_member< 1221 execution::detail::blocking::adapter<Executor>, 1222 execution::detail::blocking::possibly_t<I> > 1223 { 1224 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1225 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1226 typedef execution::blocking_t::always_t result_type; 1227 1228 static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT 1229 { 1230 return result_type(); 1231 } 1232 }; 1233 1234 template <typename Executor, int I> 1235 struct query_static_constexpr_member< 1236 execution::detail::blocking::adapter<Executor>, 1237 execution::detail::blocking::never_t<I> > 1238 { 1239 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1240 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 1241 typedef execution::blocking_t::always_t result_type; 1242 1243 static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT 1244 { 1245 return result_type(); 1246 } 1247 }; 1248 1249 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 1250 1251 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 1252 1253 template <typename Executor, typename Property> 1254 struct query_member< 1255 execution::detail::blocking::adapter<Executor>, Property, 1256 typename enable_if< 1257 can_query<const Executor&, Property>::value 1258 >::type> 1259 { 1260 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1261 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1262 (is_nothrow_query<Executor, Property>::value)); 1263 typedef typename query_result<Executor, Property>::type result_type; 1264 }; 1265 1266 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 1267 1268 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 1269 1270 template <typename Executor, int I> 1271 struct require_member< 1272 execution::detail::blocking::adapter<Executor>, 1273 execution::detail::blocking::possibly_t<I>, 1274 typename enable_if< 1275 can_require< 1276 const Executor&, 1277 execution::detail::blocking::possibly_t<I> 1278 >::value 1279 >::type> 1280 { 1281 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1282 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1283 (is_nothrow_require<const Executor&, 1284 execution::detail::blocking::possibly_t<I> >::value)); 1285 typedef typename require_result<const Executor&, 1286 execution::detail::blocking::possibly_t<I> >::type result_type; 1287 }; 1288 1289 template <typename Executor, int I> 1290 struct require_member< 1291 execution::detail::blocking::adapter<Executor>, 1292 execution::detail::blocking::never_t<I>, 1293 typename enable_if< 1294 can_require< 1295 const Executor&, 1296 execution::detail::blocking::never_t<I> 1297 >::value 1298 >::type> 1299 { 1300 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1301 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1302 (is_nothrow_require<const Executor&, 1303 execution::detail::blocking::never_t<I> >::value)); 1304 typedef typename require_result<const Executor&, 1305 execution::detail::blocking::never_t<I> >::type result_type; 1306 }; 1307 1308 template <typename Executor, typename Property> 1309 struct require_member< 1310 execution::detail::blocking::adapter<Executor>, Property, 1311 typename enable_if< 1312 can_require<const Executor&, Property>::value 1313 >::type> 1314 { 1315 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1316 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1317 (is_nothrow_require<Executor, Property>::value)); 1318 typedef execution::detail::blocking::adapter<typename decay< 1319 typename require_result<Executor, Property>::type 1320 >::type> result_type; 1321 }; 1322 1323 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 1324 1325 #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) 1326 1327 template <typename Executor, typename Property> 1328 struct prefer_member< 1329 execution::detail::blocking::adapter<Executor>, Property, 1330 typename enable_if< 1331 can_prefer<const Executor&, Property>::value 1332 >::type> 1333 { 1334 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 1335 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 1336 (is_nothrow_prefer<Executor, Property>::value)); 1337 typedef execution::detail::blocking::adapter<typename decay< 1338 typename prefer_result<Executor, Property>::type 1339 >::type> result_type; 1340 }; 1341 1342 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) 1343 1344 } // namespace traits 1345 1346 #endif // defined(GENERATING_DOCUMENTATION) 1347 1348 } // namespace asio 1349 } // namespace boost 1350 1351 #include <boost/asio/detail/pop_options.hpp> 1352 1353 #endif // BOOST_ASIO_EXECUTION_BLOCKING_HPP 1354