1 // 2 // system_executor.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_SYSTEM_EXECUTOR_HPP 12 #define BOOST_ASIO_SYSTEM_EXECUTOR_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 #include <boost/asio/detail/memory.hpp> 20 #include <boost/asio/execution.hpp> 21 22 #include <boost/asio/detail/push_options.hpp> 23 24 namespace boost { 25 namespace asio { 26 27 class system_context; 28 29 /// An executor that uses arbitrary threads. 30 /** 31 * The system executor represents an execution context where functions are 32 * permitted to run on arbitrary threads. When the blocking.never property is 33 * established, the system executor will schedule the function to run on an 34 * unspecified system thread pool. When either blocking.possibly or 35 * blocking.always is established, the executor invokes the function 36 * immediately. 37 */ 38 template <typename Blocking, typename Relationship, typename Allocator> 39 class basic_system_executor 40 { 41 public: 42 /// Default constructor. basic_system_executor()43 basic_system_executor() BOOST_ASIO_NOEXCEPT 44 : allocator_(Allocator()) 45 { 46 } 47 48 /// Obtain an executor with the @c blocking.possibly property. 49 /** 50 * Do not call this function directly. It is intended for use with the 51 * boost::asio::require customisation point. 52 * 53 * For example: 54 * @code boost::asio::system_executor ex1; 55 * auto ex2 = boost::asio::require(ex1, 56 * boost::asio::execution::blocking.possibly); @endcode 57 */ 58 basic_system_executor<execution::blocking_t::possibly_t, 59 Relationship, Allocator> require(execution::blocking_t::possibly_t) const60 require(execution::blocking_t::possibly_t) const 61 { 62 return basic_system_executor<execution::blocking_t::possibly_t, 63 Relationship, Allocator>(allocator_); 64 } 65 66 /// Obtain an executor with the @c blocking.always property. 67 /** 68 * Do not call this function directly. It is intended for use with the 69 * boost::asio::require customisation point. 70 * 71 * For example: 72 * @code boost::asio::system_executor ex1; 73 * auto ex2 = boost::asio::require(ex1, 74 * boost::asio::execution::blocking.always); @endcode 75 */ 76 basic_system_executor<execution::blocking_t::always_t, 77 Relationship, Allocator> require(execution::blocking_t::always_t) const78 require(execution::blocking_t::always_t) const 79 { 80 return basic_system_executor<execution::blocking_t::always_t, 81 Relationship, Allocator>(allocator_); 82 } 83 84 /// Obtain an executor with the @c blocking.never property. 85 /** 86 * Do not call this function directly. It is intended for use with the 87 * boost::asio::require customisation point. 88 * 89 * For example: 90 * @code boost::asio::system_executor ex1; 91 * auto ex2 = boost::asio::require(ex1, 92 * boost::asio::execution::blocking.never); @endcode 93 */ 94 basic_system_executor<execution::blocking_t::never_t, 95 Relationship, Allocator> require(execution::blocking_t::never_t) const96 require(execution::blocking_t::never_t) const 97 { 98 return basic_system_executor<execution::blocking_t::never_t, 99 Relationship, Allocator>(allocator_); 100 } 101 102 /// Obtain an executor with the @c relationship.continuation property. 103 /** 104 * Do not call this function directly. It is intended for use with the 105 * boost::asio::require customisation point. 106 * 107 * For example: 108 * @code boost::asio::system_executor ex1; 109 * auto ex2 = boost::asio::require(ex1, 110 * boost::asio::execution::relationship.continuation); @endcode 111 */ 112 basic_system_executor<Blocking, 113 execution::relationship_t::continuation_t, Allocator> require(execution::relationship_t::continuation_t) const114 require(execution::relationship_t::continuation_t) const 115 { 116 return basic_system_executor<Blocking, 117 execution::relationship_t::continuation_t, Allocator>(allocator_); 118 } 119 120 /// Obtain an executor with the @c relationship.fork property. 121 /** 122 * Do not call this function directly. It is intended for use with the 123 * boost::asio::require customisation point. 124 * 125 * For example: 126 * @code boost::asio::system_executor ex1; 127 * auto ex2 = boost::asio::require(ex1, 128 * boost::asio::execution::relationship.fork); @endcode 129 */ 130 basic_system_executor<Blocking, 131 execution::relationship_t::fork_t, Allocator> require(execution::relationship_t::fork_t) const132 require(execution::relationship_t::fork_t) const 133 { 134 return basic_system_executor<Blocking, 135 execution::relationship_t::fork_t, Allocator>(allocator_); 136 } 137 138 /// Obtain an executor with the specified @c allocator property. 139 /** 140 * Do not call this function directly. It is intended for use with the 141 * boost::asio::require customisation point. 142 * 143 * For example: 144 * @code boost::asio::system_executor ex1; 145 * auto ex2 = boost::asio::require(ex1, 146 * boost::asio::execution::allocator(my_allocator)); @endcode 147 */ 148 template <typename OtherAllocator> 149 basic_system_executor<Blocking, Relationship, OtherAllocator> require(execution::allocator_t<OtherAllocator> a) const150 require(execution::allocator_t<OtherAllocator> a) const 151 { 152 return basic_system_executor<Blocking, 153 Relationship, OtherAllocator>(a.value()); 154 } 155 156 /// Obtain an executor with the default @c allocator property. 157 /** 158 * Do not call this function directly. It is intended for use with the 159 * boost::asio::require customisation point. 160 * 161 * For example: 162 * @code boost::asio::system_executor ex1; 163 * auto ex2 = boost::asio::require(ex1, 164 * boost::asio::execution::allocator); @endcode 165 */ 166 basic_system_executor<Blocking, Relationship, std::allocator<void> > require(execution::allocator_t<void>) const167 require(execution::allocator_t<void>) const 168 { 169 return basic_system_executor<Blocking, 170 Relationship, std::allocator<void> >(); 171 } 172 173 /// Query the current value of the @c mapping property. 174 /** 175 * Do not call this function directly. It is intended for use with the 176 * boost::asio::query customisation point. 177 * 178 * For example: 179 * @code boost::asio::system_executor ex; 180 * if (boost::asio::query(ex, boost::asio::execution::mapping) 181 * == boost::asio::execution::mapping.thread) 182 * ... @endcode 183 */ query(execution::mapping_t)184 static BOOST_ASIO_CONSTEXPR execution::mapping_t query( 185 execution::mapping_t) BOOST_ASIO_NOEXCEPT 186 { 187 return execution::mapping.thread; 188 } 189 190 /// Query the current value of the @c context property. 191 /** 192 * Do not call this function directly. It is intended for use with the 193 * boost::asio::query customisation point. 194 * 195 * For example: 196 * @code boost::asio::system_executor ex; 197 * boost::asio::system_context& pool = boost::asio::query( 198 * ex, boost::asio::execution::context); @endcode 199 */ 200 static system_context& query(execution::context_t) BOOST_ASIO_NOEXCEPT; 201 202 /// Query the current value of the @c blocking property. 203 /** 204 * Do not call this function directly. It is intended for use with the 205 * boost::asio::query customisation point. 206 * 207 * For example: 208 * @code boost::asio::system_executor ex; 209 * if (boost::asio::query(ex, boost::asio::execution::blocking) 210 * == boost::asio::execution::blocking.always) 211 * ... @endcode 212 */ query(execution::blocking_t)213 static BOOST_ASIO_CONSTEXPR execution::blocking_t query( 214 execution::blocking_t) BOOST_ASIO_NOEXCEPT 215 { 216 return Blocking(); 217 } 218 219 /// Query the current value of the @c relationship property. 220 /** 221 * Do not call this function directly. It is intended for use with the 222 * boost::asio::query customisation point. 223 * 224 * For example: 225 * @code boost::asio::system_executor ex; 226 * if (boost::asio::query(ex, boost::asio::execution::relationship) 227 * == boost::asio::execution::relationship.continuation) 228 * ... @endcode 229 */ query(execution::relationship_t)230 static BOOST_ASIO_CONSTEXPR execution::relationship_t query( 231 execution::relationship_t) BOOST_ASIO_NOEXCEPT 232 { 233 return Relationship(); 234 } 235 236 /// Query the current value of the @c allocator property. 237 /** 238 * Do not call this function directly. It is intended for use with the 239 * boost::asio::query customisation point. 240 * 241 * For example: 242 * @code boost::asio::system_executor ex; 243 * auto alloc = boost::asio::query(ex, 244 * boost::asio::execution::allocator); @endcode 245 */ 246 template <typename OtherAllocator> query(execution::allocator_t<OtherAllocator>) const247 BOOST_ASIO_CONSTEXPR Allocator query( 248 execution::allocator_t<OtherAllocator>) const BOOST_ASIO_NOEXCEPT 249 { 250 return allocator_; 251 } 252 253 /// Query the current value of the @c allocator property. 254 /** 255 * Do not call this function directly. It is intended for use with the 256 * boost::asio::query customisation point. 257 * 258 * For example: 259 * @code boost::asio::system_executor ex; 260 * auto alloc = boost::asio::query(ex, 261 * boost::asio::execution::allocator); @endcode 262 */ query(execution::allocator_t<void>) const263 BOOST_ASIO_CONSTEXPR Allocator query( 264 execution::allocator_t<void>) const BOOST_ASIO_NOEXCEPT 265 { 266 return allocator_; 267 } 268 269 /// Query the occupancy (recommended number of work items) for the system 270 /// context. 271 /** 272 * Do not call this function directly. It is intended for use with the 273 * boost::asio::query customisation point. 274 * 275 * For example: 276 * @code boost::asio::system_executor ex; 277 * std::size_t occupancy = boost::asio::query( 278 * ex, boost::asio::execution::occupancy); @endcode 279 */ 280 std::size_t query(execution::occupancy_t) const BOOST_ASIO_NOEXCEPT; 281 282 /// Compare two executors for equality. 283 /** 284 * Two executors are equal if they refer to the same underlying io_context. 285 */ operator ==(const basic_system_executor &,const basic_system_executor &)286 friend bool operator==(const basic_system_executor&, 287 const basic_system_executor&) BOOST_ASIO_NOEXCEPT 288 { 289 return true; 290 } 291 292 /// Compare two executors for inequality. 293 /** 294 * Two executors are equal if they refer to the same underlying io_context. 295 */ operator !=(const basic_system_executor &,const basic_system_executor &)296 friend bool operator!=(const basic_system_executor&, 297 const basic_system_executor&) BOOST_ASIO_NOEXCEPT 298 { 299 return false; 300 } 301 302 /// Execution function. 303 /** 304 * Do not call this function directly. It is intended for use with the 305 * execution::execute customisation point. 306 * 307 * For example: 308 * @code boost::asio::system_executor ex; 309 * execution::execute(ex, my_function_object); @endcode 310 */ 311 template <typename Function> execute(BOOST_ASIO_MOVE_ARG (Function)f) const312 void execute(BOOST_ASIO_MOVE_ARG(Function) f) const 313 { 314 this->do_execute(BOOST_ASIO_MOVE_CAST(Function)(f), Blocking()); 315 } 316 317 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS) 318 /// Obtain the underlying execution context. 319 system_context& context() const BOOST_ASIO_NOEXCEPT; 320 321 /// Inform the executor that it has some outstanding work to do. 322 /** 323 * For the system executor, this is a no-op. 324 */ on_work_started() const325 void on_work_started() const BOOST_ASIO_NOEXCEPT 326 { 327 } 328 329 /// Inform the executor that some work is no longer outstanding. 330 /** 331 * For the system executor, this is a no-op. 332 */ on_work_finished() const333 void on_work_finished() const BOOST_ASIO_NOEXCEPT 334 { 335 } 336 337 /// Request the system executor to invoke the given function object. 338 /** 339 * This function is used to ask the executor to execute the given function 340 * object. The function object will always be executed inside this function. 341 * 342 * @param f The function object to be called. The executor will make 343 * a copy of the handler object as required. The function signature of the 344 * function object must be: @code void function(); @endcode 345 * 346 * @param a An allocator that may be used by the executor to allocate the 347 * internal storage needed for function invocation. 348 */ 349 template <typename Function, typename OtherAllocator> 350 void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const; 351 352 /// Request the system executor to invoke the given function object. 353 /** 354 * This function is used to ask the executor to execute the given function 355 * object. The function object will never be executed inside this function. 356 * Instead, it will be scheduled to run on an unspecified system thread pool. 357 * 358 * @param f The function object to be called. The executor will make 359 * a copy of the handler object as required. The function signature of the 360 * function object must be: @code void function(); @endcode 361 * 362 * @param a An allocator that may be used by the executor to allocate the 363 * internal storage needed for function invocation. 364 */ 365 template <typename Function, typename OtherAllocator> 366 void post(BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const; 367 368 /// Request the system executor to invoke the given function object. 369 /** 370 * This function is used to ask the executor to execute the given function 371 * object. The function object will never be executed inside this function. 372 * Instead, it will be scheduled to run on an unspecified system thread pool. 373 * 374 * @param f The function object to be called. The executor will make 375 * a copy of the handler object as required. The function signature of the 376 * function object must be: @code void function(); @endcode 377 * 378 * @param a An allocator that may be used by the executor to allocate the 379 * internal storage needed for function invocation. 380 */ 381 template <typename Function, typename OtherAllocator> 382 void defer(BOOST_ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const; 383 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS) 384 385 private: 386 template <typename, typename, typename> friend class basic_system_executor; 387 388 // Constructor used by require(). basic_system_executor(const Allocator & a)389 basic_system_executor(const Allocator& a) 390 : allocator_(a) 391 { 392 } 393 394 /// Execution helper implementation for the possibly blocking property. 395 template <typename Function> 396 void do_execute(BOOST_ASIO_MOVE_ARG(Function) f, 397 execution::blocking_t::possibly_t) const; 398 399 /// Execution helper implementation for the always blocking property. 400 template <typename Function> 401 void do_execute(BOOST_ASIO_MOVE_ARG(Function) f, 402 execution::blocking_t::always_t) const; 403 404 /// Execution helper implementation for the never blocking property. 405 template <typename Function> 406 void do_execute(BOOST_ASIO_MOVE_ARG(Function) f, 407 execution::blocking_t::never_t) const; 408 409 // The allocator used for execution functions. 410 Allocator allocator_; 411 }; 412 413 /// An executor that uses arbitrary threads. 414 /** 415 * The system executor represents an execution context where functions are 416 * permitted to run on arbitrary threads. When the blocking.never property is 417 * established, the system executor will schedule the function to run on an 418 * unspecified system thread pool. When either blocking.possibly or 419 * blocking.always is established, the executor invokes the function 420 * immediately. 421 */ 422 typedef basic_system_executor<execution::blocking_t::possibly_t, 423 execution::relationship_t::fork_t, std::allocator<void> > 424 system_executor; 425 426 #if !defined(GENERATING_DOCUMENTATION) 427 428 namespace traits { 429 430 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 431 432 template <typename Blocking, typename Relationship, typename Allocator> 433 struct equality_comparable< 434 boost::asio::basic_system_executor<Blocking, Relationship, Allocator> 435 > 436 { 437 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 438 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 439 }; 440 441 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) 442 443 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 444 445 template <typename Blocking, typename Relationship, 446 typename Allocator, typename Function> 447 struct execute_member< 448 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 449 Function 450 > 451 { 452 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 453 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 454 typedef void result_type; 455 }; 456 457 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) 458 459 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 460 461 template <typename Blocking, typename Relationship, typename Allocator> 462 struct require_member< 463 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 464 boost::asio::execution::blocking_t::possibly_t 465 > 466 { 467 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 468 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 469 typedef boost::asio::basic_system_executor< 470 boost::asio::execution::blocking_t::possibly_t, 471 Relationship, Allocator> result_type; 472 }; 473 474 template <typename Blocking, typename Relationship, typename Allocator> 475 struct require_member< 476 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 477 boost::asio::execution::blocking_t::always_t 478 > 479 { 480 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 481 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 482 typedef boost::asio::basic_system_executor< 483 boost::asio::execution::blocking_t::always_t, 484 Relationship, Allocator> result_type; 485 }; 486 487 template <typename Blocking, typename Relationship, typename Allocator> 488 struct require_member< 489 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 490 boost::asio::execution::blocking_t::never_t 491 > 492 { 493 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 494 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 495 typedef boost::asio::basic_system_executor< 496 boost::asio::execution::blocking_t::never_t, 497 Relationship, Allocator> result_type; 498 }; 499 500 template <typename Blocking, typename Relationship, typename Allocator> 501 struct require_member< 502 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 503 boost::asio::execution::relationship_t::fork_t 504 > 505 { 506 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 507 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 508 typedef boost::asio::basic_system_executor<Blocking, 509 boost::asio::execution::relationship_t::fork_t, 510 Allocator> result_type; 511 }; 512 513 template <typename Blocking, typename Relationship, typename Allocator> 514 struct require_member< 515 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 516 boost::asio::execution::relationship_t::continuation_t 517 > 518 { 519 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 520 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 521 typedef boost::asio::basic_system_executor<Blocking, 522 boost::asio::execution::relationship_t::continuation_t, 523 Allocator> result_type; 524 }; 525 526 template <typename Blocking, typename Relationship, typename Allocator> 527 struct require_member< 528 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 529 boost::asio::execution::allocator_t<void> 530 > 531 { 532 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 533 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 534 typedef boost::asio::basic_system_executor<Blocking, 535 Relationship, std::allocator<void> > result_type; 536 }; 537 538 template <typename Blocking, typename Relationship, 539 typename Allocator, typename OtherAllocator> 540 struct require_member< 541 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 542 boost::asio::execution::allocator_t<OtherAllocator> 543 > 544 { 545 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 546 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 547 typedef boost::asio::basic_system_executor<Blocking, 548 Relationship, OtherAllocator> result_type; 549 }; 550 551 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 552 553 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 554 555 template <typename Blocking, typename Relationship, 556 typename Allocator, typename Property> 557 struct query_static_constexpr_member< 558 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 559 Property, 560 typename boost::asio::enable_if< 561 boost::asio::is_convertible< 562 Property, 563 boost::asio::execution::mapping_t 564 >::value 565 >::type 566 > 567 { 568 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 569 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 570 typedef boost::asio::execution::mapping_t::thread_t result_type; 571 valueboost::asio::traits::query_static_constexpr_member572 static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT 573 { 574 return result_type(); 575 } 576 }; 577 578 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) 579 580 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 581 582 template <typename Blocking, typename Relationship, 583 typename Allocator, typename Property> 584 struct query_member< 585 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 586 Property, 587 typename boost::asio::enable_if< 588 boost::asio::is_convertible< 589 Property, 590 boost::asio::execution::blocking_t 591 >::value 592 >::type 593 > 594 { 595 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 596 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 597 typedef boost::asio::execution::blocking_t result_type; 598 }; 599 600 template <typename Blocking, typename Relationship, 601 typename Allocator, typename Property> 602 struct query_member< 603 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 604 Property, 605 typename boost::asio::enable_if< 606 boost::asio::is_convertible< 607 Property, 608 boost::asio::execution::relationship_t 609 >::value 610 >::type 611 > 612 { 613 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 614 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 615 typedef boost::asio::execution::relationship_t result_type; 616 }; 617 618 template <typename Blocking, typename Relationship, typename Allocator> 619 struct query_member< 620 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 621 boost::asio::execution::context_t 622 > 623 { 624 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 625 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 626 typedef boost::asio::system_context& result_type; 627 }; 628 629 template <typename Blocking, typename Relationship, typename Allocator> 630 struct query_member< 631 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 632 boost::asio::execution::allocator_t<void> 633 > 634 { 635 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 636 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 637 typedef Allocator result_type; 638 }; 639 640 template <typename Blocking, typename Relationship, typename Allocator> 641 struct query_member< 642 boost::asio::basic_system_executor<Blocking, Relationship, Allocator>, 643 boost::asio::execution::allocator_t<Allocator> 644 > 645 { 646 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); 647 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 648 typedef Allocator result_type; 649 }; 650 651 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) 652 653 } // namespace traits 654 655 #endif // !defined(GENERATING_DOCUMENTATION) 656 657 } // namespace asio 658 } // namespace boost 659 660 #include <boost/asio/detail/pop_options.hpp> 661 662 #include <boost/asio/impl/system_executor.hpp> 663 664 #endif // BOOST_ASIO_SYSTEM_EXECUTOR_HPP 665