allocator.hpp 9.9 KB

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