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