allocator.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. //
  2. // execution/allocator.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef ASIO_EXECUTION_ALLOCATOR_HPP
  11. #define ASIO_EXECUTION_ALLOCATOR_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include "asio/detail/type_traits.hpp"
  17. #include "asio/execution/executor.hpp"
  18. #include "asio/execution/scheduler.hpp"
  19. #include "asio/execution/sender.hpp"
  20. #include "asio/is_applicable_property.hpp"
  21. #include "asio/traits/query_static_constexpr_member.hpp"
  22. #include "asio/traits/static_query.hpp"
  23. #include "asio/detail/push_options.hpp"
  24. namespace asio {
  25. #if defined(GENERATING_DOCUMENTATION)
  26. namespace execution {
  27. /// A property to describe which allocator an executor will use to allocate the
  28. /// memory required to store a submitted function object.
  29. template <typename ProtoAllocator>
  30. struct allocator_t
  31. {
  32. /// The allocator_t property applies to executors, senders, and schedulers.
  33. template <typename T>
  34. static constexpr bool is_applicable_property_v =
  35. is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
  36. /// The allocator_t property can be required.
  37. static constexpr bool is_requirable = true;
  38. /// The allocator_t property can be preferred.
  39. static constexpr bool is_preferable = true;
  40. /// Default constructor.
  41. constexpr allocator_t();
  42. /// Obtain the allocator stored in the allocator_t property object.
  43. /**
  44. * Present only if @c ProtoAllocator is non-void.
  45. */
  46. constexpr ProtoAllocator value() const;
  47. /// Create an allocator_t object with a different allocator.
  48. /**
  49. * Present only if @c ProtoAllocator is void.
  50. */
  51. template <typename OtherAllocator>
  52. allocator_t<OtherAllocator operator()(const OtherAllocator& a);
  53. };
  54. /// A special value used for accessing the allocator_t property.
  55. constexpr allocator_t<void> allocator;
  56. } // namespace execution
  57. #else // defined(GENERATING_DOCUMENTATION)
  58. namespace execution {
  59. template <typename ProtoAllocator>
  60. struct allocator_t
  61. {
  62. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  63. template <typename T>
  64. ASIO_STATIC_CONSTEXPR(bool,
  65. is_applicable_property_v = (
  66. is_executor<T>::value
  67. || conditional<
  68. is_executor<T>::value,
  69. false_type,
  70. is_sender<T>
  71. >::type::value
  72. || conditional<
  73. is_executor<T>::value,
  74. false_type,
  75. is_scheduler<T>
  76. >::type::value));
  77. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  78. ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
  79. ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
  80. template <typename T>
  81. struct static_proxy
  82. {
  83. #if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  84. struct type
  85. {
  86. template <typename P>
  87. static constexpr auto query(ASIO_MOVE_ARG(P) p)
  88. noexcept(
  89. noexcept(
  90. conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))
  91. )
  92. )
  93. -> decltype(
  94. conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))
  95. )
  96. {
  97. return T::query(ASIO_MOVE_CAST(P)(p));
  98. }
  99. };
  100. #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  101. typedef T type;
  102. #endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  103. };
  104. template <typename T>
  105. struct query_static_constexpr_member :
  106. traits::query_static_constexpr_member<
  107. typename static_proxy<T>::type, allocator_t> {};
  108. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  109. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  110. template <typename T>
  111. static ASIO_CONSTEXPR
  112. typename query_static_constexpr_member<T>::result_type
  113. static_query()
  114. ASIO_NOEXCEPT_IF((
  115. query_static_constexpr_member<T>::is_noexcept))
  116. {
  117. return query_static_constexpr_member<T>::value();
  118. }
  119. template <typename E, typename T = decltype(allocator_t::static_query<E>())>
  120. static ASIO_CONSTEXPR const T static_query_v
  121. = allocator_t::static_query<E>();
  122. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  123. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  124. ASIO_CONSTEXPR ProtoAllocator value() const
  125. {
  126. return a_;
  127. }
  128. private:
  129. friend struct allocator_t<void>;
  130. explicit ASIO_CONSTEXPR allocator_t(const ProtoAllocator& a)
  131. : a_(a)
  132. {
  133. }
  134. ProtoAllocator a_;
  135. };
  136. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  137. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  138. template <typename ProtoAllocator> template <typename E, typename T>
  139. const T allocator_t<ProtoAllocator>::static_query_v;
  140. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  141. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  142. template <>
  143. struct allocator_t<void>
  144. {
  145. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  146. template <typename T>
  147. ASIO_STATIC_CONSTEXPR(bool,
  148. is_applicable_property_v = (
  149. is_executor<T>::value
  150. || conditional<
  151. is_executor<T>::value,
  152. false_type,
  153. is_sender<T>
  154. >::type::value
  155. || conditional<
  156. is_executor<T>::value,
  157. false_type,
  158. is_scheduler<T>
  159. >::type::value));
  160. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  161. ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
  162. ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
  163. ASIO_CONSTEXPR allocator_t()
  164. {
  165. }
  166. template <typename T>
  167. struct static_proxy
  168. {
  169. #if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  170. struct type
  171. {
  172. template <typename P>
  173. static constexpr auto query(ASIO_MOVE_ARG(P) p)
  174. noexcept(
  175. noexcept(
  176. conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))
  177. )
  178. )
  179. -> decltype(
  180. conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))
  181. )
  182. {
  183. return T::query(ASIO_MOVE_CAST(P)(p));
  184. }
  185. };
  186. #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  187. typedef T type;
  188. #endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  189. };
  190. template <typename T>
  191. struct query_static_constexpr_member :
  192. traits::query_static_constexpr_member<
  193. typename static_proxy<T>::type, allocator_t> {};
  194. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  195. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  196. template <typename T>
  197. static ASIO_CONSTEXPR
  198. typename query_static_constexpr_member<T>::result_type
  199. static_query()
  200. ASIO_NOEXCEPT_IF((
  201. query_static_constexpr_member<T>::is_noexcept))
  202. {
  203. return query_static_constexpr_member<T>::value();
  204. }
  205. template <typename E, typename T = decltype(allocator_t::static_query<E>())>
  206. static ASIO_CONSTEXPR const T static_query_v
  207. = allocator_t::static_query<E>();
  208. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  209. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  210. template <typename OtherProtoAllocator>
  211. ASIO_CONSTEXPR allocator_t<OtherProtoAllocator> operator()(
  212. const OtherProtoAllocator& a) const
  213. {
  214. return allocator_t<OtherProtoAllocator>(a);
  215. }
  216. };
  217. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  218. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  219. template <typename E, typename T>
  220. const T allocator_t<void>::static_query_v;
  221. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  222. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  223. #if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
  224. constexpr allocator_t<void> allocator;
  225. #else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
  226. template <typename T>
  227. struct allocator_instance
  228. {
  229. static allocator_t<T> instance;
  230. };
  231. template <typename T>
  232. allocator_t<T> allocator_instance<T>::instance;
  233. namespace {
  234. static const allocator_t<void>& allocator = allocator_instance<void>::instance;
  235. } // namespace
  236. #endif
  237. } // namespace execution
  238. #if !defined(ASIO_HAS_VARIABLE_TEMPLATES)
  239. template <typename T, typename ProtoAllocator>
  240. struct is_applicable_property<T, execution::allocator_t<ProtoAllocator> >
  241. : integral_constant<bool,
  242. execution::is_executor<T>::value
  243. || conditional<
  244. execution::is_executor<T>::value,
  245. false_type,
  246. execution::is_sender<T>
  247. >::type::value
  248. || conditional<
  249. execution::is_executor<T>::value,
  250. false_type,
  251. execution::is_scheduler<T>
  252. >::type::value>
  253. {
  254. };
  255. #endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)
  256. namespace traits {
  257. #if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  258. || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  259. template <typename T, typename ProtoAllocator>
  260. struct static_query<T, execution::allocator_t<ProtoAllocator>,
  261. typename enable_if<
  262. execution::allocator_t<ProtoAllocator>::template
  263. query_static_constexpr_member<T>::is_valid
  264. >::type>
  265. {
  266. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  267. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  268. typedef typename execution::allocator_t<ProtoAllocator>::template
  269. query_static_constexpr_member<T>::result_type result_type;
  270. static ASIO_CONSTEXPR result_type value()
  271. {
  272. return execution::allocator_t<ProtoAllocator>::template
  273. query_static_constexpr_member<T>::value();
  274. }
  275. };
  276. #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  277. // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  278. } // namespace traits
  279. #endif // defined(GENERATING_DOCUMENTATION)
  280. } // namespace asio
  281. #include "asio/detail/pop_options.hpp"
  282. #endif // ASIO_EXECUTION_ALLOCATOR_HPP