blocking.hpp 43 KB

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