1 1.1 joerg // -*- C++ -*- 2 1.1 joerg //===------------------------ memory_resource -----------------------------===// 3 1.1 joerg // 4 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 1.1 joerg // See https://llvm.org/LICENSE.txt for license information. 6 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 1.1 joerg // 8 1.1 joerg //===----------------------------------------------------------------------===// 9 1.1 joerg 10 1.1 joerg #ifndef _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE 11 1.1 joerg #define _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE 12 1.1 joerg 13 1.1 joerg /** 14 1.1 joerg experimental/memory_resource synopsis 15 1.1 joerg 16 1.1 joerg // C++1y 17 1.1 joerg 18 1.1 joerg namespace std { 19 1.1 joerg namespace experimental { 20 1.1 joerg inline namespace fundamentals_v1 { 21 1.1 joerg namespace pmr { 22 1.1 joerg 23 1.1 joerg class memory_resource; 24 1.1 joerg 25 1.1 joerg bool operator==(const memory_resource& a, 26 1.1 joerg const memory_resource& b) noexcept; 27 1.1 joerg bool operator!=(const memory_resource& a, 28 1.1 joerg const memory_resource& b) noexcept; 29 1.1 joerg 30 1.1 joerg template <class Tp> class polymorphic_allocator; 31 1.1 joerg 32 1.1 joerg template <class T1, class T2> 33 1.1 joerg bool operator==(const polymorphic_allocator<T1>& a, 34 1.1 joerg const polymorphic_allocator<T2>& b) noexcept; 35 1.1 joerg template <class T1, class T2> 36 1.1 joerg bool operator!=(const polymorphic_allocator<T1>& a, 37 1.1 joerg const polymorphic_allocator<T2>& b) noexcept; 38 1.1 joerg 39 1.1 joerg // The name resource_adaptor_imp is for exposition only. 40 1.1 joerg template <class Allocator> class resource_adaptor_imp; 41 1.1 joerg 42 1.1 joerg template <class Allocator> 43 1.1 joerg using resource_adaptor = resource_adaptor_imp< 44 1.1 joerg allocator_traits<Allocator>::rebind_alloc<char>>; 45 1.1 joerg 46 1.1 joerg // Global memory resources 47 1.1 joerg memory_resource* new_delete_resource() noexcept; 48 1.1 joerg memory_resource* null_memory_resource() noexcept; 49 1.1 joerg 50 1.1 joerg // The default memory resource 51 1.1 joerg memory_resource* set_default_resource(memory_resource* r) noexcept; 52 1.1 joerg memory_resource* get_default_resource() noexcept; 53 1.1 joerg 54 1.1 joerg // Standard memory resources 55 1.1 joerg struct pool_options; 56 1.1 joerg class synchronized_pool_resource; 57 1.1 joerg class unsynchronized_pool_resource; 58 1.1 joerg class monotonic_buffer_resource; 59 1.1 joerg 60 1.1 joerg } // namespace pmr 61 1.1 joerg } // namespace fundamentals_v1 62 1.1 joerg } // namespace experimental 63 1.1 joerg } // namespace std 64 1.1 joerg 65 1.1 joerg */ 66 1.1 joerg 67 1.1 joerg #include <experimental/__config> 68 1.1 joerg #include <experimental/__memory> 69 1.1 joerg #include <limits> 70 1.1 joerg #include <memory> 71 1.1 joerg #include <new> 72 1.1 joerg #include <stdexcept> 73 1.1 joerg #include <__tuple> 74 1.1 joerg #include <type_traits> 75 1.1 joerg #include <utility> 76 1.1 joerg #include <cstddef> 77 1.1 joerg #include <cstdlib> 78 1.1 joerg #include <__debug> 79 1.1 joerg 80 1.1 joerg #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 81 1.1 joerg #pragma GCC system_header 82 1.1 joerg #endif 83 1.1 joerg 84 1.1 joerg _LIBCPP_PUSH_MACROS 85 1.1 joerg #include <__undef_macros> 86 1.1 joerg 87 1.1 joerg _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR 88 1.1 joerg 89 1.1 joerg // Round __s up to next multiple of __a. 90 1.1 joerg inline _LIBCPP_INLINE_VISIBILITY 91 1.1 joerg size_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT 92 1.1 joerg { 93 1.1 joerg _LIBCPP_ASSERT(__s + __a > __s, "aligned allocation size overflows"); 94 1.1 joerg return (__s + __a - 1) & ~(__a - 1); 95 1.1 joerg } 96 1.1 joerg 97 1.1 joerg // 8.5, memory.resource 98 1.1 joerg class _LIBCPP_TYPE_VIS memory_resource 99 1.1 joerg { 100 1.1 joerg static const size_t __max_align = _LIBCPP_ALIGNOF(max_align_t); 101 1.1 joerg 102 1.1 joerg // 8.5.2, memory.resource.public 103 1.1 joerg public: 104 1.1 joerg virtual ~memory_resource() = default; 105 1.1 joerg 106 1.1 joerg _LIBCPP_INLINE_VISIBILITY 107 1.1 joerg void* allocate(size_t __bytes, size_t __align = __max_align) 108 1.1 joerg { return do_allocate(__bytes, __align); } 109 1.1 joerg 110 1.1 joerg _LIBCPP_INLINE_VISIBILITY 111 1.1 joerg void deallocate(void * __p, size_t __bytes, size_t __align = __max_align) 112 1.1 joerg { do_deallocate(__p, __bytes, __align); } 113 1.1 joerg 114 1.1 joerg _LIBCPP_INLINE_VISIBILITY 115 1.1 joerg bool is_equal(memory_resource const & __other) const _NOEXCEPT 116 1.1 joerg { return do_is_equal(__other); } 117 1.1 joerg 118 1.1 joerg // 8.5.3, memory.resource.priv 119 1.1 joerg private: 120 1.1 joerg virtual void* do_allocate(size_t, size_t) = 0; 121 1.1 joerg virtual void do_deallocate(void*, size_t, size_t) = 0; 122 1.1 joerg virtual bool do_is_equal(memory_resource const &) const _NOEXCEPT = 0; 123 1.1 joerg }; 124 1.1 joerg 125 1.1 joerg // 8.5.4, memory.resource.eq 126 1.1 joerg inline _LIBCPP_INLINE_VISIBILITY 127 1.1 joerg bool operator==(memory_resource const & __lhs, 128 1.1 joerg memory_resource const & __rhs) _NOEXCEPT 129 1.1 joerg { 130 1.1 joerg return &__lhs == &__rhs || __lhs.is_equal(__rhs); 131 1.1 joerg } 132 1.1 joerg 133 1.1 joerg inline _LIBCPP_INLINE_VISIBILITY 134 1.1 joerg bool operator!=(memory_resource const & __lhs, 135 1.1 joerg memory_resource const & __rhs) _NOEXCEPT 136 1.1 joerg { 137 1.1 joerg return !(__lhs == __rhs); 138 1.1 joerg } 139 1.1 joerg 140 1.1 joerg _LIBCPP_FUNC_VIS 141 1.1 joerg memory_resource * new_delete_resource() _NOEXCEPT; 142 1.1 joerg 143 1.1 joerg _LIBCPP_FUNC_VIS 144 1.1 joerg memory_resource * null_memory_resource() _NOEXCEPT; 145 1.1 joerg 146 1.1 joerg _LIBCPP_FUNC_VIS 147 1.1 joerg memory_resource * get_default_resource() _NOEXCEPT; 148 1.1 joerg 149 1.1 joerg _LIBCPP_FUNC_VIS 150 1.1 joerg memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT; 151 1.1 joerg 152 1.1 joerg // 8.6, memory.polymorphic.allocator.class 153 1.1 joerg 154 1.1 joerg // 8.6.1, memory.polymorphic.allocator.overview 155 1.1 joerg template <class _ValueType> 156 1.1 joerg class _LIBCPP_TEMPLATE_VIS polymorphic_allocator 157 1.1 joerg { 158 1.1 joerg public: 159 1.1 joerg typedef _ValueType value_type; 160 1.1 joerg 161 1.1 joerg // 8.6.2, memory.polymorphic.allocator.ctor 162 1.1 joerg _LIBCPP_INLINE_VISIBILITY 163 1.1 joerg polymorphic_allocator() _NOEXCEPT 164 1.1 joerg : __res_(_VSTD_LFTS_PMR::get_default_resource()) 165 1.1 joerg {} 166 1.1 joerg 167 1.1 joerg _LIBCPP_INLINE_VISIBILITY 168 1.1 joerg polymorphic_allocator(memory_resource * __r) _NOEXCEPT 169 1.1 joerg : __res_(__r) 170 1.1 joerg {} 171 1.1 joerg 172 1.1 joerg polymorphic_allocator(polymorphic_allocator const &) = default; 173 1.1 joerg 174 1.1 joerg template <class _Tp> 175 1.1 joerg _LIBCPP_INLINE_VISIBILITY 176 1.1 joerg polymorphic_allocator(polymorphic_allocator<_Tp> const & __other) _NOEXCEPT 177 1.1 joerg : __res_(__other.resource()) 178 1.1 joerg {} 179 1.1 joerg 180 1.1 joerg polymorphic_allocator & 181 1.1 joerg operator=(polymorphic_allocator const &) = delete; 182 1.1 joerg 183 1.1 joerg // 8.6.3, memory.polymorphic.allocator.mem 184 1.1 joerg _LIBCPP_INLINE_VISIBILITY 185 1.1 joerg _ValueType* allocate(size_t __n) { 186 1.1 joerg if (__n > __max_size()) { 187 1.1 joerg __throw_length_error( 188 1.1 joerg "std::experimental::pmr::polymorphic_allocator<T>::allocate(size_t n)" 189 1.1 joerg " 'n' exceeds maximum supported size"); 190 1.1 joerg } 191 1.1 joerg return static_cast<_ValueType*>( 192 1.1 joerg __res_->allocate(__n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType)) 193 1.1 joerg ); 194 1.1 joerg } 195 1.1 joerg 196 1.1 joerg _LIBCPP_INLINE_VISIBILITY 197 1.1 joerg void deallocate(_ValueType * __p, size_t __n) _NOEXCEPT { 198 1.1 joerg _LIBCPP_ASSERT(__n <= __max_size(), 199 1.1 joerg "deallocate called for size which exceeds max_size()"); 200 1.1 joerg __res_->deallocate(__p, __n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType)); 201 1.1 joerg } 202 1.1 joerg 203 1.1 joerg template <class _Tp, class ..._Ts> 204 1.1 joerg _LIBCPP_INLINE_VISIBILITY 205 1.1 joerg void construct(_Tp* __p, _Ts &&... __args) 206 1.1 joerg { 207 1.1 joerg _VSTD_LFTS::__lfts_user_alloc_construct( 208 1.1 joerg __p, *this, _VSTD::forward<_Ts>(__args)... 209 1.1 joerg ); 210 1.1 joerg } 211 1.1 joerg 212 1.1 joerg template <class _T1, class _T2, class ..._Args1, class ..._Args2> 213 1.1 joerg _LIBCPP_INLINE_VISIBILITY 214 1.1 joerg void construct(pair<_T1, _T2>* __p, piecewise_construct_t, 215 1.1 joerg tuple<_Args1...> __x, tuple<_Args2...> __y) 216 1.1 joerg { 217 1.1 joerg ::new ((void*)__p) pair<_T1, _T2>(piecewise_construct 218 1.1 joerg , __transform_tuple( 219 1.1 joerg typename __lfts_uses_alloc_ctor< 220 1.1 joerg _T1, polymorphic_allocator&, _Args1... 221 1.1 joerg >::type() 222 1.1 joerg , _VSTD::move(__x) 223 1.1 joerg , typename __make_tuple_indices<sizeof...(_Args1)>::type{} 224 1.1 joerg ) 225 1.1 joerg , __transform_tuple( 226 1.1 joerg typename __lfts_uses_alloc_ctor< 227 1.1 joerg _T2, polymorphic_allocator&, _Args2... 228 1.1 joerg >::type() 229 1.1 joerg , _VSTD::move(__y) 230 1.1 joerg , typename __make_tuple_indices<sizeof...(_Args2)>::type{} 231 1.1 joerg ) 232 1.1 joerg ); 233 1.1 joerg } 234 1.1 joerg 235 1.1 joerg template <class _T1, class _T2> 236 1.1 joerg _LIBCPP_INLINE_VISIBILITY 237 1.1 joerg void construct(pair<_T1, _T2>* __p) { 238 1.1 joerg construct(__p, piecewise_construct, tuple<>(), tuple<>()); 239 1.1 joerg } 240 1.1 joerg 241 1.1 joerg template <class _T1, class _T2, class _Up, class _Vp> 242 1.1 joerg _LIBCPP_INLINE_VISIBILITY 243 1.1 joerg void construct(pair<_T1, _T2> * __p, _Up && __u, _Vp && __v) { 244 1.1 joerg construct(__p, piecewise_construct 245 1.1 joerg , _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__u)) 246 1.1 joerg , _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__v))); 247 1.1 joerg } 248 1.1 joerg 249 1.1 joerg template <class _T1, class _T2, class _U1, class _U2> 250 1.1 joerg _LIBCPP_INLINE_VISIBILITY 251 1.1 joerg void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> const & __pr) { 252 1.1 joerg construct(__p, piecewise_construct 253 1.1 joerg , _VSTD::forward_as_tuple(__pr.first) 254 1.1 joerg , _VSTD::forward_as_tuple(__pr.second)); 255 1.1 joerg } 256 1.1 joerg 257 1.1 joerg template <class _T1, class _T2, class _U1, class _U2> 258 1.1 joerg _LIBCPP_INLINE_VISIBILITY 259 1.1 joerg void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> && __pr){ 260 1.1 joerg construct(__p, piecewise_construct 261 1.1 joerg , _VSTD::forward_as_tuple(_VSTD::forward<_U1>(__pr.first)) 262 1.1 joerg , _VSTD::forward_as_tuple(_VSTD::forward<_U2>(__pr.second))); 263 1.1 joerg } 264 1.1 joerg 265 1.1 joerg template <class _Tp> 266 1.1 joerg _LIBCPP_INLINE_VISIBILITY 267 1.1 joerg void destroy(_Tp * __p) _NOEXCEPT 268 1.1 joerg { __p->~_Tp(); } 269 1.1 joerg 270 1.1 joerg _LIBCPP_INLINE_VISIBILITY 271 1.1 joerg polymorphic_allocator 272 1.1 joerg select_on_container_copy_construction() const _NOEXCEPT 273 1.1 joerg { return polymorphic_allocator(); } 274 1.1 joerg 275 1.1 joerg _LIBCPP_INLINE_VISIBILITY 276 1.1 joerg memory_resource * resource() const _NOEXCEPT 277 1.1 joerg { return __res_; } 278 1.1 joerg 279 1.1 joerg private: 280 1.1 joerg template <class ..._Args, size_t ..._Idx> 281 1.1 joerg _LIBCPP_INLINE_VISIBILITY 282 1.1 joerg tuple<_Args&&...> 283 1.1 joerg __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, 284 1.1 joerg __tuple_indices<_Idx...>) const 285 1.1 joerg { 286 1.1 joerg return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...); 287 1.1 joerg } 288 1.1 joerg 289 1.1 joerg template <class ..._Args, size_t ..._Idx> 290 1.1 joerg _LIBCPP_INLINE_VISIBILITY 291 1.1 joerg tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...> 292 1.1 joerg __transform_tuple(integral_constant<int, 1>, tuple<_Args...> && __t, 293 1.1 joerg __tuple_indices<_Idx...>) 294 1.1 joerg { 295 1.1 joerg using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>; 296 1.1 joerg return _Tup(allocator_arg, *this, 297 1.1 joerg _VSTD::get<_Idx>(_VSTD::move(__t))...); 298 1.1 joerg } 299 1.1 joerg 300 1.1 joerg template <class ..._Args, size_t ..._Idx> 301 1.1 joerg _LIBCPP_INLINE_VISIBILITY 302 1.1 joerg tuple<_Args&&..., polymorphic_allocator&> 303 1.1 joerg __transform_tuple(integral_constant<int, 2>, tuple<_Args...> && __t, 304 1.1 joerg __tuple_indices<_Idx...>) 305 1.1 joerg { 306 1.1 joerg using _Tup = tuple<_Args&&..., polymorphic_allocator&>; 307 1.1 joerg return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., *this); 308 1.1 joerg } 309 1.1 joerg 310 1.1 joerg _LIBCPP_INLINE_VISIBILITY 311 1.1 joerg size_t __max_size() const _NOEXCEPT 312 1.1 joerg { return numeric_limits<size_t>::max() / sizeof(value_type); } 313 1.1 joerg 314 1.1 joerg memory_resource * __res_; 315 1.1 joerg }; 316 1.1 joerg 317 1.1 joerg // 8.6.4, memory.polymorphic.allocator.eq 318 1.1 joerg 319 1.1 joerg template <class _Tp, class _Up> 320 1.1 joerg inline _LIBCPP_INLINE_VISIBILITY 321 1.1 joerg bool operator==(polymorphic_allocator<_Tp> const & __lhs, 322 1.1 joerg polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT 323 1.1 joerg { 324 1.1 joerg return *__lhs.resource() == *__rhs.resource(); 325 1.1 joerg } 326 1.1 joerg 327 1.1 joerg template <class _Tp, class _Up> 328 1.1 joerg inline _LIBCPP_INLINE_VISIBILITY 329 1.1 joerg bool operator!=(polymorphic_allocator<_Tp> const & __lhs, 330 1.1 joerg polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT 331 1.1 joerg { 332 1.1 joerg return !(__lhs == __rhs); 333 1.1 joerg } 334 1.1 joerg 335 1.1 joerg // 8.7, memory.resource.adaptor 336 1.1 joerg 337 1.1 joerg // 8.7.1, memory.resource.adaptor.overview 338 1.1 joerg template <class _CharAlloc> 339 1.1 joerg class _LIBCPP_TEMPLATE_VIS __resource_adaptor_imp 340 1.1 joerg : public memory_resource 341 1.1 joerg { 342 1.1 joerg using _CTraits = allocator_traits<_CharAlloc>; 343 1.1 joerg static_assert(is_same<typename _CTraits::value_type, char>::value 344 1.1 joerg && is_same<typename _CTraits::pointer, char*>::value 345 1.1 joerg && is_same<typename _CTraits::void_pointer, void*>::value, ""); 346 1.1 joerg 347 1.1 joerg static const size_t _MaxAlign = _LIBCPP_ALIGNOF(max_align_t); 348 1.1 joerg 349 1.1 joerg using _Alloc = typename _CTraits::template rebind_alloc< 350 1.1 joerg typename aligned_storage<_MaxAlign, _MaxAlign>::type 351 1.1 joerg >; 352 1.1 joerg 353 1.1 joerg using _ValueType = typename _Alloc::value_type; 354 1.1 joerg 355 1.1 joerg _Alloc __alloc_; 356 1.1 joerg 357 1.1 joerg public: 358 1.1 joerg typedef _CharAlloc allocator_type; 359 1.1 joerg 360 1.1 joerg __resource_adaptor_imp() = default; 361 1.1 joerg __resource_adaptor_imp(__resource_adaptor_imp const &) = default; 362 1.1 joerg __resource_adaptor_imp(__resource_adaptor_imp &&) = default; 363 1.1 joerg 364 1.1 joerg // 8.7.2, memory.resource.adaptor.ctor 365 1.1 joerg 366 1.1 joerg _LIBCPP_INLINE_VISIBILITY 367 1.1 joerg explicit __resource_adaptor_imp(allocator_type const & __a) 368 1.1 joerg : __alloc_(__a) 369 1.1 joerg {} 370 1.1 joerg 371 1.1 joerg _LIBCPP_INLINE_VISIBILITY 372 1.1 joerg explicit __resource_adaptor_imp(allocator_type && __a) 373 1.1 joerg : __alloc_(_VSTD::move(__a)) 374 1.1 joerg {} 375 1.1 joerg 376 1.1 joerg __resource_adaptor_imp & 377 1.1 joerg operator=(__resource_adaptor_imp const &) = default; 378 1.1 joerg 379 1.1 joerg _LIBCPP_INLINE_VISIBILITY 380 1.1 joerg allocator_type get_allocator() const 381 1.1 joerg { return __alloc_; } 382 1.1 joerg 383 1.1 joerg // 8.7.3, memory.resource.adaptor.mem 384 1.1 joerg private: 385 1.1 joerg virtual void * do_allocate(size_t __bytes, size_t) 386 1.1 joerg { 387 1.1 joerg if (__bytes > __max_size()) { 388 1.1 joerg __throw_length_error( 389 1.1 joerg "std::experimental::pmr::resource_adaptor<T>::do_allocate(size_t bytes, size_t align)" 390 1.1 joerg " 'bytes' exceeds maximum supported size"); 391 1.1 joerg } 392 1.1 joerg size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign; 393 1.1 joerg return __alloc_.allocate(__s); 394 1.1 joerg } 395 1.1 joerg 396 1.1 joerg virtual void do_deallocate(void * __p, size_t __bytes, size_t) 397 1.1 joerg { 398 1.1 joerg _LIBCPP_ASSERT(__bytes <= __max_size(), 399 1.1 joerg "do_deallocate called for size which exceeds the maximum allocation size"); 400 1.1 joerg size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign; 401 1.1 joerg __alloc_.deallocate((_ValueType*)__p, __s); 402 1.1 joerg } 403 1.1 joerg 404 1.1 joerg virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT { 405 1.1 joerg __resource_adaptor_imp const * __p 406 1.1 joerg = dynamic_cast<__resource_adaptor_imp const *>(&__other); 407 1.1 joerg return __p ? __alloc_ == __p->__alloc_ : false; 408 1.1 joerg } 409 1.1 joerg 410 1.1 joerg _LIBCPP_INLINE_VISIBILITY 411 1.1 joerg size_t __max_size() const _NOEXCEPT { 412 1.1 joerg return numeric_limits<size_t>::max() - _MaxAlign; 413 1.1 joerg } 414 1.1 joerg }; 415 1.1 joerg 416 1.1 joerg template <class _Alloc> 417 1.1 joerg using resource_adaptor = __resource_adaptor_imp< 418 1.1 joerg typename allocator_traits<_Alloc>::template rebind_alloc<char> 419 1.1 joerg >; 420 1.1 joerg 421 1.1 joerg _LIBCPP_END_NAMESPACE_LFTS_PMR 422 1.1 joerg 423 1.1 joerg _LIBCPP_POP_MACROS 424 1.1 joerg 425 1.1 joerg #endif /* _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE */ 426