mapping.hpp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. //
  2. // execution/mapping.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_EXECUTION_MAPPING_HPP
  11. #define BOOST_ASIO_EXECUTION_MAPPING_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/type_traits.hpp>
  17. #include <boost/asio/execution/executor.hpp>
  18. #include <boost/asio/execution/scheduler.hpp>
  19. #include <boost/asio/execution/sender.hpp>
  20. #include <boost/asio/is_applicable_property.hpp>
  21. #include <boost/asio/query.hpp>
  22. #include <boost/asio/traits/query_free.hpp>
  23. #include <boost/asio/traits/query_member.hpp>
  24. #include <boost/asio/traits/query_static_constexpr_member.hpp>
  25. #include <boost/asio/traits/static_query.hpp>
  26. #include <boost/asio/traits/static_require.hpp>
  27. #include <boost/asio/detail/push_options.hpp>
  28. namespace boost {
  29. namespace asio {
  30. #if defined(GENERATING_DOCUMENTATION)
  31. namespace execution {
  32. /// A property to describe what guarantees an executor makes about the mapping
  33. /// of execution agents on to threads of execution.
  34. struct mapping_t
  35. {
  36. /// The mapping_t property applies to executors, senders, and schedulers.
  37. template <typename T>
  38. static constexpr bool is_applicable_property_v =
  39. is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
  40. /// The top-level mapping_t property cannot be required.
  41. static constexpr bool is_requirable = false;
  42. /// The top-level mapping_t property cannot be preferred.
  43. static constexpr bool is_preferable = false;
  44. /// The type returned by queries against an @c any_executor.
  45. typedef mapping_t polymorphic_query_result_type;
  46. /// A sub-property that indicates that execution agents are mapped on to
  47. /// threads of execution.
  48. struct thread_t
  49. {
  50. /// The mapping_t::thread_t property applies to executors, senders, and
  51. /// schedulers.
  52. template <typename T>
  53. static constexpr bool is_applicable_property_v =
  54. is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
  55. /// The mapping_t::thread_t property can be required.
  56. static constexpr bool is_requirable = true;
  57. /// The mapping_t::thread_t property can be preferred.
  58. static constexpr bool is_preferable = true;
  59. /// The type returned by queries against an @c any_executor.
  60. typedef mapping_t polymorphic_query_result_type;
  61. /// Default constructor.
  62. constexpr thread_t();
  63. /// Get the value associated with a property object.
  64. /**
  65. * @returns thread_t();
  66. */
  67. static constexpr mapping_t value();
  68. };
  69. /// A sub-property that indicates that execution agents are mapped on to
  70. /// new threads of execution.
  71. struct new_thread_t
  72. {
  73. /// The mapping_t::new_thread_t property applies to executors, senders, and
  74. /// schedulers.
  75. template <typename T>
  76. static constexpr bool is_applicable_property_v =
  77. is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
  78. /// The mapping_t::new_thread_t property can be required.
  79. static constexpr bool is_requirable = true;
  80. /// The mapping_t::new_thread_t property can be preferred.
  81. static constexpr bool is_preferable = true;
  82. /// The type returned by queries against an @c any_executor.
  83. typedef mapping_t polymorphic_query_result_type;
  84. /// Default constructor.
  85. constexpr new_thread_t();
  86. /// Get the value associated with a property object.
  87. /**
  88. * @returns new_thread_t();
  89. */
  90. static constexpr mapping_t value();
  91. };
  92. /// A sub-property that indicates that the mapping of execution agents is
  93. /// implementation-defined.
  94. struct other_t
  95. {
  96. /// The mapping_t::other_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. /// The mapping_t::other_t property can be required.
  102. static constexpr bool is_requirable = true;
  103. /// The mapping_t::other_t property can be preferred.
  104. static constexpr bool is_preferable = true;
  105. /// The type returned by queries against an @c any_executor.
  106. typedef mapping_t polymorphic_query_result_type;
  107. /// Default constructor.
  108. constexpr other_t();
  109. /// Get the value associated with a property object.
  110. /**
  111. * @returns other_t();
  112. */
  113. static constexpr mapping_t value();
  114. };
  115. /// A special value used for accessing the mapping_t::thread_t property.
  116. static constexpr thread_t thread;
  117. /// A special value used for accessing the mapping_t::new_thread_t property.
  118. static constexpr new_thread_t new_thread;
  119. /// A special value used for accessing the mapping_t::other_t property.
  120. static constexpr other_t other;
  121. /// Default constructor.
  122. constexpr mapping_t();
  123. /// Construct from a sub-property value.
  124. constexpr mapping_t(thread_t);
  125. /// Construct from a sub-property value.
  126. constexpr mapping_t(new_thread_t);
  127. /// Construct from a sub-property value.
  128. constexpr mapping_t(other_t);
  129. /// Compare property values for equality.
  130. friend constexpr bool operator==(
  131. const mapping_t& a, const mapping_t& b) noexcept;
  132. /// Compare property values for inequality.
  133. friend constexpr bool operator!=(
  134. const mapping_t& a, const mapping_t& b) noexcept;
  135. };
  136. /// A special value used for accessing the mapping_t property.
  137. constexpr mapping_t mapping;
  138. } // namespace execution
  139. #else // defined(GENERATING_DOCUMENTATION)
  140. namespace execution {
  141. namespace detail {
  142. namespace mapping {
  143. template <int I> struct thread_t;
  144. template <int I> struct new_thread_t;
  145. template <int I> struct other_t;
  146. } // namespace mapping
  147. template <int I = 0>
  148. struct mapping_t
  149. {
  150. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  151. template <typename T>
  152. BOOST_ASIO_STATIC_CONSTEXPR(bool,
  153. is_applicable_property_v = (
  154. is_executor<T>::value
  155. || conditional<
  156. is_executor<T>::value,
  157. false_type,
  158. is_sender<T>
  159. >::type::value
  160. || conditional<
  161. is_executor<T>::value,
  162. false_type,
  163. is_scheduler<T>
  164. >::type::value));
  165. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  166. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
  167. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
  168. typedef mapping_t polymorphic_query_result_type;
  169. typedef detail::mapping::thread_t<I> thread_t;
  170. typedef detail::mapping::new_thread_t<I> new_thread_t;
  171. typedef detail::mapping::other_t<I> other_t;
  172. BOOST_ASIO_CONSTEXPR mapping_t()
  173. : value_(-1)
  174. {
  175. }
  176. BOOST_ASIO_CONSTEXPR mapping_t(thread_t)
  177. : value_(0)
  178. {
  179. }
  180. BOOST_ASIO_CONSTEXPR mapping_t(new_thread_t)
  181. : value_(1)
  182. {
  183. }
  184. BOOST_ASIO_CONSTEXPR mapping_t(other_t)
  185. : value_(2)
  186. {
  187. }
  188. template <typename T>
  189. struct proxy
  190. {
  191. #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  192. struct type
  193. {
  194. template <typename P>
  195. auto query(BOOST_ASIO_MOVE_ARG(P) p) const
  196. noexcept(
  197. noexcept(
  198. declval<typename conditional<true, T, P>::type>().query(
  199. BOOST_ASIO_MOVE_CAST(P)(p))
  200. )
  201. )
  202. -> decltype(
  203. declval<typename conditional<true, T, P>::type>().query(
  204. BOOST_ASIO_MOVE_CAST(P)(p))
  205. );
  206. };
  207. #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  208. typedef T type;
  209. #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  210. };
  211. template <typename T>
  212. struct static_proxy
  213. {
  214. #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  215. struct type
  216. {
  217. template <typename P>
  218. static constexpr auto query(BOOST_ASIO_MOVE_ARG(P) p)
  219. noexcept(
  220. noexcept(
  221. conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p))
  222. )
  223. )
  224. -> decltype(
  225. conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p))
  226. )
  227. {
  228. return T::query(BOOST_ASIO_MOVE_CAST(P)(p));
  229. }
  230. };
  231. #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  232. typedef T type;
  233. #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  234. };
  235. template <typename T>
  236. struct query_member :
  237. traits::query_member<typename proxy<T>::type, mapping_t> {};
  238. template <typename T>
  239. struct query_static_constexpr_member :
  240. traits::query_static_constexpr_member<
  241. typename static_proxy<T>::type, mapping_t> {};
  242. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  243. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  244. template <typename T>
  245. static BOOST_ASIO_CONSTEXPR
  246. typename query_static_constexpr_member<T>::result_type
  247. static_query()
  248. BOOST_ASIO_NOEXCEPT_IF((
  249. query_static_constexpr_member<T>::is_noexcept))
  250. {
  251. return query_static_constexpr_member<T>::value();
  252. }
  253. template <typename T>
  254. static BOOST_ASIO_CONSTEXPR
  255. typename traits::static_query<T, thread_t>::result_type
  256. static_query(
  257. typename enable_if<
  258. !query_static_constexpr_member<T>::is_valid
  259. >::type* = 0,
  260. typename enable_if<
  261. !query_member<T>::is_valid
  262. >::type* = 0,
  263. typename enable_if<
  264. traits::static_query<T, thread_t>::is_valid
  265. >::type* = 0) BOOST_ASIO_NOEXCEPT
  266. {
  267. return traits::static_query<T, thread_t>::value();
  268. }
  269. template <typename T>
  270. static BOOST_ASIO_CONSTEXPR
  271. typename traits::static_query<T, new_thread_t>::result_type
  272. static_query(
  273. typename enable_if<
  274. !query_static_constexpr_member<T>::is_valid
  275. >::type* = 0,
  276. typename enable_if<
  277. !query_member<T>::is_valid
  278. >::type* = 0,
  279. typename enable_if<
  280. !traits::static_query<T, thread_t>::is_valid
  281. >::type* = 0,
  282. typename enable_if<
  283. traits::static_query<T, new_thread_t>::is_valid
  284. >::type* = 0) BOOST_ASIO_NOEXCEPT
  285. {
  286. return traits::static_query<T, new_thread_t>::value();
  287. }
  288. template <typename T>
  289. static BOOST_ASIO_CONSTEXPR
  290. typename traits::static_query<T, other_t>::result_type
  291. static_query(
  292. typename enable_if<
  293. !query_static_constexpr_member<T>::is_valid
  294. >::type* = 0,
  295. typename enable_if<
  296. !query_member<T>::is_valid
  297. >::type* = 0,
  298. typename enable_if<
  299. !traits::static_query<T, thread_t>::is_valid
  300. >::type* = 0,
  301. typename enable_if<
  302. !traits::static_query<T, new_thread_t>::is_valid
  303. >::type* = 0,
  304. typename enable_if<
  305. traits::static_query<T, other_t>::is_valid
  306. >::type* = 0) BOOST_ASIO_NOEXCEPT
  307. {
  308. return traits::static_query<T, other_t>::value();
  309. }
  310. template <typename E, typename T = decltype(mapping_t::static_query<E>())>
  311. static BOOST_ASIO_CONSTEXPR const T static_query_v
  312. = mapping_t::static_query<E>();
  313. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  314. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  315. friend BOOST_ASIO_CONSTEXPR bool operator==(
  316. const mapping_t& a, const mapping_t& b)
  317. {
  318. return a.value_ == b.value_;
  319. }
  320. friend BOOST_ASIO_CONSTEXPR bool operator!=(
  321. const mapping_t& a, const mapping_t& b)
  322. {
  323. return a.value_ != b.value_;
  324. }
  325. struct convertible_from_mapping_t
  326. {
  327. BOOST_ASIO_CONSTEXPR convertible_from_mapping_t(mapping_t) {}
  328. };
  329. template <typename Executor>
  330. friend BOOST_ASIO_CONSTEXPR mapping_t query(
  331. const Executor& ex, convertible_from_mapping_t,
  332. typename enable_if<
  333. can_query<const Executor&, thread_t>::value
  334. >::type* = 0)
  335. #if !defined(__clang__) // Clang crashes if noexcept is used here.
  336. #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
  337. BOOST_ASIO_NOEXCEPT_IF((
  338. is_nothrow_query<const Executor&, mapping_t<>::thread_t>::value))
  339. #else // defined(BOOST_ASIO_MSVC)
  340. BOOST_ASIO_NOEXCEPT_IF((
  341. is_nothrow_query<const Executor&, thread_t>::value))
  342. #endif // defined(BOOST_ASIO_MSVC)
  343. #endif // !defined(__clang__)
  344. {
  345. return boost::asio::query(ex, thread_t());
  346. }
  347. template <typename Executor>
  348. friend BOOST_ASIO_CONSTEXPR mapping_t query(
  349. const Executor& ex, convertible_from_mapping_t,
  350. typename enable_if<
  351. !can_query<const Executor&, thread_t>::value
  352. >::type* = 0,
  353. typename enable_if<
  354. can_query<const Executor&, new_thread_t>::value
  355. >::type* = 0)
  356. #if !defined(__clang__) // Clang crashes if noexcept is used here.
  357. #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
  358. BOOST_ASIO_NOEXCEPT_IF((
  359. is_nothrow_query<const Executor&, mapping_t<>::new_thread_t>::value))
  360. #else // defined(BOOST_ASIO_MSVC)
  361. BOOST_ASIO_NOEXCEPT_IF((
  362. is_nothrow_query<const Executor&, new_thread_t>::value))
  363. #endif // defined(BOOST_ASIO_MSVC)
  364. #endif // !defined(__clang__)
  365. {
  366. return boost::asio::query(ex, new_thread_t());
  367. }
  368. template <typename Executor>
  369. friend BOOST_ASIO_CONSTEXPR mapping_t query(
  370. const Executor& ex, convertible_from_mapping_t,
  371. typename enable_if<
  372. !can_query<const Executor&, thread_t>::value
  373. >::type* = 0,
  374. typename enable_if<
  375. !can_query<const Executor&, new_thread_t>::value
  376. >::type* = 0,
  377. typename enable_if<
  378. can_query<const Executor&, other_t>::value
  379. >::type* = 0)
  380. #if !defined(__clang__) // Clang crashes if noexcept is used here.
  381. #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
  382. BOOST_ASIO_NOEXCEPT_IF((
  383. is_nothrow_query<const Executor&, mapping_t<>::other_t>::value))
  384. #else // defined(BOOST_ASIO_MSVC)
  385. BOOST_ASIO_NOEXCEPT_IF((
  386. is_nothrow_query<const Executor&, other_t>::value))
  387. #endif // defined(BOOST_ASIO_MSVC)
  388. #endif // !defined(__clang__)
  389. {
  390. return boost::asio::query(ex, other_t());
  391. }
  392. BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(thread_t, thread);
  393. BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(new_thread_t, new_thread);
  394. BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(other_t, other);
  395. #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
  396. static const mapping_t instance;
  397. #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR)
  398. private:
  399. int value_;
  400. };
  401. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  402. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  403. template <int I> template <typename E, typename T>
  404. const T mapping_t<I>::static_query_v;
  405. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  406. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  407. #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
  408. template <int I>
  409. const mapping_t<I> mapping_t<I>::instance;
  410. #endif
  411. template <int I>
  412. const typename mapping_t<I>::thread_t mapping_t<I>::thread;
  413. template <int I>
  414. const typename mapping_t<I>::new_thread_t mapping_t<I>::new_thread;
  415. template <int I>
  416. const typename mapping_t<I>::other_t mapping_t<I>::other;
  417. namespace mapping {
  418. template <int I = 0>
  419. struct thread_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 = (
  425. is_executor<T>::value
  426. || conditional<
  427. is_executor<T>::value,
  428. false_type,
  429. is_sender<T>
  430. >::type::value
  431. || conditional<
  432. is_executor<T>::value,
  433. false_type,
  434. is_scheduler<T>
  435. >::type::value));
  436. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  437. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
  438. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
  439. typedef mapping_t<I> polymorphic_query_result_type;
  440. BOOST_ASIO_CONSTEXPR thread_t()
  441. {
  442. }
  443. template <typename T>
  444. struct query_member :
  445. traits::query_member<
  446. typename mapping_t<I>::template proxy<T>::type, thread_t> {};
  447. template <typename T>
  448. struct query_static_constexpr_member :
  449. traits::query_static_constexpr_member<
  450. typename mapping_t<I>::template static_proxy<T>::type, thread_t> {};
  451. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  452. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  453. template <typename T>
  454. static BOOST_ASIO_CONSTEXPR
  455. typename query_static_constexpr_member<T>::result_type
  456. static_query()
  457. BOOST_ASIO_NOEXCEPT_IF((
  458. query_static_constexpr_member<T>::is_noexcept))
  459. {
  460. return query_static_constexpr_member<T>::value();
  461. }
  462. template <typename T>
  463. static BOOST_ASIO_CONSTEXPR thread_t static_query(
  464. typename enable_if<
  465. !query_static_constexpr_member<T>::is_valid
  466. >::type* = 0,
  467. typename enable_if<
  468. !query_member<T>::is_valid
  469. >::type* = 0,
  470. typename enable_if<
  471. !traits::query_free<T, thread_t>::is_valid
  472. >::type* = 0,
  473. typename enable_if<
  474. !can_query<T, new_thread_t<I> >::value
  475. >::type* = 0,
  476. typename enable_if<
  477. !can_query<T, other_t<I> >::value
  478. >::type* = 0) BOOST_ASIO_NOEXCEPT
  479. {
  480. return thread_t();
  481. }
  482. template <typename E, typename T = decltype(thread_t::static_query<E>())>
  483. static BOOST_ASIO_CONSTEXPR const T static_query_v
  484. = thread_t::static_query<E>();
  485. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  486. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  487. static BOOST_ASIO_CONSTEXPR mapping_t<I> value()
  488. {
  489. return thread_t();
  490. }
  491. friend BOOST_ASIO_CONSTEXPR bool operator==(
  492. const thread_t&, const thread_t&)
  493. {
  494. return true;
  495. }
  496. friend BOOST_ASIO_CONSTEXPR bool operator!=(
  497. const thread_t&, const thread_t&)
  498. {
  499. return false;
  500. }
  501. };
  502. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  503. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  504. template <int I> template <typename E, typename T>
  505. const T thread_t<I>::static_query_v;
  506. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  507. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  508. template <int I = 0>
  509. struct new_thread_t
  510. {
  511. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  512. template <typename T>
  513. BOOST_ASIO_STATIC_CONSTEXPR(bool,
  514. is_applicable_property_v = (
  515. is_executor<T>::value
  516. || conditional<
  517. is_executor<T>::value,
  518. false_type,
  519. is_sender<T>
  520. >::type::value
  521. || conditional<
  522. is_executor<T>::value,
  523. false_type,
  524. is_scheduler<T>
  525. >::type::value));
  526. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  527. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
  528. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
  529. typedef mapping_t<I> polymorphic_query_result_type;
  530. BOOST_ASIO_CONSTEXPR new_thread_t()
  531. {
  532. }
  533. template <typename T>
  534. struct query_member :
  535. traits::query_member<
  536. typename mapping_t<I>::template proxy<T>::type, new_thread_t> {};
  537. template <typename T>
  538. struct query_static_constexpr_member :
  539. traits::query_static_constexpr_member<
  540. typename mapping_t<I>::template static_proxy<T>::type, new_thread_t> {};
  541. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  542. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  543. template <typename T>
  544. static BOOST_ASIO_CONSTEXPR
  545. typename query_static_constexpr_member<T>::result_type
  546. static_query()
  547. BOOST_ASIO_NOEXCEPT_IF((
  548. query_static_constexpr_member<T>::is_noexcept))
  549. {
  550. return query_static_constexpr_member<T>::value();
  551. }
  552. template <typename E, typename T = decltype(new_thread_t::static_query<E>())>
  553. static BOOST_ASIO_CONSTEXPR const T static_query_v
  554. = new_thread_t::static_query<E>();
  555. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  556. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  557. static BOOST_ASIO_CONSTEXPR mapping_t<I> value()
  558. {
  559. return new_thread_t();
  560. }
  561. friend BOOST_ASIO_CONSTEXPR bool operator==(
  562. const new_thread_t&, const new_thread_t&)
  563. {
  564. return true;
  565. }
  566. friend BOOST_ASIO_CONSTEXPR bool operator!=(
  567. const new_thread_t&, const new_thread_t&)
  568. {
  569. return false;
  570. }
  571. };
  572. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  573. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  574. template <int I> template <typename E, typename T>
  575. const T new_thread_t<I>::static_query_v;
  576. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  577. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  578. template <int I>
  579. struct other_t
  580. {
  581. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  582. template <typename T>
  583. BOOST_ASIO_STATIC_CONSTEXPR(bool,
  584. is_applicable_property_v = (
  585. is_executor<T>::value
  586. || conditional<
  587. is_executor<T>::value,
  588. false_type,
  589. is_sender<T>
  590. >::type::value
  591. || conditional<
  592. is_executor<T>::value,
  593. false_type,
  594. is_scheduler<T>
  595. >::type::value));
  596. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  597. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
  598. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
  599. typedef mapping_t<I> polymorphic_query_result_type;
  600. BOOST_ASIO_CONSTEXPR other_t()
  601. {
  602. }
  603. template <typename T>
  604. struct query_member :
  605. traits::query_member<
  606. typename mapping_t<I>::template proxy<T>::type, other_t> {};
  607. template <typename T>
  608. struct query_static_constexpr_member :
  609. traits::query_static_constexpr_member<
  610. typename mapping_t<I>::template static_proxy<T>::type, other_t> {};
  611. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  612. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  613. template <typename T>
  614. static BOOST_ASIO_CONSTEXPR
  615. typename query_static_constexpr_member<T>::result_type
  616. static_query()
  617. BOOST_ASIO_NOEXCEPT_IF((
  618. query_static_constexpr_member<T>::is_noexcept))
  619. {
  620. return query_static_constexpr_member<T>::value();
  621. }
  622. template <typename E, typename T = decltype(other_t::static_query<E>())>
  623. static BOOST_ASIO_CONSTEXPR const T static_query_v
  624. = other_t::static_query<E>();
  625. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  626. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  627. static BOOST_ASIO_CONSTEXPR mapping_t<I> value()
  628. {
  629. return other_t();
  630. }
  631. friend BOOST_ASIO_CONSTEXPR bool operator==(
  632. const other_t&, const other_t&)
  633. {
  634. return true;
  635. }
  636. friend BOOST_ASIO_CONSTEXPR bool operator!=(
  637. const other_t&, const other_t&)
  638. {
  639. return false;
  640. }
  641. };
  642. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  643. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  644. template <int I> template <typename E, typename T>
  645. const T other_t<I>::static_query_v;
  646. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  647. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  648. } // namespace mapping
  649. } // namespace detail
  650. typedef detail::mapping_t<> mapping_t;
  651. #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
  652. constexpr mapping_t mapping;
  653. #else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
  654. namespace { static const mapping_t& mapping = mapping_t::instance; }
  655. #endif
  656. } // namespace execution
  657. #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  658. template <typename T>
  659. struct is_applicable_property<T, execution::mapping_t>
  660. : integral_constant<bool,
  661. execution::is_executor<T>::value
  662. || conditional<
  663. execution::is_executor<T>::value,
  664. false_type,
  665. execution::is_sender<T>
  666. >::type::value
  667. || conditional<
  668. execution::is_executor<T>::value,
  669. false_type,
  670. execution::is_scheduler<T>
  671. >::type::value>
  672. {
  673. };
  674. template <typename T>
  675. struct is_applicable_property<T, execution::mapping_t::thread_t>
  676. : integral_constant<bool,
  677. execution::is_executor<T>::value
  678. || conditional<
  679. execution::is_executor<T>::value,
  680. false_type,
  681. execution::is_sender<T>
  682. >::type::value
  683. || conditional<
  684. execution::is_executor<T>::value,
  685. false_type,
  686. execution::is_scheduler<T>
  687. >::type::value>
  688. {
  689. };
  690. template <typename T>
  691. struct is_applicable_property<T, execution::mapping_t::new_thread_t>
  692. : integral_constant<bool,
  693. execution::is_executor<T>::value
  694. || conditional<
  695. execution::is_executor<T>::value,
  696. false_type,
  697. execution::is_sender<T>
  698. >::type::value
  699. || conditional<
  700. execution::is_executor<T>::value,
  701. false_type,
  702. execution::is_scheduler<T>
  703. >::type::value>
  704. {
  705. };
  706. template <typename T>
  707. struct is_applicable_property<T, execution::mapping_t::other_t>
  708. : integral_constant<bool,
  709. execution::is_executor<T>::value
  710. || conditional<
  711. execution::is_executor<T>::value,
  712. false_type,
  713. execution::is_sender<T>
  714. >::type::value
  715. || conditional<
  716. execution::is_executor<T>::value,
  717. false_type,
  718. execution::is_scheduler<T>
  719. >::type::value>
  720. {
  721. };
  722. #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  723. namespace traits {
  724. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  725. template <typename T>
  726. struct query_free_default<T, execution::mapping_t,
  727. typename enable_if<
  728. can_query<T, execution::mapping_t::thread_t>::value
  729. >::type>
  730. {
  731. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  732. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  733. (is_nothrow_query<T, execution::mapping_t::thread_t>::value));
  734. typedef execution::mapping_t result_type;
  735. };
  736. template <typename T>
  737. struct query_free_default<T, execution::mapping_t,
  738. typename enable_if<
  739. !can_query<T, execution::mapping_t::thread_t>::value
  740. && can_query<T, execution::mapping_t::new_thread_t>::value
  741. >::type>
  742. {
  743. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  744. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  745. (is_nothrow_query<T, execution::mapping_t::new_thread_t>::value));
  746. typedef execution::mapping_t result_type;
  747. };
  748. template <typename T>
  749. struct query_free_default<T, execution::mapping_t,
  750. typename enable_if<
  751. !can_query<T, execution::mapping_t::thread_t>::value
  752. && !can_query<T, execution::mapping_t::new_thread_t>::value
  753. && can_query<T, execution::mapping_t::other_t>::value
  754. >::type>
  755. {
  756. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  757. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  758. (is_nothrow_query<T, execution::mapping_t::other_t>::value));
  759. typedef execution::mapping_t result_type;
  760. };
  761. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  762. #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  763. || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  764. template <typename T>
  765. struct static_query<T, execution::mapping_t,
  766. typename enable_if<
  767. execution::detail::mapping_t<0>::
  768. query_static_constexpr_member<T>::is_valid
  769. >::type>
  770. {
  771. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  772. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  773. typedef typename execution::detail::mapping_t<0>::
  774. query_static_constexpr_member<T>::result_type result_type;
  775. static BOOST_ASIO_CONSTEXPR result_type value()
  776. {
  777. return execution::detail::mapping_t<0>::
  778. query_static_constexpr_member<T>::value();
  779. }
  780. };
  781. template <typename T>
  782. struct static_query<T, execution::mapping_t,
  783. typename enable_if<
  784. !execution::detail::mapping_t<0>::
  785. query_static_constexpr_member<T>::is_valid
  786. && !execution::detail::mapping_t<0>::
  787. query_member<T>::is_valid
  788. && traits::static_query<T, execution::mapping_t::thread_t>::is_valid
  789. >::type>
  790. {
  791. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  792. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  793. typedef typename traits::static_query<T,
  794. execution::mapping_t::thread_t>::result_type result_type;
  795. static BOOST_ASIO_CONSTEXPR result_type value()
  796. {
  797. return traits::static_query<T, execution::mapping_t::thread_t>::value();
  798. }
  799. };
  800. template <typename T>
  801. struct static_query<T, execution::mapping_t,
  802. typename enable_if<
  803. !execution::detail::mapping_t<0>::
  804. query_static_constexpr_member<T>::is_valid
  805. && !execution::detail::mapping_t<0>::
  806. query_member<T>::is_valid
  807. && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid
  808. && traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid
  809. >::type>
  810. {
  811. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  812. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  813. typedef typename traits::static_query<T,
  814. execution::mapping_t::new_thread_t>::result_type result_type;
  815. static BOOST_ASIO_CONSTEXPR result_type value()
  816. {
  817. return traits::static_query<T, execution::mapping_t::new_thread_t>::value();
  818. }
  819. };
  820. template <typename T>
  821. struct static_query<T, execution::mapping_t,
  822. typename enable_if<
  823. !execution::detail::mapping_t<0>::
  824. query_static_constexpr_member<T>::is_valid
  825. && !execution::detail::mapping_t<0>::
  826. query_member<T>::is_valid
  827. && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid
  828. && !traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid
  829. && traits::static_query<T, execution::mapping_t::other_t>::is_valid
  830. >::type>
  831. {
  832. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  833. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  834. typedef typename traits::static_query<T,
  835. execution::mapping_t::other_t>::result_type result_type;
  836. static BOOST_ASIO_CONSTEXPR result_type value()
  837. {
  838. return traits::static_query<T, execution::mapping_t::other_t>::value();
  839. }
  840. };
  841. template <typename T>
  842. struct static_query<T, execution::mapping_t::thread_t,
  843. typename enable_if<
  844. execution::detail::mapping::thread_t<0>::
  845. query_static_constexpr_member<T>::is_valid
  846. >::type>
  847. {
  848. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  849. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  850. typedef typename execution::detail::mapping::thread_t<0>::
  851. query_static_constexpr_member<T>::result_type result_type;
  852. static BOOST_ASIO_CONSTEXPR result_type value()
  853. {
  854. return execution::detail::mapping::thread_t<0>::
  855. query_static_constexpr_member<T>::value();
  856. }
  857. };
  858. template <typename T>
  859. struct static_query<T, execution::mapping_t::thread_t,
  860. typename enable_if<
  861. !execution::detail::mapping::thread_t<0>::
  862. query_static_constexpr_member<T>::is_valid
  863. && !execution::detail::mapping::thread_t<0>::
  864. query_member<T>::is_valid
  865. && !traits::query_free<T, execution::mapping_t::thread_t>::is_valid
  866. && !can_query<T, execution::mapping_t::new_thread_t>::value
  867. && !can_query<T, execution::mapping_t::other_t>::value
  868. >::type>
  869. {
  870. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  871. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  872. typedef execution::mapping_t::thread_t result_type;
  873. static BOOST_ASIO_CONSTEXPR result_type value()
  874. {
  875. return result_type();
  876. }
  877. };
  878. template <typename T>
  879. struct static_query<T, execution::mapping_t::new_thread_t,
  880. typename enable_if<
  881. execution::detail::mapping::new_thread_t<0>::
  882. query_static_constexpr_member<T>::is_valid
  883. >::type>
  884. {
  885. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  886. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  887. typedef typename execution::detail::mapping::new_thread_t<0>::
  888. query_static_constexpr_member<T>::result_type result_type;
  889. static BOOST_ASIO_CONSTEXPR result_type value()
  890. {
  891. return execution::detail::mapping::new_thread_t<0>::
  892. query_static_constexpr_member<T>::value();
  893. }
  894. };
  895. template <typename T>
  896. struct static_query<T, execution::mapping_t::other_t,
  897. typename enable_if<
  898. execution::detail::mapping::other_t<0>::
  899. query_static_constexpr_member<T>::is_valid
  900. >::type>
  901. {
  902. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  903. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  904. typedef typename execution::detail::mapping::other_t<0>::
  905. query_static_constexpr_member<T>::result_type result_type;
  906. static BOOST_ASIO_CONSTEXPR result_type value()
  907. {
  908. return execution::detail::mapping::other_t<0>::
  909. query_static_constexpr_member<T>::value();
  910. }
  911. };
  912. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  913. // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  914. #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
  915. template <typename T>
  916. struct static_require<T, execution::mapping_t::thread_t,
  917. typename enable_if<
  918. static_query<T, execution::mapping_t::thread_t>::is_valid
  919. >::type>
  920. {
  921. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
  922. (is_same<typename static_query<T,
  923. execution::mapping_t::thread_t>::result_type,
  924. execution::mapping_t::thread_t>::value));
  925. };
  926. template <typename T>
  927. struct static_require<T, execution::mapping_t::new_thread_t,
  928. typename enable_if<
  929. static_query<T, execution::mapping_t::new_thread_t>::is_valid
  930. >::type>
  931. {
  932. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
  933. (is_same<typename static_query<T,
  934. execution::mapping_t::new_thread_t>::result_type,
  935. execution::mapping_t::new_thread_t>::value));
  936. };
  937. template <typename T>
  938. struct static_require<T, execution::mapping_t::other_t,
  939. typename enable_if<
  940. static_query<T, execution::mapping_t::other_t>::is_valid
  941. >::type>
  942. {
  943. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
  944. (is_same<typename static_query<T,
  945. execution::mapping_t::other_t>::result_type,
  946. execution::mapping_t::other_t>::value));
  947. };
  948. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
  949. } // namespace traits
  950. #endif // defined(GENERATING_DOCUMENTATION)
  951. } // namespace asio
  952. } // namespace boost
  953. #include <boost/asio/detail/pop_options.hpp>
  954. #endif // BOOST_ASIO_EXECUTION_MAPPING_HPP