blocking.hpp 45 KB

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