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