blocking_adaptation.hpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. //
  2. // execution/blocking_adaptation.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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 Executor>
  399. class adapter
  400. {
  401. public:
  402. adapter(int, const Executor& e) noexcept
  403. : executor_(e)
  404. {
  405. }
  406. adapter(const adapter& other) noexcept
  407. : executor_(other.executor_)
  408. {
  409. }
  410. adapter(adapter&& other) noexcept
  411. : executor_(static_cast<Executor&&>(other.executor_))
  412. {
  413. }
  414. template <int I>
  415. static constexpr allowed_t<I> query(blocking_adaptation_t<I>) noexcept
  416. {
  417. return allowed_t<I>();
  418. }
  419. template <int I>
  420. static constexpr allowed_t<I> query(allowed_t<I>) noexcept
  421. {
  422. return allowed_t<I>();
  423. }
  424. template <int I>
  425. static constexpr allowed_t<I> query(disallowed_t<I>) noexcept
  426. {
  427. return allowed_t<I>();
  428. }
  429. template <typename Property>
  430. enable_if_t<
  431. can_query<const Executor&, Property>::value,
  432. query_result_t<const Executor&, Property>
  433. > query(const Property& p) const
  434. noexcept(is_nothrow_query<const Executor&, Property>::value)
  435. {
  436. return boost::asio::query(executor_, p);
  437. }
  438. template <int I>
  439. Executor require(disallowed_t<I>) const noexcept
  440. {
  441. return executor_;
  442. }
  443. template <typename Property>
  444. enable_if_t<
  445. can_require<const Executor&, Property>::value,
  446. adapter<decay_t<require_result_t<const Executor&, Property>>>
  447. > require(const Property& p) const
  448. noexcept(is_nothrow_require<const Executor&, Property>::value)
  449. {
  450. return adapter<decay_t<require_result_t<const Executor&, Property>>>(
  451. 0, boost::asio::require(executor_, p));
  452. }
  453. template <typename Property>
  454. enable_if_t<
  455. can_prefer<const Executor&, Property>::value,
  456. adapter<decay_t<prefer_result_t<const Executor&, Property>>>
  457. > prefer(const Property& p) const
  458. noexcept(is_nothrow_prefer<const Executor&, Property>::value)
  459. {
  460. return adapter<decay_t<prefer_result_t<const Executor&, Property>>>(
  461. 0, boost::asio::prefer(executor_, p));
  462. }
  463. template <typename Function>
  464. enable_if_t<
  465. traits::execute_member<const Executor&, Function>::is_valid
  466. > execute(Function&& f) const
  467. {
  468. executor_.execute(static_cast<Function&&>(f));
  469. }
  470. friend bool operator==(const adapter& a, const adapter& b) noexcept
  471. {
  472. return a.executor_ == b.executor_;
  473. }
  474. friend bool operator!=(const adapter& a, const adapter& b) noexcept
  475. {
  476. return a.executor_ != b.executor_;
  477. }
  478. private:
  479. Executor executor_;
  480. };
  481. template <int I = 0>
  482. struct allowed_t
  483. {
  484. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  485. template <typename T>
  486. static constexpr bool is_applicable_property_v = is_executor<T>::value;
  487. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  488. static constexpr bool is_requirable = true;
  489. static constexpr bool is_preferable = false;
  490. typedef blocking_adaptation_t<I> polymorphic_query_result_type;
  491. constexpr allowed_t()
  492. {
  493. }
  494. template <typename T>
  495. struct query_member :
  496. traits::query_member<
  497. typename blocking_adaptation_t<I>::template proxy<T>::type,
  498. allowed_t> {};
  499. template <typename T>
  500. struct query_static_constexpr_member :
  501. traits::query_static_constexpr_member<
  502. typename blocking_adaptation_t<I>::template static_proxy<T>::type,
  503. allowed_t> {};
  504. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  505. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  506. template <typename T>
  507. static constexpr typename query_static_constexpr_member<T>::result_type
  508. static_query()
  509. noexcept(query_static_constexpr_member<T>::is_noexcept)
  510. {
  511. return query_static_constexpr_member<T>::value();
  512. }
  513. template <typename E, typename T = decltype(allowed_t::static_query<E>())>
  514. static constexpr const T static_query_v = allowed_t::static_query<E>();
  515. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  516. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  517. static constexpr blocking_adaptation_t<I> value()
  518. {
  519. return allowed_t();
  520. }
  521. friend constexpr bool operator==(const allowed_t&, const allowed_t&)
  522. {
  523. return true;
  524. }
  525. friend constexpr bool operator!=(const allowed_t&, const allowed_t&)
  526. {
  527. return false;
  528. }
  529. friend constexpr bool operator==(const allowed_t&, const disallowed_t<I>&)
  530. {
  531. return false;
  532. }
  533. friend constexpr bool operator!=(const allowed_t&, const disallowed_t<I>&)
  534. {
  535. return true;
  536. }
  537. template <typename Executor>
  538. friend adapter<Executor> require(
  539. const Executor& e, const allowed_t&,
  540. enable_if_t<
  541. is_executor<Executor>::value
  542. >* = 0)
  543. {
  544. return adapter<Executor>(0, e);
  545. }
  546. };
  547. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  548. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  549. template <int I> template <typename E, typename T>
  550. const T allowed_t<I>::static_query_v;
  551. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  552. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  553. template <typename Function>
  554. class blocking_execute_state
  555. {
  556. public:
  557. template <typename F>
  558. blocking_execute_state(F&& f)
  559. : func_(static_cast<F&&>(f)),
  560. is_complete_(false)
  561. {
  562. }
  563. template <typename Executor>
  564. void execute_and_wait(Executor&& ex)
  565. {
  566. handler h = { this };
  567. ex.execute(h);
  568. boost::asio::detail::mutex::scoped_lock lock(mutex_);
  569. while (!is_complete_)
  570. event_.wait(lock);
  571. }
  572. struct cleanup
  573. {
  574. ~cleanup()
  575. {
  576. boost::asio::detail::mutex::scoped_lock lock(state_->mutex_);
  577. state_->is_complete_ = true;
  578. state_->event_.unlock_and_signal_one_for_destruction(lock);
  579. }
  580. blocking_execute_state* state_;
  581. };
  582. struct handler
  583. {
  584. void operator()()
  585. {
  586. cleanup c = { state_ };
  587. state_->func_();
  588. }
  589. blocking_execute_state* state_;
  590. };
  591. Function func_;
  592. boost::asio::detail::mutex mutex_;
  593. boost::asio::detail::event event_;
  594. bool is_complete_;
  595. };
  596. template <typename Executor, typename Function>
  597. void blocking_execute(
  598. Executor&& ex,
  599. Function&& func)
  600. {
  601. typedef decay_t<Function> func_t;
  602. blocking_execute_state<func_t> state(static_cast<Function&&>(func));
  603. state.execute_and_wait(ex);
  604. }
  605. } // namespace blocking_adaptation
  606. } // namespace detail
  607. typedef detail::blocking_adaptation_t<> blocking_adaptation_t;
  608. constexpr blocking_adaptation_t blocking_adaptation;
  609. } // namespace execution
  610. #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  611. template <typename T>
  612. struct is_applicable_property<T, execution::blocking_adaptation_t>
  613. : integral_constant<bool, execution::is_executor<T>::value>
  614. {
  615. };
  616. template <typename T>
  617. struct is_applicable_property<T, execution::blocking_adaptation_t::disallowed_t>
  618. : integral_constant<bool, execution::is_executor<T>::value>
  619. {
  620. };
  621. template <typename T>
  622. struct is_applicable_property<T, execution::blocking_adaptation_t::allowed_t>
  623. : integral_constant<bool, execution::is_executor<T>::value>
  624. {
  625. };
  626. #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  627. namespace traits {
  628. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  629. template <typename T>
  630. struct query_free_default<T, execution::blocking_adaptation_t,
  631. enable_if_t<
  632. can_query<T, execution::blocking_adaptation_t::disallowed_t>::value
  633. >>
  634. {
  635. static constexpr bool is_valid = true;
  636. static constexpr bool is_noexcept =
  637. is_nothrow_query<T, execution::blocking_adaptation_t::disallowed_t>::value;
  638. typedef execution::blocking_adaptation_t result_type;
  639. };
  640. template <typename T>
  641. struct query_free_default<T, execution::blocking_adaptation_t,
  642. enable_if_t<
  643. !can_query<T, execution::blocking_adaptation_t::disallowed_t>::value
  644. && can_query<T, execution::blocking_adaptation_t::allowed_t>::value
  645. >>
  646. {
  647. static constexpr bool is_valid = true;
  648. static constexpr bool is_noexcept =
  649. is_nothrow_query<T, execution::blocking_adaptation_t::allowed_t>::value;
  650. typedef execution::blocking_adaptation_t result_type;
  651. };
  652. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  653. #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  654. || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  655. template <typename T>
  656. struct static_query<T, execution::blocking_adaptation_t,
  657. enable_if_t<
  658. execution::detail::blocking_adaptation_t<0>::
  659. query_static_constexpr_member<T>::is_valid
  660. >>
  661. {
  662. static constexpr bool is_valid = true;
  663. static constexpr bool is_noexcept = true;
  664. typedef typename execution::detail::blocking_adaptation_t<0>::
  665. query_static_constexpr_member<T>::result_type result_type;
  666. static constexpr result_type value()
  667. {
  668. return execution::detail::blocking_adaptation_t<0>::
  669. query_static_constexpr_member<T>::value();
  670. }
  671. };
  672. template <typename T>
  673. struct static_query<T, execution::blocking_adaptation_t,
  674. enable_if_t<
  675. !execution::detail::blocking_adaptation_t<0>::
  676. query_static_constexpr_member<T>::is_valid
  677. && !execution::detail::blocking_adaptation_t<0>::
  678. query_member<T>::is_valid
  679. && traits::static_query<T,
  680. execution::blocking_adaptation_t::disallowed_t>::is_valid
  681. >>
  682. {
  683. static constexpr bool is_valid = true;
  684. static constexpr bool is_noexcept = true;
  685. typedef typename traits::static_query<T,
  686. execution::blocking_adaptation_t::disallowed_t>::result_type result_type;
  687. static constexpr result_type value()
  688. {
  689. return traits::static_query<T,
  690. execution::blocking_adaptation_t::disallowed_t>::value();
  691. }
  692. };
  693. template <typename T>
  694. struct static_query<T, execution::blocking_adaptation_t,
  695. enable_if_t<
  696. !execution::detail::blocking_adaptation_t<0>::
  697. query_static_constexpr_member<T>::is_valid
  698. && !execution::detail::blocking_adaptation_t<0>::
  699. query_member<T>::is_valid
  700. && !traits::static_query<T,
  701. execution::blocking_adaptation_t::disallowed_t>::is_valid
  702. && traits::static_query<T,
  703. execution::blocking_adaptation_t::allowed_t>::is_valid
  704. >>
  705. {
  706. static constexpr bool is_valid = true;
  707. static constexpr bool is_noexcept = true;
  708. typedef typename traits::static_query<T,
  709. execution::blocking_adaptation_t::allowed_t>::result_type result_type;
  710. static constexpr result_type value()
  711. {
  712. return traits::static_query<T,
  713. execution::blocking_adaptation_t::allowed_t>::value();
  714. }
  715. };
  716. template <typename T>
  717. struct static_query<T, execution::blocking_adaptation_t::disallowed_t,
  718. enable_if_t<
  719. execution::detail::blocking_adaptation::disallowed_t<0>::
  720. query_static_constexpr_member<T>::is_valid
  721. >>
  722. {
  723. static constexpr bool is_valid = true;
  724. static constexpr bool is_noexcept = true;
  725. typedef typename execution::detail::blocking_adaptation::disallowed_t<0>::
  726. query_static_constexpr_member<T>::result_type result_type;
  727. static constexpr result_type value()
  728. {
  729. return execution::detail::blocking_adaptation::disallowed_t<0>::
  730. query_static_constexpr_member<T>::value();
  731. }
  732. };
  733. template <typename T>
  734. struct static_query<T, execution::blocking_adaptation_t::disallowed_t,
  735. enable_if_t<
  736. !execution::detail::blocking_adaptation::disallowed_t<0>::
  737. query_static_constexpr_member<T>::is_valid
  738. && !execution::detail::blocking_adaptation::disallowed_t<0>::
  739. query_member<T>::is_valid
  740. && !traits::query_free<T,
  741. execution::blocking_adaptation_t::disallowed_t>::is_valid
  742. && !can_query<T, execution::blocking_adaptation_t::allowed_t>::value
  743. >>
  744. {
  745. static constexpr bool is_valid = true;
  746. static constexpr bool is_noexcept = true;
  747. typedef execution::blocking_adaptation_t::disallowed_t result_type;
  748. static constexpr result_type value()
  749. {
  750. return result_type();
  751. }
  752. };
  753. template <typename T>
  754. struct static_query<T, execution::blocking_adaptation_t::allowed_t,
  755. enable_if_t<
  756. execution::detail::blocking_adaptation::allowed_t<0>::
  757. query_static_constexpr_member<T>::is_valid
  758. >>
  759. {
  760. static constexpr bool is_valid = true;
  761. static constexpr bool is_noexcept = true;
  762. typedef typename execution::detail::blocking_adaptation::allowed_t<0>::
  763. query_static_constexpr_member<T>::result_type result_type;
  764. static constexpr result_type value()
  765. {
  766. return execution::detail::blocking_adaptation::allowed_t<0>::
  767. query_static_constexpr_member<T>::value();
  768. }
  769. };
  770. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  771. // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  772. #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)
  773. template <typename T>
  774. struct require_free_default<T, execution::blocking_adaptation_t::allowed_t,
  775. enable_if_t<
  776. is_same<T, decay_t<T>>::value
  777. && execution::is_executor<T>::value
  778. >>
  779. {
  780. static constexpr bool is_valid = true;
  781. static constexpr bool is_noexcept = false;
  782. typedef execution::detail::blocking_adaptation::adapter<T> result_type;
  783. };
  784. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)
  785. #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  786. template <typename Executor>
  787. struct equality_comparable<
  788. execution::detail::blocking_adaptation::adapter<Executor>>
  789. {
  790. static constexpr bool is_valid = true;
  791. static constexpr bool is_noexcept = true;
  792. };
  793. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  794. #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  795. template <typename Executor, typename Function>
  796. struct execute_member<
  797. execution::detail::blocking_adaptation::adapter<Executor>, Function>
  798. {
  799. static constexpr bool is_valid = true;
  800. static constexpr bool is_noexcept = false;
  801. typedef void result_type;
  802. };
  803. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  804. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  805. template <typename Executor, int I>
  806. struct query_static_constexpr_member<
  807. execution::detail::blocking_adaptation::adapter<Executor>,
  808. execution::detail::blocking_adaptation_t<I>>
  809. {
  810. static constexpr bool is_valid = true;
  811. static constexpr bool is_noexcept = true;
  812. typedef execution::blocking_adaptation_t::allowed_t result_type;
  813. static constexpr result_type value() noexcept
  814. {
  815. return result_type();
  816. }
  817. };
  818. template <typename Executor, int I>
  819. struct query_static_constexpr_member<
  820. execution::detail::blocking_adaptation::adapter<Executor>,
  821. execution::detail::blocking_adaptation::allowed_t<I>>
  822. {
  823. static constexpr bool is_valid = true;
  824. static constexpr bool is_noexcept = true;
  825. typedef execution::blocking_adaptation_t::allowed_t result_type;
  826. static constexpr result_type value() noexcept
  827. {
  828. return result_type();
  829. }
  830. };
  831. template <typename Executor, int I>
  832. struct query_static_constexpr_member<
  833. execution::detail::blocking_adaptation::adapter<Executor>,
  834. execution::detail::blocking_adaptation::disallowed_t<I>>
  835. {
  836. static constexpr bool is_valid = true;
  837. static constexpr bool is_noexcept = true;
  838. typedef execution::blocking_adaptation_t::allowed_t result_type;
  839. static constexpr result_type value() noexcept
  840. {
  841. return result_type();
  842. }
  843. };
  844. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  845. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  846. template <typename Executor, typename Property>
  847. struct query_member<
  848. execution::detail::blocking_adaptation::adapter<Executor>, Property,
  849. enable_if_t<
  850. can_query<const Executor&, Property>::value
  851. >>
  852. {
  853. static constexpr bool is_valid = true;
  854. static constexpr bool is_noexcept =
  855. is_nothrow_query<Executor, Property>::value;
  856. typedef query_result_t<Executor, Property> result_type;
  857. };
  858. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  859. #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  860. template <typename Executor, int I>
  861. struct require_member<
  862. execution::detail::blocking_adaptation::adapter<Executor>,
  863. execution::detail::blocking_adaptation::disallowed_t<I>>
  864. {
  865. static constexpr bool is_valid = true;
  866. static constexpr bool is_noexcept = true;
  867. typedef Executor result_type;
  868. };
  869. template <typename Executor, typename Property>
  870. struct require_member<
  871. execution::detail::blocking_adaptation::adapter<Executor>, Property,
  872. enable_if_t<
  873. can_require<const Executor&, Property>::value
  874. >>
  875. {
  876. static constexpr bool is_valid = true;
  877. static constexpr bool is_noexcept =
  878. is_nothrow_require<Executor, Property>::value;
  879. typedef execution::detail::blocking_adaptation::adapter<
  880. decay_t<require_result_t<Executor, Property>>> result_type;
  881. };
  882. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  883. #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
  884. template <typename Executor, typename Property>
  885. struct prefer_member<
  886. execution::detail::blocking_adaptation::adapter<Executor>, Property,
  887. enable_if_t<
  888. can_prefer<const Executor&, Property>::value
  889. >>
  890. {
  891. static constexpr bool is_valid = true;
  892. static constexpr bool is_noexcept =
  893. is_nothrow_prefer<Executor, Property>::value;
  894. typedef execution::detail::blocking_adaptation::adapter<
  895. decay_t<prefer_result_t<Executor, Property>>> result_type;
  896. };
  897. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
  898. } // namespace traits
  899. #endif // defined(GENERATING_DOCUMENTATION)
  900. } // namespace asio
  901. } // namespace boost
  902. #include <boost/asio/detail/pop_options.hpp>
  903. #endif // BOOST_ASIO_EXECUTION_BLOCKING_ADAPTATION_HPP