blocking_adaptation.hpp 32 KB

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