blocking_adaptation.hpp 30 KB

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