blocking_adaptation.hpp 35 KB

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