any_executor.hpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933
  1. //
  2. // execution/any_executor.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_ANY_EXECUTOR_HPP
  11. #define ASIO_EXECUTION_ANY_EXECUTOR_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 <new>
  17. #include <typeinfo>
  18. #include "asio/detail/assert.hpp"
  19. #include "asio/detail/atomic_count.hpp"
  20. #include "asio/detail/cstddef.hpp"
  21. #include "asio/detail/executor_function.hpp"
  22. #include "asio/detail/memory.hpp"
  23. #include "asio/detail/non_const_lvalue.hpp"
  24. #include "asio/detail/scoped_ptr.hpp"
  25. #include "asio/detail/type_traits.hpp"
  26. #include "asio/detail/throw_exception.hpp"
  27. #include "asio/execution/bad_executor.hpp"
  28. #include "asio/execution/blocking.hpp"
  29. #include "asio/execution/executor.hpp"
  30. #include "asio/prefer.hpp"
  31. #include "asio/query.hpp"
  32. #include "asio/require.hpp"
  33. #include "asio/detail/push_options.hpp"
  34. namespace asio {
  35. #if defined(GENERATING_DOCUMENTATION)
  36. namespace execution {
  37. /// Polymorphic executor wrapper.
  38. template <typename... SupportableProperties>
  39. class any_executor
  40. {
  41. public:
  42. /// Default constructor.
  43. any_executor() noexcept;
  44. /// Construct in an empty state. Equivalent effects to default constructor.
  45. any_executor(nullptr_t) noexcept;
  46. /// Copy constructor.
  47. any_executor(const any_executor& e) noexcept;
  48. /// Move constructor.
  49. any_executor(any_executor&& e) noexcept;
  50. /// Construct to point to the same target as another any_executor.
  51. template <class... OtherSupportableProperties>
  52. any_executor(any_executor<OtherSupportableProperties...> e);
  53. /// Construct to point to the same target as another any_executor.
  54. template <class... OtherSupportableProperties>
  55. any_executor(std::nothrow_t,
  56. any_executor<OtherSupportableProperties...> e) noexcept;
  57. /// Construct to point to the same target as another any_executor.
  58. any_executor(std::nothrow_t, const any_executor& e) noexcept;
  59. /// Construct to point to the same target as another any_executor.
  60. any_executor(std::nothrow_t, any_executor&& e) noexcept;
  61. /// Construct a polymorphic wrapper for the specified executor.
  62. template <typename Executor>
  63. any_executor(Executor e);
  64. /// Construct a polymorphic wrapper for the specified executor.
  65. template <typename Executor>
  66. any_executor(std::nothrow_t, Executor e) noexcept;
  67. /// Assignment operator.
  68. any_executor& operator=(const any_executor& e) noexcept;
  69. /// Move assignment operator.
  70. any_executor& operator=(any_executor&& e) noexcept;
  71. /// Assignment operator that sets the polymorphic wrapper to the empty state.
  72. any_executor& operator=(nullptr_t);
  73. /// Assignment operator to create a polymorphic wrapper for the specified
  74. /// executor.
  75. template <typename Executor>
  76. any_executor& operator=(Executor e);
  77. /// Destructor.
  78. ~any_executor();
  79. /// Swap targets with another polymorphic wrapper.
  80. void swap(any_executor& other) noexcept;
  81. /// Obtain a polymorphic wrapper with the specified property.
  82. /**
  83. * Do not call this function directly. It is intended for use with the
  84. * asio::require and asio::prefer customisation points.
  85. *
  86. * For example:
  87. * @code execution::any_executor<execution::blocking_t::possibly_t> ex = ...;
  88. * auto ex2 = asio::requre(ex, execution::blocking.possibly); @endcode
  89. */
  90. template <typename Property>
  91. any_executor require(Property) const;
  92. /// Obtain a polymorphic wrapper with the specified property.
  93. /**
  94. * Do not call this function directly. It is intended for use with the
  95. * asio::prefer customisation point.
  96. *
  97. * For example:
  98. * @code execution::any_executor<execution::blocking_t::possibly_t> ex = ...;
  99. * auto ex2 = asio::prefer(ex, execution::blocking.possibly); @endcode
  100. */
  101. template <typename Property>
  102. any_executor prefer(Property) const;
  103. /// Obtain the value associated with the specified property.
  104. /**
  105. * Do not call this function directly. It is intended for use with the
  106. * asio::query customisation point.
  107. *
  108. * For example:
  109. * @code execution::any_executor<execution::occupancy_t> ex = ...;
  110. * size_t n = asio::query(ex, execution::occupancy); @endcode
  111. */
  112. template <typename Property>
  113. typename Property::polymorphic_query_result_type query(Property) const;
  114. /// Execute the function on the target executor.
  115. /**
  116. * Throws asio::bad_executor if the polymorphic wrapper has no target.
  117. */
  118. template <typename Function>
  119. void execute(Function&& f) const;
  120. /// Obtain the underlying execution context.
  121. /**
  122. * This function is provided for backward compatibility. It is automatically
  123. * defined when the @c SupportableProperties... list includes a property of
  124. * type <tt>execution::context_as<U></tt>, for some type <tt>U</tt>.
  125. */
  126. automatically_determined context() const;
  127. /// Determine whether the wrapper has a target executor.
  128. /**
  129. * @returns @c true if the polymorphic wrapper has a target executor,
  130. * otherwise false.
  131. */
  132. explicit operator bool() const noexcept;
  133. /// Get the type of the target executor.
  134. const type_info& target_type() const noexcept;
  135. /// Get a pointer to the target executor.
  136. template <typename Executor> Executor* target() noexcept;
  137. /// Get a pointer to the target executor.
  138. template <typename Executor> const Executor* target() const noexcept;
  139. };
  140. /// Equality operator.
  141. /**
  142. * @relates any_executor
  143. */
  144. template <typename... SupportableProperties>
  145. bool operator==(const any_executor<SupportableProperties...>& a,
  146. const any_executor<SupportableProperties...>& b) noexcept;
  147. /// Equality operator.
  148. /**
  149. * @relates any_executor
  150. */
  151. template <typename... SupportableProperties>
  152. bool operator==(const any_executor<SupportableProperties...>& a,
  153. nullptr_t) noexcept;
  154. /// Equality operator.
  155. /**
  156. * @relates any_executor
  157. */
  158. template <typename... SupportableProperties>
  159. bool operator==(nullptr_t,
  160. const any_executor<SupportableProperties...>& b) noexcept;
  161. /// Inequality operator.
  162. /**
  163. * @relates any_executor
  164. */
  165. template <typename... SupportableProperties>
  166. bool operator!=(const any_executor<SupportableProperties...>& a,
  167. const any_executor<SupportableProperties...>& b) noexcept;
  168. /// Inequality operator.
  169. /**
  170. * @relates any_executor
  171. */
  172. template <typename... SupportableProperties>
  173. bool operator!=(const any_executor<SupportableProperties...>& a,
  174. nullptr_t) noexcept;
  175. /// Inequality operator.
  176. /**
  177. * @relates any_executor
  178. */
  179. template <typename... SupportableProperties>
  180. bool operator!=(nullptr_t,
  181. const any_executor<SupportableProperties...>& b) noexcept;
  182. } // namespace execution
  183. #else // defined(GENERATING_DOCUMENTATION)
  184. namespace execution {
  185. #if !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)
  186. #define ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL
  187. template <typename... SupportableProperties>
  188. class any_executor;
  189. #endif // !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)
  190. template <typename U>
  191. struct context_as_t;
  192. namespace detail {
  193. // Traits used to detect whether a property is requirable or preferable, taking
  194. // into account that T::is_requirable or T::is_preferable may not not be well
  195. // formed.
  196. template <typename T, typename = void>
  197. struct is_requirable : false_type {};
  198. template <typename T>
  199. struct is_requirable<T, enable_if_t<T::is_requirable>> : true_type {};
  200. template <typename T, typename = void>
  201. struct is_preferable : false_type {};
  202. template <typename T>
  203. struct is_preferable<T, enable_if_t<T::is_preferable>> : true_type {};
  204. // Trait used to detect context_as property, for backward compatibility.
  205. template <typename T>
  206. struct is_context_as : false_type {};
  207. template <typename U>
  208. struct is_context_as<context_as_t<U>> : true_type {};
  209. // Helper template to:
  210. // - Check if a target can supply the supportable properties.
  211. // - Find the first convertible-from-T property in the list.
  212. template <std::size_t I, typename Props>
  213. struct supportable_properties;
  214. template <std::size_t I, typename Prop>
  215. struct supportable_properties<I, void(Prop)>
  216. {
  217. template <typename T>
  218. struct is_valid_target : integral_constant<bool,
  219. (
  220. is_requirable<Prop>::value
  221. ? can_require<T, Prop>::value
  222. : true
  223. )
  224. &&
  225. (
  226. is_preferable<Prop>::value
  227. ? can_prefer<T, Prop>::value
  228. : true
  229. )
  230. &&
  231. (
  232. !is_requirable<Prop>::value && !is_preferable<Prop>::value
  233. ? can_query<T, Prop>::value
  234. : true
  235. )
  236. >
  237. {
  238. };
  239. struct found
  240. {
  241. static constexpr bool value = true;
  242. typedef Prop type;
  243. typedef typename Prop::polymorphic_query_result_type query_result_type;
  244. static constexpr std::size_t index = I;
  245. };
  246. struct not_found
  247. {
  248. static constexpr bool value = false;
  249. };
  250. template <typename T>
  251. struct find_convertible_property :
  252. conditional_t<
  253. is_same<T, Prop>::value || is_convertible<T, Prop>::value,
  254. found,
  255. not_found
  256. > {};
  257. template <typename T>
  258. struct find_convertible_requirable_property :
  259. conditional_t<
  260. is_requirable<Prop>::value
  261. && (is_same<T, Prop>::value || is_convertible<T, Prop>::value),
  262. found,
  263. not_found
  264. > {};
  265. template <typename T>
  266. struct find_convertible_preferable_property :
  267. conditional_t<
  268. is_preferable<Prop>::value
  269. && (is_same<T, Prop>::value || is_convertible<T, Prop>::value),
  270. found,
  271. not_found
  272. > {};
  273. struct find_context_as_property :
  274. conditional_t<
  275. is_context_as<Prop>::value,
  276. found,
  277. not_found
  278. > {};
  279. };
  280. template <std::size_t I, typename Head, typename... Tail>
  281. struct supportable_properties<I, void(Head, Tail...)>
  282. {
  283. template <typename T>
  284. struct is_valid_target : integral_constant<bool,
  285. (
  286. supportable_properties<I,
  287. void(Head)>::template is_valid_target<T>::value
  288. &&
  289. supportable_properties<I + 1,
  290. void(Tail...)>::template is_valid_target<T>::value
  291. )
  292. >
  293. {
  294. };
  295. template <typename T>
  296. struct find_convertible_property :
  297. conditional_t<
  298. is_convertible<T, Head>::value,
  299. typename supportable_properties<I, void(Head)>::found,
  300. typename supportable_properties<I + 1,
  301. void(Tail...)>::template find_convertible_property<T>
  302. > {};
  303. template <typename T>
  304. struct find_convertible_requirable_property :
  305. conditional_t<
  306. is_requirable<Head>::value
  307. && is_convertible<T, Head>::value,
  308. typename supportable_properties<I, void(Head)>::found,
  309. typename supportable_properties<I + 1,
  310. void(Tail...)>::template find_convertible_requirable_property<T>
  311. > {};
  312. template <typename T>
  313. struct find_convertible_preferable_property :
  314. conditional_t<
  315. is_preferable<Head>::value
  316. && is_convertible<T, Head>::value,
  317. typename supportable_properties<I, void(Head)>::found,
  318. typename supportable_properties<I + 1,
  319. void(Tail...)>::template find_convertible_preferable_property<T>
  320. > {};
  321. struct find_context_as_property :
  322. conditional_t<
  323. is_context_as<Head>::value,
  324. typename supportable_properties<I, void(Head)>::found,
  325. typename supportable_properties<I + 1,
  326. void(Tail...)>::find_context_as_property
  327. > {};
  328. };
  329. template <typename T, typename Props>
  330. struct is_valid_target_executor :
  331. conditional_t<
  332. is_executor<T>::value,
  333. typename supportable_properties<0, Props>::template is_valid_target<T>,
  334. false_type
  335. >
  336. {
  337. };
  338. template <typename Props>
  339. struct is_valid_target_executor<int, Props> : false_type
  340. {
  341. };
  342. class shared_target_executor
  343. {
  344. public:
  345. template <typename E>
  346. shared_target_executor(E&& e, decay_t<E>*& target)
  347. {
  348. impl<decay_t<E>>* i =
  349. new impl<decay_t<E>>(static_cast<E&&>(e));
  350. target = &i->ex_;
  351. impl_ = i;
  352. }
  353. template <typename E>
  354. shared_target_executor(std::nothrow_t, E&& e, decay_t<E>*& target) noexcept
  355. {
  356. impl<decay_t<E>>* i =
  357. new (std::nothrow) impl<decay_t<E>>(static_cast<E&&>(e));
  358. target = i ? &i->ex_ : 0;
  359. impl_ = i;
  360. }
  361. shared_target_executor(const shared_target_executor& other) noexcept
  362. : impl_(other.impl_)
  363. {
  364. if (impl_)
  365. asio::detail::ref_count_up(impl_->ref_count_);
  366. }
  367. shared_target_executor(shared_target_executor&& other) noexcept
  368. : impl_(other.impl_)
  369. {
  370. other.impl_ = 0;
  371. }
  372. ~shared_target_executor()
  373. {
  374. if (impl_)
  375. if (asio::detail::ref_count_down(impl_->ref_count_))
  376. delete impl_;
  377. }
  378. void* get() const noexcept
  379. {
  380. return impl_ ? impl_->get() : 0;
  381. }
  382. private:
  383. shared_target_executor& operator=(
  384. const shared_target_executor& other) = delete;
  385. shared_target_executor& operator=(
  386. shared_target_executor&& other) = delete;
  387. struct impl_base
  388. {
  389. impl_base() : ref_count_(1) {}
  390. virtual ~impl_base() {}
  391. virtual void* get() = 0;
  392. asio::detail::atomic_count ref_count_;
  393. };
  394. template <typename Executor>
  395. struct impl : impl_base
  396. {
  397. impl(Executor ex) : ex_(static_cast<Executor&&>(ex)) {}
  398. virtual void* get() { return &ex_; }
  399. Executor ex_;
  400. };
  401. impl_base* impl_;
  402. };
  403. class any_executor_base
  404. {
  405. public:
  406. any_executor_base() noexcept
  407. : object_fns_(0),
  408. target_(0),
  409. target_fns_(0)
  410. {
  411. }
  412. template <ASIO_EXECUTION_EXECUTOR Executor>
  413. any_executor_base(Executor ex, false_type)
  414. : target_fns_(target_fns_table<Executor>(
  415. any_executor_base::query_blocking(ex,
  416. can_query<const Executor&, const execution::blocking_t&>())
  417. == execution::blocking.always))
  418. {
  419. any_executor_base::construct_object(ex,
  420. integral_constant<bool,
  421. sizeof(Executor) <= sizeof(object_type)
  422. && alignment_of<Executor>::value <= alignment_of<object_type>::value
  423. >());
  424. }
  425. template <ASIO_EXECUTION_EXECUTOR Executor>
  426. any_executor_base(std::nothrow_t, Executor ex, false_type) noexcept
  427. : target_fns_(target_fns_table<Executor>(
  428. any_executor_base::query_blocking(ex,
  429. can_query<const Executor&, const execution::blocking_t&>())
  430. == execution::blocking.always))
  431. {
  432. any_executor_base::construct_object(std::nothrow, ex,
  433. integral_constant<bool,
  434. sizeof(Executor) <= sizeof(object_type)
  435. && alignment_of<Executor>::value <= alignment_of<object_type>::value
  436. >());
  437. if (target_ == 0)
  438. {
  439. object_fns_ = 0;
  440. target_fns_ = 0;
  441. }
  442. }
  443. template <ASIO_EXECUTION_EXECUTOR Executor>
  444. any_executor_base(Executor other, true_type)
  445. : object_fns_(object_fns_table<shared_target_executor>()),
  446. target_fns_(other.target_fns_)
  447. {
  448. Executor* p = 0;
  449. new (&object_) shared_target_executor(
  450. static_cast<Executor&&>(other), p);
  451. target_ = p->template target<void>();
  452. }
  453. template <ASIO_EXECUTION_EXECUTOR Executor>
  454. any_executor_base(std::nothrow_t,
  455. Executor other, true_type) noexcept
  456. : object_fns_(object_fns_table<shared_target_executor>()),
  457. target_fns_(other.target_fns_)
  458. {
  459. Executor* p = 0;
  460. new (&object_) shared_target_executor(
  461. std::nothrow, static_cast<Executor&&>(other), p);
  462. if (p)
  463. target_ = p->template target<void>();
  464. else
  465. {
  466. target_ = 0;
  467. object_fns_ = 0;
  468. target_fns_ = 0;
  469. }
  470. }
  471. any_executor_base(const any_executor_base& other) noexcept
  472. {
  473. if (!!other)
  474. {
  475. object_fns_ = other.object_fns_;
  476. target_fns_ = other.target_fns_;
  477. object_fns_->copy(*this, other);
  478. }
  479. else
  480. {
  481. object_fns_ = 0;
  482. target_ = 0;
  483. target_fns_ = 0;
  484. }
  485. }
  486. ~any_executor_base() noexcept
  487. {
  488. if (!!*this)
  489. object_fns_->destroy(*this);
  490. }
  491. any_executor_base& operator=(
  492. const any_executor_base& other) noexcept
  493. {
  494. if (this != &other)
  495. {
  496. if (!!*this)
  497. object_fns_->destroy(*this);
  498. if (!!other)
  499. {
  500. object_fns_ = other.object_fns_;
  501. target_fns_ = other.target_fns_;
  502. object_fns_->copy(*this, other);
  503. }
  504. else
  505. {
  506. object_fns_ = 0;
  507. target_ = 0;
  508. target_fns_ = 0;
  509. }
  510. }
  511. return *this;
  512. }
  513. any_executor_base& operator=(nullptr_t) noexcept
  514. {
  515. if (target_)
  516. object_fns_->destroy(*this);
  517. target_ = 0;
  518. object_fns_ = 0;
  519. target_fns_ = 0;
  520. return *this;
  521. }
  522. any_executor_base(any_executor_base&& other) noexcept
  523. {
  524. if (other.target_)
  525. {
  526. object_fns_ = other.object_fns_;
  527. target_fns_ = other.target_fns_;
  528. other.object_fns_ = 0;
  529. other.target_fns_ = 0;
  530. object_fns_->move(*this, other);
  531. other.target_ = 0;
  532. }
  533. else
  534. {
  535. object_fns_ = 0;
  536. target_ = 0;
  537. target_fns_ = 0;
  538. }
  539. }
  540. any_executor_base& operator=(
  541. any_executor_base&& other) noexcept
  542. {
  543. if (this != &other)
  544. {
  545. if (!!*this)
  546. object_fns_->destroy(*this);
  547. if (!!other)
  548. {
  549. object_fns_ = other.object_fns_;
  550. target_fns_ = other.target_fns_;
  551. other.object_fns_ = 0;
  552. other.target_fns_ = 0;
  553. object_fns_->move(*this, other);
  554. other.target_ = 0;
  555. }
  556. else
  557. {
  558. object_fns_ = 0;
  559. target_ = 0;
  560. target_fns_ = 0;
  561. }
  562. }
  563. return *this;
  564. }
  565. void swap(any_executor_base& other) noexcept
  566. {
  567. if (this != &other)
  568. {
  569. any_executor_base tmp(static_cast<any_executor_base&&>(other));
  570. other = static_cast<any_executor_base&&>(*this);
  571. *this = static_cast<any_executor_base&&>(tmp);
  572. }
  573. }
  574. template <typename F>
  575. void execute(F&& f) const
  576. {
  577. if (target_)
  578. {
  579. if (target_fns_->blocking_execute != 0)
  580. {
  581. asio::detail::non_const_lvalue<F> f2(f);
  582. target_fns_->blocking_execute(*this, function_view(f2.value));
  583. }
  584. else
  585. {
  586. target_fns_->execute(*this,
  587. function(static_cast<F&&>(f), std::allocator<void>()));
  588. }
  589. }
  590. else
  591. {
  592. bad_executor ex;
  593. asio::detail::throw_exception(ex);
  594. }
  595. }
  596. template <typename Executor>
  597. Executor* target()
  598. {
  599. return target_ && (is_same<Executor, void>::value
  600. || target_fns_->target_type() == target_type_ex<Executor>())
  601. ? static_cast<Executor*>(target_) : 0;
  602. }
  603. template <typename Executor>
  604. const Executor* target() const
  605. {
  606. return target_ && (is_same<Executor, void>::value
  607. || target_fns_->target_type() == target_type_ex<Executor>())
  608. ? static_cast<const Executor*>(target_) : 0;
  609. }
  610. #if !defined(ASIO_NO_TYPEID)
  611. const std::type_info& target_type() const
  612. {
  613. return target_ ? target_fns_->target_type() : typeid(void);
  614. }
  615. #else // !defined(ASIO_NO_TYPEID)
  616. const void* target_type() const
  617. {
  618. return target_ ? target_fns_->target_type() : 0;
  619. }
  620. #endif // !defined(ASIO_NO_TYPEID)
  621. struct unspecified_bool_type_t {};
  622. typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
  623. static void unspecified_bool_true(unspecified_bool_type_t) {}
  624. operator unspecified_bool_type() const noexcept
  625. {
  626. return target_ ? &any_executor_base::unspecified_bool_true : 0;
  627. }
  628. bool operator!() const noexcept
  629. {
  630. return target_ == 0;
  631. }
  632. protected:
  633. bool equality_helper(const any_executor_base& other) const noexcept
  634. {
  635. if (target_ == other.target_)
  636. return true;
  637. if (target_ && !other.target_)
  638. return false;
  639. if (!target_ && other.target_)
  640. return false;
  641. if (target_fns_ != other.target_fns_)
  642. return false;
  643. return target_fns_->equal(*this, other);
  644. }
  645. template <typename Ex>
  646. Ex& object()
  647. {
  648. return *static_cast<Ex*>(static_cast<void*>(&object_));
  649. }
  650. template <typename Ex>
  651. const Ex& object() const
  652. {
  653. return *static_cast<const Ex*>(static_cast<const void*>(&object_));
  654. }
  655. struct object_fns
  656. {
  657. void (*destroy)(any_executor_base&);
  658. void (*copy)(any_executor_base&, const any_executor_base&);
  659. void (*move)(any_executor_base&, any_executor_base&);
  660. const void* (*target)(const any_executor_base&);
  661. };
  662. static void destroy_shared(any_executor_base& ex)
  663. {
  664. typedef shared_target_executor type;
  665. ex.object<type>().~type();
  666. }
  667. static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2)
  668. {
  669. typedef shared_target_executor type;
  670. new (&ex1.object_) type(ex2.object<type>());
  671. ex1.target_ = ex2.target_;
  672. }
  673. static void move_shared(any_executor_base& ex1, any_executor_base& ex2)
  674. {
  675. typedef shared_target_executor type;
  676. new (&ex1.object_) type(static_cast<type&&>(ex2.object<type>()));
  677. ex1.target_ = ex2.target_;
  678. ex2.object<type>().~type();
  679. }
  680. static const void* target_shared(const any_executor_base& ex)
  681. {
  682. typedef shared_target_executor type;
  683. return ex.object<type>().get();
  684. }
  685. template <typename Obj>
  686. static const object_fns* object_fns_table(
  687. enable_if_t<
  688. is_same<Obj, shared_target_executor>::value
  689. >* = 0)
  690. {
  691. static const object_fns fns =
  692. {
  693. &any_executor_base::destroy_shared,
  694. &any_executor_base::copy_shared,
  695. &any_executor_base::move_shared,
  696. &any_executor_base::target_shared
  697. };
  698. return &fns;
  699. }
  700. template <typename Obj>
  701. static void destroy_object(any_executor_base& ex)
  702. {
  703. ex.object<Obj>().~Obj();
  704. }
  705. template <typename Obj>
  706. static void copy_object(any_executor_base& ex1, const any_executor_base& ex2)
  707. {
  708. new (&ex1.object_) Obj(ex2.object<Obj>());
  709. ex1.target_ = &ex1.object<Obj>();
  710. }
  711. template <typename Obj>
  712. static void move_object(any_executor_base& ex1, any_executor_base& ex2)
  713. {
  714. new (&ex1.object_) Obj(static_cast<Obj&&>(ex2.object<Obj>()));
  715. ex1.target_ = &ex1.object<Obj>();
  716. ex2.object<Obj>().~Obj();
  717. }
  718. template <typename Obj>
  719. static const void* target_object(const any_executor_base& ex)
  720. {
  721. return &ex.object<Obj>();
  722. }
  723. template <typename Obj>
  724. static const object_fns* object_fns_table(
  725. enable_if_t<
  726. !is_same<Obj, void>::value
  727. && !is_same<Obj, shared_target_executor>::value
  728. >* = 0)
  729. {
  730. static const object_fns fns =
  731. {
  732. &any_executor_base::destroy_object<Obj>,
  733. &any_executor_base::copy_object<Obj>,
  734. &any_executor_base::move_object<Obj>,
  735. &any_executor_base::target_object<Obj>
  736. };
  737. return &fns;
  738. }
  739. typedef asio::detail::executor_function function;
  740. typedef asio::detail::executor_function_view function_view;
  741. struct target_fns
  742. {
  743. #if !defined(ASIO_NO_TYPEID)
  744. const std::type_info& (*target_type)();
  745. #else // !defined(ASIO_NO_TYPEID)
  746. const void* (*target_type)();
  747. #endif // !defined(ASIO_NO_TYPEID)
  748. bool (*equal)(const any_executor_base&, const any_executor_base&);
  749. void (*execute)(const any_executor_base&, function&&);
  750. void (*blocking_execute)(const any_executor_base&, function_view);
  751. };
  752. #if !defined(ASIO_NO_TYPEID)
  753. template <typename Ex>
  754. static const std::type_info& target_type_ex()
  755. {
  756. return typeid(Ex);
  757. }
  758. #else // !defined(ASIO_NO_TYPEID)
  759. template <typename Ex>
  760. static const void* target_type_ex()
  761. {
  762. static int unique_id;
  763. return &unique_id;
  764. }
  765. #endif // !defined(ASIO_NO_TYPEID)
  766. template <typename Ex>
  767. static bool equal_ex(const any_executor_base& ex1,
  768. const any_executor_base& ex2)
  769. {
  770. const Ex* p1 = ex1.target<Ex>();
  771. const Ex* p2 = ex2.target<Ex>();
  772. ASIO_ASSUME(p1 != 0 && p2 != 0);
  773. return *p1 == *p2;
  774. }
  775. template <typename Ex>
  776. static void execute_ex(const any_executor_base& ex, function&& f)
  777. {
  778. const Ex* p = ex.target<Ex>();
  779. ASIO_ASSUME(p != 0);
  780. p->execute(static_cast<function&&>(f));
  781. }
  782. template <typename Ex>
  783. static void blocking_execute_ex(const any_executor_base& ex, function_view f)
  784. {
  785. const Ex* p = ex.target<Ex>();
  786. ASIO_ASSUME(p != 0);
  787. p->execute(f);
  788. }
  789. template <typename Ex>
  790. static const target_fns* target_fns_table(bool is_always_blocking,
  791. enable_if_t<
  792. !is_same<Ex, void>::value
  793. >* = 0)
  794. {
  795. static const target_fns fns_with_execute =
  796. {
  797. &any_executor_base::target_type_ex<Ex>,
  798. &any_executor_base::equal_ex<Ex>,
  799. &any_executor_base::execute_ex<Ex>,
  800. 0
  801. };
  802. static const target_fns fns_with_blocking_execute =
  803. {
  804. &any_executor_base::target_type_ex<Ex>,
  805. &any_executor_base::equal_ex<Ex>,
  806. 0,
  807. &any_executor_base::blocking_execute_ex<Ex>
  808. };
  809. return is_always_blocking ? &fns_with_blocking_execute : &fns_with_execute;
  810. }
  811. #if defined(ASIO_MSVC)
  812. # pragma warning (push)
  813. # pragma warning (disable:4702)
  814. #endif // defined(ASIO_MSVC)
  815. static void query_fn_void(void*, const void*, const void*)
  816. {
  817. bad_executor ex;
  818. asio::detail::throw_exception(ex);
  819. }
  820. template <typename Ex, class Prop>
  821. static void query_fn_non_void(void*, const void* ex, const void* prop,
  822. enable_if_t<
  823. asio::can_query<const Ex&, const Prop&>::value
  824. && is_same<typename Prop::polymorphic_query_result_type, void>::value
  825. >*)
  826. {
  827. asio::query(*static_cast<const Ex*>(ex),
  828. *static_cast<const Prop*>(prop));
  829. }
  830. template <typename Ex, class Prop>
  831. static void query_fn_non_void(void*, const void*, const void*,
  832. enable_if_t<
  833. !asio::can_query<const Ex&, const Prop&>::value
  834. && is_same<typename Prop::polymorphic_query_result_type, void>::value
  835. >*)
  836. {
  837. }
  838. template <typename Ex, class Prop>
  839. static void query_fn_non_void(void* result, const void* ex, const void* prop,
  840. enable_if_t<
  841. asio::can_query<const Ex&, const Prop&>::value
  842. && !is_same<typename Prop::polymorphic_query_result_type, void>::value
  843. && is_reference<typename Prop::polymorphic_query_result_type>::value
  844. >*)
  845. {
  846. *static_cast<remove_reference_t<
  847. typename Prop::polymorphic_query_result_type>**>(result)
  848. = &static_cast<typename Prop::polymorphic_query_result_type>(
  849. asio::query(*static_cast<const Ex*>(ex),
  850. *static_cast<const Prop*>(prop)));
  851. }
  852. template <typename Ex, class Prop>
  853. static void query_fn_non_void(void*, const void*, const void*,
  854. enable_if_t<
  855. !asio::can_query<const Ex&, const Prop&>::value
  856. && !is_same<typename Prop::polymorphic_query_result_type, void>::value
  857. && is_reference<typename Prop::polymorphic_query_result_type>::value
  858. >*)
  859. {
  860. std::terminate(); // Combination should not be possible.
  861. }
  862. template <typename Ex, class Prop>
  863. static void query_fn_non_void(void* result, const void* ex, const void* prop,
  864. enable_if_t<
  865. asio::can_query<const Ex&, const Prop&>::value
  866. && !is_same<typename Prop::polymorphic_query_result_type, void>::value
  867. && is_scalar<typename Prop::polymorphic_query_result_type>::value
  868. >*)
  869. {
  870. *static_cast<typename Prop::polymorphic_query_result_type*>(result)
  871. = static_cast<typename Prop::polymorphic_query_result_type>(
  872. asio::query(*static_cast<const Ex*>(ex),
  873. *static_cast<const Prop*>(prop)));
  874. }
  875. template <typename Ex, class Prop>
  876. static void query_fn_non_void(void* result, const void*, const void*,
  877. enable_if_t<
  878. !asio::can_query<const Ex&, const Prop&>::value
  879. && !is_same<typename Prop::polymorphic_query_result_type, void>::value
  880. && is_scalar<typename Prop::polymorphic_query_result_type>::value
  881. >*)
  882. {
  883. *static_cast<typename Prop::polymorphic_query_result_type*>(result)
  884. = typename Prop::polymorphic_query_result_type();
  885. }
  886. template <typename Ex, class Prop>
  887. static void query_fn_non_void(void* result, const void* ex, const void* prop,
  888. enable_if_t<
  889. asio::can_query<const Ex&, const Prop&>::value
  890. && !is_same<typename Prop::polymorphic_query_result_type, void>::value
  891. && !is_reference<typename Prop::polymorphic_query_result_type>::value
  892. && !is_scalar<typename Prop::polymorphic_query_result_type>::value
  893. >*)
  894. {
  895. *static_cast<typename Prop::polymorphic_query_result_type**>(result)
  896. = new typename Prop::polymorphic_query_result_type(
  897. asio::query(*static_cast<const Ex*>(ex),
  898. *static_cast<const Prop*>(prop)));
  899. }
  900. template <typename Ex, class Prop>
  901. static void query_fn_non_void(void* result, const void*, const void*, ...)
  902. {
  903. *static_cast<typename Prop::polymorphic_query_result_type**>(result)
  904. = new typename Prop::polymorphic_query_result_type();
  905. }
  906. template <typename Ex, class Prop>
  907. static void query_fn_impl(void* result, const void* ex, const void* prop,
  908. enable_if_t<
  909. is_same<Ex, void>::value
  910. >*)
  911. {
  912. query_fn_void(result, ex, prop);
  913. }
  914. template <typename Ex, class Prop>
  915. static void query_fn_impl(void* result, const void* ex, const void* prop,
  916. enable_if_t<
  917. !is_same<Ex, void>::value
  918. >*)
  919. {
  920. query_fn_non_void<Ex, Prop>(result, ex, prop, 0);
  921. }
  922. template <typename Ex, class Prop>
  923. static void query_fn(void* result, const void* ex, const void* prop)
  924. {
  925. query_fn_impl<Ex, Prop>(result, ex, prop, 0);
  926. }
  927. template <typename Poly, typename Ex, class Prop>
  928. static Poly require_fn_impl(const void*, const void*,
  929. enable_if_t<
  930. is_same<Ex, void>::value
  931. >*)
  932. {
  933. bad_executor ex;
  934. asio::detail::throw_exception(ex);
  935. return Poly();
  936. }
  937. template <typename Poly, typename Ex, class Prop>
  938. static Poly require_fn_impl(const void* ex, const void* prop,
  939. enable_if_t<
  940. !is_same<Ex, void>::value && Prop::is_requirable
  941. >*)
  942. {
  943. return asio::require(*static_cast<const Ex*>(ex),
  944. *static_cast<const Prop*>(prop));
  945. }
  946. template <typename Poly, typename Ex, class Prop>
  947. static Poly require_fn_impl(const void*, const void*, ...)
  948. {
  949. return Poly();
  950. }
  951. template <typename Poly, typename Ex, class Prop>
  952. static Poly require_fn(const void* ex, const void* prop)
  953. {
  954. return require_fn_impl<Poly, Ex, Prop>(ex, prop, 0);
  955. }
  956. template <typename Poly, typename Ex, class Prop>
  957. static Poly prefer_fn_impl(const void*, const void*,
  958. enable_if_t<
  959. is_same<Ex, void>::value
  960. >*)
  961. {
  962. bad_executor ex;
  963. asio::detail::throw_exception(ex);
  964. return Poly();
  965. }
  966. template <typename Poly, typename Ex, class Prop>
  967. static Poly prefer_fn_impl(const void* ex, const void* prop,
  968. enable_if_t<
  969. !is_same<Ex, void>::value && Prop::is_preferable
  970. >*)
  971. {
  972. return asio::prefer(*static_cast<const Ex*>(ex),
  973. *static_cast<const Prop*>(prop));
  974. }
  975. template <typename Poly, typename Ex, class Prop>
  976. static Poly prefer_fn_impl(const void*, const void*, ...)
  977. {
  978. return Poly();
  979. }
  980. template <typename Poly, typename Ex, class Prop>
  981. static Poly prefer_fn(const void* ex, const void* prop)
  982. {
  983. return prefer_fn_impl<Poly, Ex, Prop>(ex, prop, 0);
  984. }
  985. template <typename Poly>
  986. struct prop_fns
  987. {
  988. void (*query)(void*, const void*, const void*);
  989. Poly (*require)(const void*, const void*);
  990. Poly (*prefer)(const void*, const void*);
  991. };
  992. #if defined(ASIO_MSVC)
  993. # pragma warning (pop)
  994. #endif // defined(ASIO_MSVC)
  995. private:
  996. template <typename Executor>
  997. static execution::blocking_t query_blocking(const Executor& ex, true_type)
  998. {
  999. return asio::query(ex, execution::blocking);
  1000. }
  1001. template <typename Executor>
  1002. static execution::blocking_t query_blocking(const Executor&, false_type)
  1003. {
  1004. return execution::blocking_t();
  1005. }
  1006. template <typename Executor>
  1007. void construct_object(Executor& ex, true_type)
  1008. {
  1009. object_fns_ = object_fns_table<Executor>();
  1010. target_ = new (&object_) Executor(static_cast<Executor&&>(ex));
  1011. }
  1012. template <typename Executor>
  1013. void construct_object(Executor& ex, false_type)
  1014. {
  1015. object_fns_ = object_fns_table<shared_target_executor>();
  1016. Executor* p = 0;
  1017. new (&object_) shared_target_executor(
  1018. static_cast<Executor&&>(ex), p);
  1019. target_ = p;
  1020. }
  1021. template <typename Executor>
  1022. void construct_object(std::nothrow_t,
  1023. Executor& ex, true_type) noexcept
  1024. {
  1025. object_fns_ = object_fns_table<Executor>();
  1026. target_ = new (&object_) Executor(static_cast<Executor&&>(ex));
  1027. }
  1028. template <typename Executor>
  1029. void construct_object(std::nothrow_t,
  1030. Executor& ex, false_type) noexcept
  1031. {
  1032. object_fns_ = object_fns_table<shared_target_executor>();
  1033. Executor* p = 0;
  1034. new (&object_) shared_target_executor(
  1035. std::nothrow, static_cast<Executor&&>(ex), p);
  1036. target_ = p;
  1037. }
  1038. /*private:*/public:
  1039. // template <typename...> friend class any_executor;
  1040. typedef aligned_storage<
  1041. sizeof(asio::detail::shared_ptr<void>) + sizeof(void*),
  1042. alignment_of<asio::detail::shared_ptr<void>>::value
  1043. >::type object_type;
  1044. object_type object_;
  1045. const object_fns* object_fns_;
  1046. void* target_;
  1047. const target_fns* target_fns_;
  1048. };
  1049. template <typename Derived, typename Property, typename = void>
  1050. struct any_executor_context
  1051. {
  1052. };
  1053. #if !defined(ASIO_NO_TS_EXECUTORS)
  1054. template <typename Derived, typename Property>
  1055. struct any_executor_context<Derived, Property, enable_if_t<Property::value>>
  1056. {
  1057. typename Property::query_result_type context() const
  1058. {
  1059. return static_cast<const Derived*>(this)->query(typename Property::type());
  1060. }
  1061. };
  1062. #endif // !defined(ASIO_NO_TS_EXECUTORS)
  1063. } // namespace detail
  1064. template <>
  1065. class any_executor<> : public detail::any_executor_base
  1066. {
  1067. public:
  1068. any_executor() noexcept
  1069. : detail::any_executor_base()
  1070. {
  1071. }
  1072. any_executor(nullptr_t) noexcept
  1073. : detail::any_executor_base()
  1074. {
  1075. }
  1076. template <typename Executor>
  1077. any_executor(Executor ex,
  1078. enable_if_t<
  1079. conditional_t<
  1080. !is_same<Executor, any_executor>::value
  1081. && !is_base_of<detail::any_executor_base, Executor>::value,
  1082. is_executor<Executor>,
  1083. false_type
  1084. >::value
  1085. >* = 0)
  1086. : detail::any_executor_base(
  1087. static_cast<Executor&&>(ex), false_type())
  1088. {
  1089. }
  1090. template <typename Executor>
  1091. any_executor(std::nothrow_t, Executor ex,
  1092. enable_if_t<
  1093. conditional_t<
  1094. !is_same<Executor, any_executor>::value
  1095. && !is_base_of<detail::any_executor_base, Executor>::value,
  1096. is_executor<Executor>,
  1097. false_type
  1098. >::value
  1099. >* = 0) noexcept
  1100. : detail::any_executor_base(std::nothrow,
  1101. static_cast<Executor&&>(ex), false_type())
  1102. {
  1103. }
  1104. template <typename... OtherSupportableProperties>
  1105. any_executor(any_executor<OtherSupportableProperties...> other)
  1106. : detail::any_executor_base(
  1107. static_cast<const detail::any_executor_base&>(other))
  1108. {
  1109. }
  1110. template <typename... OtherSupportableProperties>
  1111. any_executor(std::nothrow_t,
  1112. any_executor<OtherSupportableProperties...> other) noexcept
  1113. : detail::any_executor_base(
  1114. static_cast<const detail::any_executor_base&>(other))
  1115. {
  1116. }
  1117. any_executor(const any_executor& other) noexcept
  1118. : detail::any_executor_base(
  1119. static_cast<const detail::any_executor_base&>(other))
  1120. {
  1121. }
  1122. any_executor(std::nothrow_t, const any_executor& other) noexcept
  1123. : detail::any_executor_base(
  1124. static_cast<const detail::any_executor_base&>(other))
  1125. {
  1126. }
  1127. any_executor& operator=(const any_executor& other) noexcept
  1128. {
  1129. if (this != &other)
  1130. {
  1131. detail::any_executor_base::operator=(
  1132. static_cast<const detail::any_executor_base&>(other));
  1133. }
  1134. return *this;
  1135. }
  1136. any_executor& operator=(nullptr_t p) noexcept
  1137. {
  1138. detail::any_executor_base::operator=(p);
  1139. return *this;
  1140. }
  1141. any_executor(any_executor&& other) noexcept
  1142. : detail::any_executor_base(
  1143. static_cast<any_executor_base&&>(
  1144. static_cast<any_executor_base&>(other)))
  1145. {
  1146. }
  1147. any_executor(std::nothrow_t, any_executor&& other) noexcept
  1148. : detail::any_executor_base(
  1149. static_cast<any_executor_base&&>(
  1150. static_cast<any_executor_base&>(other)))
  1151. {
  1152. }
  1153. any_executor& operator=(any_executor&& other) noexcept
  1154. {
  1155. if (this != &other)
  1156. {
  1157. detail::any_executor_base::operator=(
  1158. static_cast<detail::any_executor_base&&>(
  1159. static_cast<detail::any_executor_base&>(other)));
  1160. }
  1161. return *this;
  1162. }
  1163. void swap(any_executor& other) noexcept
  1164. {
  1165. detail::any_executor_base::swap(
  1166. static_cast<detail::any_executor_base&>(other));
  1167. }
  1168. using detail::any_executor_base::execute;
  1169. using detail::any_executor_base::target;
  1170. using detail::any_executor_base::target_type;
  1171. using detail::any_executor_base::operator unspecified_bool_type;
  1172. using detail::any_executor_base::operator!;
  1173. bool equality_helper(const any_executor& other) const noexcept
  1174. {
  1175. return any_executor_base::equality_helper(other);
  1176. }
  1177. template <typename AnyExecutor1, typename AnyExecutor2>
  1178. friend enable_if_t<
  1179. is_base_of<any_executor, AnyExecutor1>::value
  1180. || is_base_of<any_executor, AnyExecutor2>::value,
  1181. bool
  1182. > operator==(const AnyExecutor1& a,
  1183. const AnyExecutor2& b) noexcept
  1184. {
  1185. return static_cast<const any_executor&>(a).equality_helper(b);
  1186. }
  1187. template <typename AnyExecutor>
  1188. friend enable_if_t<
  1189. is_same<AnyExecutor, any_executor>::value,
  1190. bool
  1191. > operator==(const AnyExecutor& a, nullptr_t) noexcept
  1192. {
  1193. return !a;
  1194. }
  1195. template <typename AnyExecutor>
  1196. friend enable_if_t<
  1197. is_same<AnyExecutor, any_executor>::value,
  1198. bool
  1199. > operator==(nullptr_t, const AnyExecutor& b) noexcept
  1200. {
  1201. return !b;
  1202. }
  1203. template <typename AnyExecutor1, typename AnyExecutor2>
  1204. friend enable_if_t<
  1205. is_base_of<any_executor, AnyExecutor1>::value
  1206. || is_base_of<any_executor, AnyExecutor2>::value,
  1207. bool
  1208. > operator!=(const AnyExecutor1& a,
  1209. const AnyExecutor2& b) noexcept
  1210. {
  1211. return !static_cast<const any_executor&>(a).equality_helper(b);
  1212. }
  1213. template <typename AnyExecutor>
  1214. friend enable_if_t<
  1215. is_same<AnyExecutor, any_executor>::value,
  1216. bool
  1217. > operator!=(const AnyExecutor& a, nullptr_t) noexcept
  1218. {
  1219. return !!a;
  1220. }
  1221. template <typename AnyExecutor>
  1222. friend enable_if_t<
  1223. is_same<AnyExecutor, any_executor>::value,
  1224. bool
  1225. > operator!=(nullptr_t, const AnyExecutor& b) noexcept
  1226. {
  1227. return !!b;
  1228. }
  1229. };
  1230. inline void swap(any_executor<>& a, any_executor<>& b) noexcept
  1231. {
  1232. return a.swap(b);
  1233. }
  1234. template <typename... SupportableProperties>
  1235. class any_executor :
  1236. public detail::any_executor_base,
  1237. public detail::any_executor_context<
  1238. any_executor<SupportableProperties...>,
  1239. typename detail::supportable_properties<
  1240. 0, void(SupportableProperties...)>::find_context_as_property>
  1241. {
  1242. public:
  1243. any_executor() noexcept
  1244. : detail::any_executor_base(),
  1245. prop_fns_(prop_fns_table<void>())
  1246. {
  1247. }
  1248. any_executor(nullptr_t) noexcept
  1249. : detail::any_executor_base(),
  1250. prop_fns_(prop_fns_table<void>())
  1251. {
  1252. }
  1253. template <typename Executor>
  1254. any_executor(Executor ex,
  1255. enable_if_t<
  1256. conditional_t<
  1257. !is_same<Executor, any_executor>::value
  1258. && !is_base_of<detail::any_executor_base, Executor>::value,
  1259. detail::is_valid_target_executor<
  1260. Executor, void(SupportableProperties...)>,
  1261. false_type
  1262. >::value
  1263. >* = 0)
  1264. : detail::any_executor_base(
  1265. static_cast<Executor&&>(ex), false_type()),
  1266. prop_fns_(prop_fns_table<Executor>())
  1267. {
  1268. }
  1269. template <typename Executor>
  1270. any_executor(std::nothrow_t, Executor ex,
  1271. enable_if_t<
  1272. conditional_t<
  1273. !is_same<Executor, any_executor>::value
  1274. && !is_base_of<detail::any_executor_base, Executor>::value,
  1275. detail::is_valid_target_executor<
  1276. Executor, void(SupportableProperties...)>,
  1277. false_type
  1278. >::value
  1279. >* = 0) noexcept
  1280. : detail::any_executor_base(std::nothrow,
  1281. static_cast<Executor&&>(ex), false_type()),
  1282. prop_fns_(prop_fns_table<Executor>())
  1283. {
  1284. if (this->template target<void>() == 0)
  1285. prop_fns_ = prop_fns_table<void>();
  1286. }
  1287. template <typename... OtherSupportableProperties>
  1288. any_executor(any_executor<OtherSupportableProperties...> other,
  1289. enable_if_t<
  1290. conditional_t<
  1291. !is_same<
  1292. any_executor<OtherSupportableProperties...>,
  1293. any_executor
  1294. >::value,
  1295. typename detail::supportable_properties<
  1296. 0, void(SupportableProperties...)>::template is_valid_target<
  1297. any_executor<OtherSupportableProperties...>>,
  1298. false_type
  1299. >::value
  1300. >* = 0)
  1301. : detail::any_executor_base(
  1302. static_cast<any_executor<OtherSupportableProperties...>&&>(other),
  1303. true_type()),
  1304. prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...>>())
  1305. {
  1306. }
  1307. template <typename... OtherSupportableProperties>
  1308. any_executor(std::nothrow_t,
  1309. any_executor<OtherSupportableProperties...> other,
  1310. enable_if_t<
  1311. conditional_t<
  1312. !is_same<
  1313. any_executor<OtherSupportableProperties...>,
  1314. any_executor
  1315. >::value,
  1316. typename detail::supportable_properties<
  1317. 0, void(SupportableProperties...)>::template is_valid_target<
  1318. any_executor<OtherSupportableProperties...>>,
  1319. false_type
  1320. >::value
  1321. >* = 0) noexcept
  1322. : detail::any_executor_base(std::nothrow,
  1323. static_cast<any_executor<OtherSupportableProperties...>&&>(other),
  1324. true_type()),
  1325. prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...>>())
  1326. {
  1327. if (this->template target<void>() == 0)
  1328. prop_fns_ = prop_fns_table<void>();
  1329. }
  1330. any_executor(const any_executor& other) noexcept
  1331. : detail::any_executor_base(
  1332. static_cast<const detail::any_executor_base&>(other)),
  1333. prop_fns_(other.prop_fns_)
  1334. {
  1335. }
  1336. any_executor(std::nothrow_t, const any_executor& other) noexcept
  1337. : detail::any_executor_base(
  1338. static_cast<const detail::any_executor_base&>(other)),
  1339. prop_fns_(other.prop_fns_)
  1340. {
  1341. }
  1342. any_executor& operator=(const any_executor& other) noexcept
  1343. {
  1344. if (this != &other)
  1345. {
  1346. prop_fns_ = other.prop_fns_;
  1347. detail::any_executor_base::operator=(
  1348. static_cast<const detail::any_executor_base&>(other));
  1349. }
  1350. return *this;
  1351. }
  1352. any_executor& operator=(nullptr_t p) noexcept
  1353. {
  1354. prop_fns_ = prop_fns_table<void>();
  1355. detail::any_executor_base::operator=(p);
  1356. return *this;
  1357. }
  1358. any_executor(any_executor&& other) noexcept
  1359. : detail::any_executor_base(
  1360. static_cast<any_executor_base&&>(
  1361. static_cast<any_executor_base&>(other))),
  1362. prop_fns_(other.prop_fns_)
  1363. {
  1364. other.prop_fns_ = prop_fns_table<void>();
  1365. }
  1366. any_executor(std::nothrow_t, any_executor&& other) noexcept
  1367. : detail::any_executor_base(
  1368. static_cast<any_executor_base&&>(
  1369. static_cast<any_executor_base&>(other))),
  1370. prop_fns_(other.prop_fns_)
  1371. {
  1372. other.prop_fns_ = prop_fns_table<void>();
  1373. }
  1374. any_executor& operator=(any_executor&& other) noexcept
  1375. {
  1376. if (this != &other)
  1377. {
  1378. prop_fns_ = other.prop_fns_;
  1379. detail::any_executor_base::operator=(
  1380. static_cast<detail::any_executor_base&&>(
  1381. static_cast<detail::any_executor_base&>(other)));
  1382. }
  1383. return *this;
  1384. }
  1385. void swap(any_executor& other) noexcept
  1386. {
  1387. if (this != &other)
  1388. {
  1389. detail::any_executor_base::swap(
  1390. static_cast<detail::any_executor_base&>(other));
  1391. const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_;
  1392. other.prop_fns_ = prop_fns_;
  1393. prop_fns_ = tmp_prop_fns;
  1394. }
  1395. }
  1396. using detail::any_executor_base::execute;
  1397. using detail::any_executor_base::target;
  1398. using detail::any_executor_base::target_type;
  1399. using detail::any_executor_base::operator unspecified_bool_type;
  1400. using detail::any_executor_base::operator!;
  1401. bool equality_helper(const any_executor& other) const noexcept
  1402. {
  1403. return any_executor_base::equality_helper(other);
  1404. }
  1405. template <typename AnyExecutor1, typename AnyExecutor2>
  1406. friend enable_if_t<
  1407. is_base_of<any_executor, AnyExecutor1>::value
  1408. || is_base_of<any_executor, AnyExecutor2>::value,
  1409. bool
  1410. > operator==(const AnyExecutor1& a,
  1411. const AnyExecutor2& b) noexcept
  1412. {
  1413. return static_cast<const any_executor&>(a).equality_helper(b);
  1414. }
  1415. template <typename AnyExecutor>
  1416. friend enable_if_t<
  1417. is_same<AnyExecutor, any_executor>::value,
  1418. bool
  1419. > operator==(const AnyExecutor& a, nullptr_t) noexcept
  1420. {
  1421. return !a;
  1422. }
  1423. template <typename AnyExecutor>
  1424. friend enable_if_t<
  1425. is_same<AnyExecutor, any_executor>::value,
  1426. bool
  1427. > operator==(nullptr_t, const AnyExecutor& b) noexcept
  1428. {
  1429. return !b;
  1430. }
  1431. template <typename AnyExecutor1, typename AnyExecutor2>
  1432. friend enable_if_t<
  1433. is_base_of<any_executor, AnyExecutor1>::value
  1434. || is_base_of<any_executor, AnyExecutor2>::value,
  1435. bool
  1436. > operator!=(const AnyExecutor1& a,
  1437. const AnyExecutor2& b) noexcept
  1438. {
  1439. return !static_cast<const any_executor&>(a).equality_helper(b);
  1440. }
  1441. template <typename AnyExecutor>
  1442. friend enable_if_t<
  1443. is_same<AnyExecutor, any_executor>::value,
  1444. bool
  1445. > operator!=(const AnyExecutor& a, nullptr_t) noexcept
  1446. {
  1447. return !!a;
  1448. }
  1449. template <typename AnyExecutor>
  1450. friend enable_if_t<
  1451. is_same<AnyExecutor, any_executor>::value,
  1452. bool
  1453. > operator!=(nullptr_t, const AnyExecutor& b) noexcept
  1454. {
  1455. return !!b;
  1456. }
  1457. template <typename T>
  1458. struct find_convertible_property :
  1459. detail::supportable_properties<
  1460. 0, void(SupportableProperties...)>::template
  1461. find_convertible_property<T> {};
  1462. template <typename Property>
  1463. void query(const Property& p,
  1464. enable_if_t<
  1465. is_same<
  1466. typename find_convertible_property<Property>::query_result_type,
  1467. void
  1468. >::value
  1469. >* = 0) const
  1470. {
  1471. if (!target_)
  1472. {
  1473. bad_executor ex;
  1474. asio::detail::throw_exception(ex);
  1475. }
  1476. typedef find_convertible_property<Property> found;
  1477. prop_fns_[found::index].query(0, object_fns_->target(*this),
  1478. &static_cast<const typename found::type&>(p));
  1479. }
  1480. template <typename Property>
  1481. typename find_convertible_property<Property>::query_result_type
  1482. query(const Property& p,
  1483. enable_if_t<
  1484. !is_same<
  1485. typename find_convertible_property<Property>::query_result_type,
  1486. void
  1487. >::value
  1488. &&
  1489. is_reference<
  1490. typename find_convertible_property<Property>::query_result_type
  1491. >::value
  1492. >* = 0) const
  1493. {
  1494. if (!target_)
  1495. {
  1496. bad_executor ex;
  1497. asio::detail::throw_exception(ex);
  1498. }
  1499. typedef find_convertible_property<Property> found;
  1500. remove_reference_t<typename found::query_result_type>* result = 0;
  1501. prop_fns_[found::index].query(&result, object_fns_->target(*this),
  1502. &static_cast<const typename found::type&>(p));
  1503. return *result;
  1504. }
  1505. template <typename Property>
  1506. typename find_convertible_property<Property>::query_result_type
  1507. query(const Property& p,
  1508. enable_if_t<
  1509. !is_same<
  1510. typename find_convertible_property<Property>::query_result_type,
  1511. void
  1512. >::value
  1513. &&
  1514. is_scalar<
  1515. typename find_convertible_property<Property>::query_result_type
  1516. >::value
  1517. >* = 0) const
  1518. {
  1519. if (!target_)
  1520. {
  1521. bad_executor ex;
  1522. asio::detail::throw_exception(ex);
  1523. }
  1524. typedef find_convertible_property<Property> found;
  1525. typename found::query_result_type result;
  1526. prop_fns_[found::index].query(&result, object_fns_->target(*this),
  1527. &static_cast<const typename found::type&>(p));
  1528. return result;
  1529. }
  1530. template <typename Property>
  1531. typename find_convertible_property<Property>::query_result_type
  1532. query(const Property& p,
  1533. enable_if_t<
  1534. !is_same<
  1535. typename find_convertible_property<Property>::query_result_type,
  1536. void
  1537. >::value
  1538. &&
  1539. !is_reference<
  1540. typename find_convertible_property<Property>::query_result_type
  1541. >::value
  1542. &&
  1543. !is_scalar<
  1544. typename find_convertible_property<Property>::query_result_type
  1545. >::value
  1546. >* = 0) const
  1547. {
  1548. if (!target_)
  1549. {
  1550. bad_executor ex;
  1551. asio::detail::throw_exception(ex);
  1552. }
  1553. typedef find_convertible_property<Property> found;
  1554. typename found::query_result_type* result;
  1555. prop_fns_[found::index].query(&result, object_fns_->target(*this),
  1556. &static_cast<const typename found::type&>(p));
  1557. return *asio::detail::scoped_ptr<
  1558. typename found::query_result_type>(result);
  1559. }
  1560. template <typename T>
  1561. struct find_convertible_requirable_property :
  1562. detail::supportable_properties<
  1563. 0, void(SupportableProperties...)>::template
  1564. find_convertible_requirable_property<T> {};
  1565. template <typename Property>
  1566. any_executor require(const Property& p,
  1567. enable_if_t<
  1568. find_convertible_requirable_property<Property>::value
  1569. >* = 0) const
  1570. {
  1571. if (!target_)
  1572. {
  1573. bad_executor ex;
  1574. asio::detail::throw_exception(ex);
  1575. }
  1576. typedef find_convertible_requirable_property<Property> found;
  1577. return prop_fns_[found::index].require(object_fns_->target(*this),
  1578. &static_cast<const typename found::type&>(p));
  1579. }
  1580. template <typename T>
  1581. struct find_convertible_preferable_property :
  1582. detail::supportable_properties<
  1583. 0, void(SupportableProperties...)>::template
  1584. find_convertible_preferable_property<T> {};
  1585. template <typename Property>
  1586. any_executor prefer(const Property& p,
  1587. enable_if_t<
  1588. find_convertible_preferable_property<Property>::value
  1589. >* = 0) const
  1590. {
  1591. if (!target_)
  1592. {
  1593. bad_executor ex;
  1594. asio::detail::throw_exception(ex);
  1595. }
  1596. typedef find_convertible_preferable_property<Property> found;
  1597. return prop_fns_[found::index].prefer(object_fns_->target(*this),
  1598. &static_cast<const typename found::type&>(p));
  1599. }
  1600. //private:
  1601. template <typename Ex>
  1602. static const prop_fns<any_executor>* prop_fns_table()
  1603. {
  1604. static const prop_fns<any_executor> fns[] =
  1605. {
  1606. {
  1607. &detail::any_executor_base::query_fn<
  1608. Ex, SupportableProperties>,
  1609. &detail::any_executor_base::require_fn<
  1610. any_executor, Ex, SupportableProperties>,
  1611. &detail::any_executor_base::prefer_fn<
  1612. any_executor, Ex, SupportableProperties>
  1613. }...
  1614. };
  1615. return fns;
  1616. }
  1617. const prop_fns<any_executor>* prop_fns_;
  1618. };
  1619. template <typename... SupportableProperties>
  1620. inline void swap(any_executor<SupportableProperties...>& a,
  1621. any_executor<SupportableProperties...>& b) noexcept
  1622. {
  1623. return a.swap(b);
  1624. }
  1625. } // namespace execution
  1626. namespace traits {
  1627. #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  1628. template <typename... SupportableProperties>
  1629. struct equality_comparable<execution::any_executor<SupportableProperties...>>
  1630. {
  1631. static constexpr bool is_valid = true;
  1632. static constexpr bool is_noexcept = true;
  1633. };
  1634. #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
  1635. #if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  1636. template <typename F, typename... SupportableProperties>
  1637. struct execute_member<execution::any_executor<SupportableProperties...>, F>
  1638. {
  1639. static constexpr bool is_valid = true;
  1640. static constexpr bool is_noexcept = false;
  1641. typedef void result_type;
  1642. };
  1643. #endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
  1644. #if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  1645. template <typename Prop, typename... SupportableProperties>
  1646. struct query_member<
  1647. execution::any_executor<SupportableProperties...>, Prop,
  1648. enable_if_t<
  1649. execution::detail::supportable_properties<
  1650. 0, void(SupportableProperties...)>::template
  1651. find_convertible_property<Prop>::value
  1652. >>
  1653. {
  1654. static constexpr bool is_valid = true;
  1655. static constexpr bool is_noexcept = false;
  1656. typedef typename execution::detail::supportable_properties<
  1657. 0, void(SupportableProperties...)>::template
  1658. find_convertible_property<Prop>::query_result_type result_type;
  1659. };
  1660. #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  1661. #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  1662. template <typename Prop, typename... SupportableProperties>
  1663. struct require_member<
  1664. execution::any_executor<SupportableProperties...>, Prop,
  1665. enable_if_t<
  1666. execution::detail::supportable_properties<
  1667. 0, void(SupportableProperties...)>::template
  1668. find_convertible_requirable_property<Prop>::value
  1669. >>
  1670. {
  1671. static constexpr bool is_valid = true;
  1672. static constexpr bool is_noexcept = false;
  1673. typedef execution::any_executor<SupportableProperties...> result_type;
  1674. };
  1675. #endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  1676. #if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
  1677. template <typename Prop, typename... SupportableProperties>
  1678. struct prefer_member<
  1679. execution::any_executor<SupportableProperties...>, Prop,
  1680. enable_if_t<
  1681. execution::detail::supportable_properties<
  1682. 0, void(SupportableProperties...)>::template
  1683. find_convertible_preferable_property<Prop>::value
  1684. >>
  1685. {
  1686. static constexpr bool is_valid = true;
  1687. static constexpr bool is_noexcept = false;
  1688. typedef execution::any_executor<SupportableProperties...> result_type;
  1689. };
  1690. #endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
  1691. } // namespace traits
  1692. #endif // defined(GENERATING_DOCUMENTATION)
  1693. } // namespace asio
  1694. #include "asio/detail/pop_options.hpp"
  1695. #endif // ASIO_EXECUTION_ANY_EXECUTOR_HPP