blocking.hpp 47 KB

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