blocking_adaptation.hpp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. //
  2. // execution/blocking_adaptation.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_ADAPTATION_HPP
  11. #define BOOST_ASIO_EXECUTION_BLOCKING_ADAPTATION_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/event.hpp>
  17. #include <boost/asio/detail/mutex.hpp>
  18. #include <boost/asio/detail/type_traits.hpp>
  19. #include <boost/asio/execution/execute.hpp>
  20. #include <boost/asio/execution/executor.hpp>
  21. #include <boost/asio/execution/scheduler.hpp>
  22. #include <boost/asio/execution/sender.hpp>
  23. #include <boost/asio/is_applicable_property.hpp>
  24. #include <boost/asio/prefer.hpp>
  25. #include <boost/asio/query.hpp>
  26. #include <boost/asio/require.hpp>
  27. #include <boost/asio/traits/prefer_member.hpp>
  28. #include <boost/asio/traits/query_free.hpp>
  29. #include <boost/asio/traits/query_member.hpp>
  30. #include <boost/asio/traits/query_static_constexpr_member.hpp>
  31. #include <boost/asio/traits/require_member.hpp>
  32. #include <boost/asio/traits/static_query.hpp>
  33. #include <boost/asio/traits/static_require.hpp>
  34. #include <boost/asio/detail/push_options.hpp>
  35. namespace boost {
  36. namespace asio {
  37. #if defined(GENERATING_DOCUMENTATION)
  38. namespace execution {
  39. /// A property to describe whether automatic adaptation of an executor is
  40. /// allowed in order to apply the blocking_adaptation_t::allowed_t property.
  41. struct blocking_adaptation_t
  42. {
  43. /// The blocking_adaptation_t property applies to executors, senders, and
  44. /// schedulers.
  45. template <typename T>
  46. static constexpr bool is_applicable_property_v =
  47. is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
  48. /// The top-level blocking_adaptation_t property cannot be required.
  49. static constexpr bool is_requirable = false;
  50. /// The top-level blocking_adaptation_t property cannot be preferred.
  51. static constexpr bool is_preferable = false;
  52. /// The type returned by queries against an @c any_executor.
  53. typedef blocking_adaptation_t polymorphic_query_result_type;
  54. /// A sub-property that indicates that automatic adaptation is not allowed.
  55. struct disallowed_t
  56. {
  57. /// The blocking_adaptation_t::disallowed_t property applies to executors,
  58. /// senders, and schedulers.
  59. template <typename T>
  60. static constexpr bool is_applicable_property_v =
  61. is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
  62. /// The blocking_adaptation_t::disallowed_t property can be required.
  63. static constexpr bool is_requirable = true;
  64. /// The blocking_adaptation_t::disallowed_t property can be preferred.
  65. static constexpr bool is_preferable = true;
  66. /// The type returned by queries against an @c any_executor.
  67. typedef blocking_adaptation_t polymorphic_query_result_type;
  68. /// Default constructor.
  69. constexpr disallowed_t();
  70. /// Get the value associated with a property object.
  71. /**
  72. * @returns disallowed_t();
  73. */
  74. static constexpr blocking_adaptation_t value();
  75. };
  76. /// A sub-property that indicates that automatic adaptation is allowed.
  77. struct allowed_t
  78. {
  79. /// The blocking_adaptation_t::allowed_t property applies to executors,
  80. /// senders, and 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_adaptation_t::allowed_t property can be required.
  85. static constexpr bool is_requirable = true;
  86. /// The blocking_adaptation_t::allowed_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_adaptation_t polymorphic_query_result_type;
  90. /// Default constructor.
  91. constexpr allowed_t();
  92. /// Get the value associated with a property object.
  93. /**
  94. * @returns allowed_t();
  95. */
  96. static constexpr blocking_adaptation_t value();
  97. };
  98. /// A special value used for accessing the blocking_adaptation_t::disallowed_t
  99. /// property.
  100. static constexpr disallowed_t disallowed;
  101. /// A special value used for accessing the blocking_adaptation_t::allowed_t
  102. /// property.
  103. static constexpr allowed_t allowed;
  104. /// Default constructor.
  105. constexpr blocking_adaptation_t();
  106. /// Construct from a sub-property value.
  107. constexpr blocking_adaptation_t(disallowed_t);
  108. /// Construct from a sub-property value.
  109. constexpr blocking_adaptation_t(allowed_t);
  110. /// Compare property values for equality.
  111. friend constexpr bool operator==(
  112. const blocking_adaptation_t& a, const blocking_adaptation_t& b) noexcept;
  113. /// Compare property values for inequality.
  114. friend constexpr bool operator!=(
  115. const blocking_adaptation_t& a, const blocking_adaptation_t& b) noexcept;
  116. };
  117. /// A special value used for accessing the blocking_adaptation_t property.
  118. constexpr blocking_adaptation_t blocking_adaptation;
  119. } // namespace execution
  120. #else // defined(GENERATING_DOCUMENTATION)
  121. namespace execution {
  122. namespace detail {
  123. namespace blocking_adaptation {
  124. template <int I> struct disallowed_t;
  125. template <int I> struct allowed_t;
  126. } // namespace blocking_adaptation
  127. template <int I = 0>
  128. struct blocking_adaptation_t
  129. {
  130. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  131. # if defined(BOOST_ASIO_NO_DEPRECATED)
  132. template <typename T>
  133. BOOST_ASIO_STATIC_CONSTEXPR(bool,
  134. is_applicable_property_v = (
  135. is_executor<T>::value));
  136. # else // defined(BOOST_ASIO_NO_DEPRECATED)
  137. template <typename T>
  138. BOOST_ASIO_STATIC_CONSTEXPR(bool,
  139. is_applicable_property_v = (
  140. is_executor<T>::value
  141. || conditional<
  142. is_executor<T>::value,
  143. false_type,
  144. is_sender<T>
  145. >::type::value
  146. || conditional<
  147. is_executor<T>::value,
  148. false_type,
  149. is_scheduler<T>
  150. >::type::value
  151. ));
  152. # endif // defined(BOOST_ASIO_NO_DEPRECATED)
  153. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  154. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
  155. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
  156. typedef blocking_adaptation_t polymorphic_query_result_type;
  157. typedef detail::blocking_adaptation::disallowed_t<I> disallowed_t;
  158. typedef detail::blocking_adaptation::allowed_t<I> allowed_t;
  159. BOOST_ASIO_CONSTEXPR blocking_adaptation_t()
  160. : value_(-1)
  161. {
  162. }
  163. BOOST_ASIO_CONSTEXPR blocking_adaptation_t(disallowed_t)
  164. : value_(0)
  165. {
  166. }
  167. BOOST_ASIO_CONSTEXPR blocking_adaptation_t(allowed_t)
  168. : value_(1)
  169. {
  170. }
  171. template <typename T>
  172. struct proxy
  173. {
  174. #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  175. struct type
  176. {
  177. template <typename P>
  178. auto query(BOOST_ASIO_MOVE_ARG(P) p) const
  179. noexcept(
  180. noexcept(
  181. declval<typename conditional<true, T, P>::type>().query(
  182. BOOST_ASIO_MOVE_CAST(P)(p))
  183. )
  184. )
  185. -> decltype(
  186. declval<typename conditional<true, T, P>::type>().query(
  187. BOOST_ASIO_MOVE_CAST(P)(p))
  188. );
  189. };
  190. #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  191. typedef T type;
  192. #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  193. };
  194. template <typename T>
  195. struct static_proxy
  196. {
  197. #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  198. struct type
  199. {
  200. template <typename P>
  201. static constexpr auto query(BOOST_ASIO_MOVE_ARG(P) p)
  202. noexcept(
  203. noexcept(
  204. conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p))
  205. )
  206. )
  207. -> decltype(
  208. conditional<true, T, P>::type::query(BOOST_ASIO_MOVE_CAST(P)(p))
  209. )
  210. {
  211. return T::query(BOOST_ASIO_MOVE_CAST(P)(p));
  212. }
  213. };
  214. #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  215. typedef T type;
  216. #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  217. };
  218. template <typename T>
  219. struct query_member :
  220. traits::query_member<typename proxy<T>::type, blocking_adaptation_t> {};
  221. template <typename T>
  222. struct query_static_constexpr_member :
  223. traits::query_static_constexpr_member<
  224. typename static_proxy<T>::type, blocking_adaptation_t> {};
  225. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  226. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  227. template <typename T>
  228. static BOOST_ASIO_CONSTEXPR
  229. typename query_static_constexpr_member<T>::result_type
  230. static_query()
  231. BOOST_ASIO_NOEXCEPT_IF((
  232. query_static_constexpr_member<T>::is_noexcept))
  233. {
  234. return query_static_constexpr_member<T>::value();
  235. }
  236. template <typename T>
  237. static BOOST_ASIO_CONSTEXPR
  238. typename traits::static_query<T, disallowed_t>::result_type
  239. static_query(
  240. typename enable_if<
  241. !query_static_constexpr_member<T>::is_valid
  242. >::type* = 0,
  243. typename enable_if<
  244. !query_member<T>::is_valid
  245. >::type* = 0,
  246. typename enable_if<
  247. traits::static_query<T, disallowed_t>::is_valid
  248. >::type* = 0) BOOST_ASIO_NOEXCEPT
  249. {
  250. return traits::static_query<T, disallowed_t>::value();
  251. }
  252. template <typename T>
  253. static BOOST_ASIO_CONSTEXPR
  254. typename traits::static_query<T, allowed_t>::result_type
  255. static_query(
  256. typename enable_if<
  257. !query_static_constexpr_member<T>::is_valid
  258. >::type* = 0,
  259. typename enable_if<
  260. !query_member<T>::is_valid
  261. >::type* = 0,
  262. typename enable_if<
  263. !traits::static_query<T, disallowed_t>::is_valid
  264. >::type* = 0,
  265. typename enable_if<
  266. traits::static_query<T, allowed_t>::is_valid
  267. >::type* = 0) BOOST_ASIO_NOEXCEPT
  268. {
  269. return traits::static_query<T, allowed_t>::value();
  270. }
  271. template <typename E,
  272. typename T = decltype(blocking_adaptation_t::static_query<E>())>
  273. static BOOST_ASIO_CONSTEXPR const T static_query_v
  274. = blocking_adaptation_t::static_query<E>();
  275. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  276. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  277. friend BOOST_ASIO_CONSTEXPR bool operator==(
  278. const blocking_adaptation_t& a, const blocking_adaptation_t& b)
  279. {
  280. return a.value_ == b.value_;
  281. }
  282. friend BOOST_ASIO_CONSTEXPR bool operator!=(
  283. const blocking_adaptation_t& a, const blocking_adaptation_t& b)
  284. {
  285. return a.value_ != b.value_;
  286. }
  287. struct convertible_from_blocking_adaptation_t
  288. {
  289. BOOST_ASIO_CONSTEXPR convertible_from_blocking_adaptation_t(
  290. blocking_adaptation_t)
  291. {
  292. }
  293. };
  294. template <typename Executor>
  295. friend BOOST_ASIO_CONSTEXPR blocking_adaptation_t query(
  296. const Executor& ex, convertible_from_blocking_adaptation_t,
  297. typename enable_if<
  298. can_query<const Executor&, disallowed_t>::value
  299. >::type* = 0)
  300. #if !defined(__clang__) // Clang crashes if noexcept is used here.
  301. #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
  302. BOOST_ASIO_NOEXCEPT_IF((
  303. is_nothrow_query<const Executor&,
  304. blocking_adaptation_t<>::disallowed_t>::value))
  305. #else // defined(BOOST_ASIO_MSVC)
  306. BOOST_ASIO_NOEXCEPT_IF((
  307. is_nothrow_query<const Executor&, disallowed_t>::value))
  308. #endif // defined(BOOST_ASIO_MSVC)
  309. #endif // !defined(__clang__)
  310. {
  311. return boost::asio::query(ex, disallowed_t());
  312. }
  313. template <typename Executor>
  314. friend BOOST_ASIO_CONSTEXPR blocking_adaptation_t query(
  315. const Executor& ex, convertible_from_blocking_adaptation_t,
  316. typename enable_if<
  317. !can_query<const Executor&, disallowed_t>::value
  318. >::type* = 0,
  319. typename enable_if<
  320. can_query<const Executor&, allowed_t>::value
  321. >::type* = 0)
  322. #if !defined(__clang__) // Clang crashes if noexcept is used here.
  323. #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
  324. BOOST_ASIO_NOEXCEPT_IF((
  325. is_nothrow_query<const Executor&,
  326. blocking_adaptation_t<>::allowed_t>::value))
  327. #else // defined(BOOST_ASIO_MSVC)
  328. BOOST_ASIO_NOEXCEPT_IF((
  329. is_nothrow_query<const Executor&, allowed_t>::value))
  330. #endif // defined(BOOST_ASIO_MSVC)
  331. #endif // !defined(__clang__)
  332. {
  333. return boost::asio::query(ex, allowed_t());
  334. }
  335. BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(disallowed_t, disallowed);
  336. BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(allowed_t, allowed);
  337. #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
  338. static const blocking_adaptation_t instance;
  339. #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR)
  340. private:
  341. int value_;
  342. };
  343. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  344. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  345. template <int I> template <typename E, typename T>
  346. const T blocking_adaptation_t<I>::static_query_v;
  347. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  348. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  349. #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
  350. template <int I>
  351. const blocking_adaptation_t<I> blocking_adaptation_t<I>::instance;
  352. #endif
  353. template <int I>
  354. const typename blocking_adaptation_t<I>::disallowed_t
  355. blocking_adaptation_t<I>::disallowed;
  356. template <int I>
  357. const typename blocking_adaptation_t<I>::allowed_t
  358. blocking_adaptation_t<I>::allowed;
  359. namespace blocking_adaptation {
  360. template <int I = 0>
  361. struct disallowed_t
  362. {
  363. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  364. # if defined(BOOST_ASIO_NO_DEPRECATED)
  365. template <typename T>
  366. BOOST_ASIO_STATIC_CONSTEXPR(bool,
  367. is_applicable_property_v = (
  368. is_executor<T>::value));
  369. # else // defined(BOOST_ASIO_NO_DEPRECATED)
  370. template <typename T>
  371. BOOST_ASIO_STATIC_CONSTEXPR(bool,
  372. is_applicable_property_v = (
  373. is_executor<T>::value
  374. || conditional<
  375. is_executor<T>::value,
  376. false_type,
  377. is_sender<T>
  378. >::type::value
  379. || conditional<
  380. is_executor<T>::value,
  381. false_type,
  382. is_scheduler<T>
  383. >::type::value
  384. ));
  385. # endif // defined(BOOST_ASIO_NO_DEPRECATED)
  386. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  387. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
  388. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
  389. typedef blocking_adaptation_t<I> polymorphic_query_result_type;
  390. BOOST_ASIO_CONSTEXPR disallowed_t()
  391. {
  392. }
  393. template <typename T>
  394. struct query_member :
  395. traits::query_member<
  396. typename blocking_adaptation_t<I>::template proxy<T>::type,
  397. disallowed_t> {};
  398. template <typename T>
  399. struct query_static_constexpr_member :
  400. traits::query_static_constexpr_member<
  401. typename blocking_adaptation_t<I>::template static_proxy<T>::type,
  402. disallowed_t> {};
  403. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  404. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  405. template <typename T>
  406. static BOOST_ASIO_CONSTEXPR
  407. typename query_static_constexpr_member<T>::result_type
  408. static_query()
  409. BOOST_ASIO_NOEXCEPT_IF((
  410. query_static_constexpr_member<T>::is_noexcept))
  411. {
  412. return query_static_constexpr_member<T>::value();
  413. }
  414. template <typename T>
  415. static BOOST_ASIO_CONSTEXPR disallowed_t static_query(
  416. typename enable_if<
  417. !query_static_constexpr_member<T>::is_valid
  418. >::type* = 0,
  419. typename enable_if<
  420. !query_member<T>::is_valid
  421. >::type* = 0,
  422. typename enable_if<
  423. !traits::query_free<T, disallowed_t>::is_valid
  424. >::type* = 0,
  425. typename enable_if<
  426. !can_query<T, allowed_t<I> >::value
  427. >::type* = 0) BOOST_ASIO_NOEXCEPT
  428. {
  429. return disallowed_t();
  430. }
  431. template <typename E, typename T = decltype(disallowed_t::static_query<E>())>
  432. static BOOST_ASIO_CONSTEXPR const T static_query_v
  433. = disallowed_t::static_query<E>();
  434. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  435. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  436. static BOOST_ASIO_CONSTEXPR blocking_adaptation_t<I> value()
  437. {
  438. return disallowed_t();
  439. }
  440. friend BOOST_ASIO_CONSTEXPR bool operator==(
  441. const disallowed_t&, const disallowed_t&)
  442. {
  443. return true;
  444. }
  445. friend BOOST_ASIO_CONSTEXPR bool operator!=(
  446. const disallowed_t&, const disallowed_t&)
  447. {
  448. return false;
  449. }
  450. };
  451. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  452. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  453. template <int I> template <typename E, typename T>
  454. const T disallowed_t<I>::static_query_v;
  455. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  456. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  457. template <typename Executor>
  458. class adapter
  459. {
  460. public:
  461. adapter(int, const Executor& e) BOOST_ASIO_NOEXCEPT
  462. : executor_(e)
  463. {
  464. }
  465. adapter(const adapter& other) BOOST_ASIO_NOEXCEPT
  466. : executor_(other.executor_)
  467. {
  468. }
  469. #if defined(BOOST_ASIO_HAS_MOVE)
  470. adapter(adapter&& other) BOOST_ASIO_NOEXCEPT
  471. : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_))
  472. {
  473. }
  474. #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  475. template <int I>
  476. static BOOST_ASIO_CONSTEXPR allowed_t<I> query(
  477. blocking_adaptation_t<I>) BOOST_ASIO_NOEXCEPT
  478. {
  479. return allowed_t<I>();
  480. }
  481. template <int I>
  482. static BOOST_ASIO_CONSTEXPR allowed_t<I> query(
  483. allowed_t<I>) BOOST_ASIO_NOEXCEPT
  484. {
  485. return allowed_t<I>();
  486. }
  487. template <int I>
  488. static BOOST_ASIO_CONSTEXPR allowed_t<I> query(
  489. disallowed_t<I>) BOOST_ASIO_NOEXCEPT
  490. {
  491. return allowed_t<I>();
  492. }
  493. template <typename Property>
  494. typename enable_if<
  495. can_query<const Executor&, Property>::value,
  496. typename query_result<const Executor&, Property>::type
  497. >::type query(const Property& p) const
  498. BOOST_ASIO_NOEXCEPT_IF((
  499. is_nothrow_query<const Executor&, Property>::value))
  500. {
  501. return boost::asio::query(executor_, p);
  502. }
  503. template <int I>
  504. Executor require(disallowed_t<I>) const BOOST_ASIO_NOEXCEPT
  505. {
  506. return executor_;
  507. }
  508. template <typename Property>
  509. typename enable_if<
  510. can_require<const Executor&, Property>::value,
  511. adapter<typename decay<
  512. typename require_result<const Executor&, Property>::type
  513. >::type>
  514. >::type require(const Property& p) const
  515. BOOST_ASIO_NOEXCEPT_IF((
  516. is_nothrow_require<const Executor&, Property>::value))
  517. {
  518. return adapter<typename decay<
  519. typename require_result<const Executor&, Property>::type
  520. >::type>(0, boost::asio::require(executor_, p));
  521. }
  522. template <typename Property>
  523. typename enable_if<
  524. can_prefer<const Executor&, Property>::value,
  525. adapter<typename decay<
  526. typename prefer_result<const Executor&, Property>::type
  527. >::type>
  528. >::type prefer(const Property& p) const
  529. BOOST_ASIO_NOEXCEPT_IF((
  530. is_nothrow_prefer<const Executor&, Property>::value))
  531. {
  532. return adapter<typename decay<
  533. typename prefer_result<const Executor&, Property>::type
  534. >::type>(0, boost::asio::prefer(executor_, p));
  535. }
  536. template <typename Function>
  537. typename enable_if<
  538. #if defined(BOOST_ASIO_NO_DEPRECATED)
  539. traits::execute_member<const Executor&, Function>::is_valid
  540. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  541. execution::can_execute<const Executor&, Function>::value
  542. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  543. >::type execute(BOOST_ASIO_MOVE_ARG(Function) f) const
  544. {
  545. #if defined(BOOST_ASIO_NO_DEPRECATED)
  546. executor_.execute(BOOST_ASIO_MOVE_CAST(Function)(f));
  547. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  548. execution::execute(executor_, BOOST_ASIO_MOVE_CAST(Function)(f));
  549. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  550. }
  551. friend bool operator==(const adapter& a, const adapter& b) BOOST_ASIO_NOEXCEPT
  552. {
  553. return a.executor_ == b.executor_;
  554. }
  555. friend bool operator!=(const adapter& a, const adapter& b) BOOST_ASIO_NOEXCEPT
  556. {
  557. return a.executor_ != b.executor_;
  558. }
  559. private:
  560. Executor executor_;
  561. };
  562. template <int I = 0>
  563. struct allowed_t
  564. {
  565. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  566. # if defined(BOOST_ASIO_NO_DEPRECATED)
  567. template <typename T>
  568. BOOST_ASIO_STATIC_CONSTEXPR(bool,
  569. is_applicable_property_v = (
  570. is_executor<T>::value));
  571. # else // defined(BOOST_ASIO_NO_DEPRECATED)
  572. template <typename T>
  573. BOOST_ASIO_STATIC_CONSTEXPR(bool,
  574. is_applicable_property_v = (
  575. is_executor<T>::value
  576. || conditional<
  577. is_executor<T>::value,
  578. false_type,
  579. is_sender<T>
  580. >::type::value
  581. || conditional<
  582. is_executor<T>::value,
  583. false_type,
  584. is_scheduler<T>
  585. >::type::value
  586. ));
  587. # endif // defined(BOOST_ASIO_NO_DEPRECATED)
  588. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  589. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
  590. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
  591. typedef blocking_adaptation_t<I> polymorphic_query_result_type;
  592. BOOST_ASIO_CONSTEXPR allowed_t()
  593. {
  594. }
  595. template <typename T>
  596. struct query_member :
  597. traits::query_member<
  598. typename blocking_adaptation_t<I>::template proxy<T>::type,
  599. allowed_t> {};
  600. template <typename T>
  601. struct query_static_constexpr_member :
  602. traits::query_static_constexpr_member<
  603. typename blocking_adaptation_t<I>::template static_proxy<T>::type,
  604. allowed_t> {};
  605. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  606. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  607. template <typename T>
  608. static BOOST_ASIO_CONSTEXPR
  609. typename query_static_constexpr_member<T>::result_type
  610. static_query()
  611. BOOST_ASIO_NOEXCEPT_IF((
  612. query_static_constexpr_member<T>::is_noexcept))
  613. {
  614. return query_static_constexpr_member<T>::value();
  615. }
  616. template <typename E, typename T = decltype(allowed_t::static_query<E>())>
  617. static BOOST_ASIO_CONSTEXPR const T static_query_v
  618. = allowed_t::static_query<E>();
  619. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  620. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  621. static BOOST_ASIO_CONSTEXPR blocking_adaptation_t<I> value()
  622. {
  623. return allowed_t();
  624. }
  625. friend BOOST_ASIO_CONSTEXPR bool operator==(
  626. const allowed_t&, const allowed_t&)
  627. {
  628. return true;
  629. }
  630. friend BOOST_ASIO_CONSTEXPR bool operator!=(
  631. const allowed_t&, const allowed_t&)
  632. {
  633. return false;
  634. }
  635. template <typename Executor>
  636. friend adapter<Executor> require(
  637. const Executor& e, const allowed_t&,
  638. typename enable_if<
  639. is_executor<Executor>::value
  640. >::type* = 0)
  641. {
  642. return adapter<Executor>(0, e);
  643. }
  644. };
  645. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  646. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  647. template <int I> template <typename E, typename T>
  648. const T allowed_t<I>::static_query_v;
  649. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  650. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  651. template <typename Function>
  652. class blocking_execute_state
  653. {
  654. public:
  655. template <typename F>
  656. blocking_execute_state(BOOST_ASIO_MOVE_ARG(F) f)
  657. : func_(BOOST_ASIO_MOVE_CAST(F)(f)),
  658. is_complete_(false)
  659. {
  660. }
  661. template <typename Executor>
  662. void execute_and_wait(BOOST_ASIO_MOVE_ARG(Executor) ex)
  663. {
  664. handler h = { this };
  665. #if defined(BOOST_ASIO_NO_DEPRECATED)
  666. ex.execute(h);
  667. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  668. execution::execute(BOOST_ASIO_MOVE_CAST(Executor)(ex), h);
  669. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  670. boost::asio::detail::mutex::scoped_lock lock(mutex_);
  671. while (!is_complete_)
  672. event_.wait(lock);
  673. }
  674. struct cleanup
  675. {
  676. ~cleanup()
  677. {
  678. boost::asio::detail::mutex::scoped_lock lock(state_->mutex_);
  679. state_->is_complete_ = true;
  680. state_->event_.unlock_and_signal_one_for_destruction(lock);
  681. }
  682. blocking_execute_state* state_;
  683. };
  684. struct handler
  685. {
  686. void operator()()
  687. {
  688. cleanup c = { state_ };
  689. state_->func_();
  690. }
  691. blocking_execute_state* state_;
  692. };
  693. Function func_;
  694. boost::asio::detail::mutex mutex_;
  695. boost::asio::detail::event event_;
  696. bool is_complete_;
  697. };
  698. template <typename Executor, typename Function>
  699. void blocking_execute(
  700. BOOST_ASIO_MOVE_ARG(Executor) ex,
  701. BOOST_ASIO_MOVE_ARG(Function) func)
  702. {
  703. typedef typename decay<Function>::type func_t;
  704. blocking_execute_state<func_t> state(BOOST_ASIO_MOVE_CAST(Function)(func));
  705. state.execute_and_wait(ex);
  706. }
  707. } // namespace blocking_adaptation
  708. } // namespace detail
  709. typedef detail::blocking_adaptation_t<> blocking_adaptation_t;
  710. #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
  711. constexpr blocking_adaptation_t blocking_adaptation;
  712. #else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
  713. namespace { static const blocking_adaptation_t&
  714. blocking_adaptation = blocking_adaptation_t::instance; }
  715. #endif
  716. } // namespace execution
  717. #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  718. template <typename T>
  719. struct is_applicable_property<T, execution::blocking_adaptation_t>
  720. : integral_constant<bool,
  721. execution::is_executor<T>::value
  722. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  723. || conditional<
  724. execution::is_executor<T>::value,
  725. false_type,
  726. execution::is_sender<T>
  727. >::type::value
  728. || conditional<
  729. execution::is_executor<T>::value,
  730. false_type,
  731. execution::is_scheduler<T>
  732. >::type::value
  733. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  734. >
  735. {
  736. };
  737. template <typename T>
  738. struct is_applicable_property<T, execution::blocking_adaptation_t::disallowed_t>
  739. : integral_constant<bool,
  740. execution::is_executor<T>::value
  741. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  742. || conditional<
  743. execution::is_executor<T>::value,
  744. false_type,
  745. execution::is_sender<T>
  746. >::type::value
  747. || conditional<
  748. execution::is_executor<T>::value,
  749. false_type,
  750. execution::is_scheduler<T>
  751. >::type::value
  752. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  753. >
  754. {
  755. };
  756. template <typename T>
  757. struct is_applicable_property<T, execution::blocking_adaptation_t::allowed_t>
  758. : integral_constant<bool,
  759. execution::is_executor<T>::value
  760. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  761. || conditional<
  762. execution::is_executor<T>::value,
  763. false_type,
  764. execution::is_sender<T>
  765. >::type::value
  766. || conditional<
  767. execution::is_executor<T>::value,
  768. false_type,
  769. execution::is_scheduler<T>
  770. >::type::value
  771. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  772. >
  773. {
  774. };
  775. #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  776. namespace traits {
  777. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  778. template <typename T>
  779. struct query_free_default<T, execution::blocking_adaptation_t,
  780. typename enable_if<
  781. can_query<T, execution::blocking_adaptation_t::disallowed_t>::value
  782. >::type>
  783. {
  784. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  785. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (is_nothrow_query<T,
  786. execution::blocking_adaptation_t::disallowed_t>::value));
  787. typedef execution::blocking_adaptation_t result_type;
  788. };
  789. template <typename T>
  790. struct query_free_default<T, execution::blocking_adaptation_t,
  791. typename enable_if<
  792. !can_query<T, execution::blocking_adaptation_t::disallowed_t>::value
  793. && can_query<T, execution::blocking_adaptation_t::allowed_t>::value
  794. >::type>
  795. {
  796. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  797. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  798. (is_nothrow_query<T, execution::blocking_adaptation_t::allowed_t>::value));
  799. typedef execution::blocking_adaptation_t result_type;
  800. };
  801. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  802. #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  803. || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  804. template <typename T>
  805. struct static_query<T, execution::blocking_adaptation_t,
  806. typename enable_if<
  807. execution::detail::blocking_adaptation_t<0>::
  808. query_static_constexpr_member<T>::is_valid
  809. >::type>
  810. {
  811. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  812. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  813. typedef typename execution::detail::blocking_adaptation_t<0>::
  814. query_static_constexpr_member<T>::result_type result_type;
  815. static BOOST_ASIO_CONSTEXPR result_type value()
  816. {
  817. return execution::detail::blocking_adaptation_t<0>::
  818. query_static_constexpr_member<T>::value();
  819. }
  820. };
  821. template <typename T>
  822. struct static_query<T, execution::blocking_adaptation_t,
  823. typename enable_if<
  824. !execution::detail::blocking_adaptation_t<0>::
  825. query_static_constexpr_member<T>::is_valid
  826. && !execution::detail::blocking_adaptation_t<0>::
  827. query_member<T>::is_valid
  828. && traits::static_query<T,
  829. execution::blocking_adaptation_t::disallowed_t>::is_valid
  830. >::type>
  831. {
  832. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  833. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  834. typedef typename traits::static_query<T,
  835. execution::blocking_adaptation_t::disallowed_t>::result_type result_type;
  836. static BOOST_ASIO_CONSTEXPR result_type value()
  837. {
  838. return traits::static_query<T,
  839. execution::blocking_adaptation_t::disallowed_t>::value();
  840. }
  841. };
  842. template <typename T>
  843. struct static_query<T, execution::blocking_adaptation_t,
  844. typename enable_if<
  845. !execution::detail::blocking_adaptation_t<0>::
  846. query_static_constexpr_member<T>::is_valid
  847. && !execution::detail::blocking_adaptation_t<0>::
  848. query_member<T>::is_valid
  849. && !traits::static_query<T,
  850. execution::blocking_adaptation_t::disallowed_t>::is_valid
  851. && traits::static_query<T,
  852. execution::blocking_adaptation_t::allowed_t>::is_valid
  853. >::type>
  854. {
  855. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  856. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  857. typedef typename traits::static_query<T,
  858. execution::blocking_adaptation_t::allowed_t>::result_type result_type;
  859. static BOOST_ASIO_CONSTEXPR result_type value()
  860. {
  861. return traits::static_query<T,
  862. execution::blocking_adaptation_t::allowed_t>::value();
  863. }
  864. };
  865. template <typename T>
  866. struct static_query<T, execution::blocking_adaptation_t::disallowed_t,
  867. typename enable_if<
  868. execution::detail::blocking_adaptation::disallowed_t<0>::
  869. query_static_constexpr_member<T>::is_valid
  870. >::type>
  871. {
  872. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  873. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  874. typedef typename execution::detail::blocking_adaptation::disallowed_t<0>::
  875. query_static_constexpr_member<T>::result_type result_type;
  876. static BOOST_ASIO_CONSTEXPR result_type value()
  877. {
  878. return execution::detail::blocking_adaptation::disallowed_t<0>::
  879. query_static_constexpr_member<T>::value();
  880. }
  881. };
  882. template <typename T>
  883. struct static_query<T, execution::blocking_adaptation_t::disallowed_t,
  884. typename enable_if<
  885. !execution::detail::blocking_adaptation::disallowed_t<0>::
  886. query_static_constexpr_member<T>::is_valid
  887. && !execution::detail::blocking_adaptation::disallowed_t<0>::
  888. query_member<T>::is_valid
  889. && !traits::query_free<T,
  890. execution::blocking_adaptation_t::disallowed_t>::is_valid
  891. && !can_query<T, execution::blocking_adaptation_t::allowed_t>::value
  892. >::type>
  893. {
  894. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  895. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  896. typedef execution::blocking_adaptation_t::disallowed_t result_type;
  897. static BOOST_ASIO_CONSTEXPR result_type value()
  898. {
  899. return result_type();
  900. }
  901. };
  902. template <typename T>
  903. struct static_query<T, execution::blocking_adaptation_t::allowed_t,
  904. typename enable_if<
  905. execution::detail::blocking_adaptation::allowed_t<0>::
  906. query_static_constexpr_member<T>::is_valid
  907. >::type>
  908. {
  909. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  910. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  911. typedef typename execution::detail::blocking_adaptation::allowed_t<0>::
  912. query_static_constexpr_member<T>::result_type result_type;
  913. static BOOST_ASIO_CONSTEXPR result_type value()
  914. {
  915. return execution::detail::blocking_adaptation::allowed_t<0>::
  916. query_static_constexpr_member<T>::value();
  917. }
  918. };
  919. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  920. // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  921. #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
  922. template <typename T>
  923. struct static_require<T, execution::blocking_adaptation_t::disallowed_t,
  924. typename enable_if<
  925. static_query<T, execution::blocking_adaptation_t::disallowed_t>::is_valid
  926. >::type>
  927. {
  928. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
  929. (is_same<typename static_query<T,
  930. execution::blocking_adaptation_t::disallowed_t>::result_type,
  931. execution::blocking_adaptation_t::disallowed_t>::value));
  932. };
  933. template <typename T>
  934. struct static_require<T, execution::blocking_adaptation_t::allowed_t,
  935. typename enable_if<
  936. static_query<T, execution::blocking_adaptation_t::allowed_t>::is_valid
  937. >::type>
  938. {
  939. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
  940. (is_same<typename static_query<T,
  941. execution::blocking_adaptation_t::allowed_t>::result_type,
  942. execution::blocking_adaptation_t::allowed_t>::value));
  943. };
  944. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
  945. #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)
  946. template <typename T>
  947. struct require_free_default<T, execution::blocking_adaptation_t::allowed_t,
  948. typename enable_if<
  949. is_same<T, typename decay<T>::type>::value
  950. && execution::is_executor<T>::value
  951. >::type>
  952. {
  953. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  954. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  955. typedef execution::detail::blocking_adaptation::adapter<T> result_type;
  956. };
  957. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)
  958. #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  959. template <typename Executor>
  960. struct equality_comparable<
  961. execution::detail::blocking_adaptation::adapter<Executor> >
  962. {
  963. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  964. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  965. };
  966. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  967. #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  968. template <typename Executor, typename Function>
  969. struct execute_member<
  970. execution::detail::blocking_adaptation::adapter<Executor>, Function>
  971. {
  972. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  973. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  974. typedef void result_type;
  975. };
  976. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  977. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  978. template <typename Executor, int I>
  979. struct query_static_constexpr_member<
  980. execution::detail::blocking_adaptation::adapter<Executor>,
  981. execution::detail::blocking_adaptation_t<I> >
  982. {
  983. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  984. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  985. typedef execution::blocking_adaptation_t::allowed_t result_type;
  986. static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT
  987. {
  988. return result_type();
  989. }
  990. };
  991. template <typename Executor, int I>
  992. struct query_static_constexpr_member<
  993. execution::detail::blocking_adaptation::adapter<Executor>,
  994. execution::detail::blocking_adaptation::allowed_t<I> >
  995. {
  996. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  997. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  998. typedef execution::blocking_adaptation_t::allowed_t result_type;
  999. static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT
  1000. {
  1001. return result_type();
  1002. }
  1003. };
  1004. template <typename Executor, int I>
  1005. struct query_static_constexpr_member<
  1006. execution::detail::blocking_adaptation::adapter<Executor>,
  1007. execution::detail::blocking_adaptation::disallowed_t<I> >
  1008. {
  1009. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  1010. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  1011. typedef execution::blocking_adaptation_t::allowed_t result_type;
  1012. static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT
  1013. {
  1014. return result_type();
  1015. }
  1016. };
  1017. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  1018. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  1019. template <typename Executor, typename Property>
  1020. struct query_member<
  1021. execution::detail::blocking_adaptation::adapter<Executor>, Property,
  1022. typename enable_if<
  1023. can_query<const Executor&, Property>::value
  1024. >::type>
  1025. {
  1026. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  1027. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  1028. (is_nothrow_query<Executor, Property>::value));
  1029. typedef typename query_result<Executor, Property>::type result_type;
  1030. };
  1031. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  1032. #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  1033. template <typename Executor, int I>
  1034. struct require_member<
  1035. execution::detail::blocking_adaptation::adapter<Executor>,
  1036. execution::detail::blocking_adaptation::disallowed_t<I> >
  1037. {
  1038. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  1039. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  1040. typedef Executor result_type;
  1041. };
  1042. template <typename Executor, typename Property>
  1043. struct require_member<
  1044. execution::detail::blocking_adaptation::adapter<Executor>, Property,
  1045. typename enable_if<
  1046. can_require<const Executor&, Property>::value
  1047. >::type>
  1048. {
  1049. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  1050. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  1051. (is_nothrow_require<Executor, Property>::value));
  1052. typedef execution::detail::blocking_adaptation::adapter<typename decay<
  1053. typename require_result<Executor, Property>::type
  1054. >::type> result_type;
  1055. };
  1056. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  1057. #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
  1058. template <typename Executor, typename Property>
  1059. struct prefer_member<
  1060. execution::detail::blocking_adaptation::adapter<Executor>, Property,
  1061. typename enable_if<
  1062. can_prefer<const Executor&, Property>::value
  1063. >::type>
  1064. {
  1065. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  1066. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  1067. (is_nothrow_prefer<Executor, Property>::value));
  1068. typedef execution::detail::blocking_adaptation::adapter<typename decay<
  1069. typename prefer_result<Executor, Property>::type
  1070. >::type> result_type;
  1071. };
  1072. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
  1073. } // namespace traits
  1074. #endif // defined(GENERATING_DOCUMENTATION)
  1075. } // namespace asio
  1076. } // namespace boost
  1077. #include <boost/asio/detail/pop_options.hpp>
  1078. #endif // BOOST_ASIO_EXECUTION_BLOCKING_ADAPTATION_HPP