system_executor.hpp 22 KB

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