17c82a1ecSDimitry Andric// -*- C++ -*- 27c82a1ecSDimitry Andric//===------------------------ memory_resource -----------------------------===// 37c82a1ecSDimitry Andric// 47c82a1ecSDimitry Andric// The LLVM Compiler Infrastructure 57c82a1ecSDimitry Andric// 67c82a1ecSDimitry Andric// This file is distributed under the University of Illinois Open Source 77c82a1ecSDimitry Andric// License. See LICENSE.TXT for details. 87c82a1ecSDimitry Andric// 97c82a1ecSDimitry Andric//===----------------------------------------------------------------------===// 107c82a1ecSDimitry Andric 117c82a1ecSDimitry Andric#ifndef _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE 127c82a1ecSDimitry Andric#define _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE 137c82a1ecSDimitry Andric 147c82a1ecSDimitry Andric/** 157c82a1ecSDimitry Andric experimental/memory_resource synopsis 167c82a1ecSDimitry Andric 177c82a1ecSDimitry Andric// C++1y 187c82a1ecSDimitry Andric 197c82a1ecSDimitry Andricnamespace std { 207c82a1ecSDimitry Andricnamespace experimental { 217c82a1ecSDimitry Andricinline namespace fundamentals_v1 { 227c82a1ecSDimitry Andricnamespace pmr { 237c82a1ecSDimitry Andric 247c82a1ecSDimitry Andric class memory_resource; 257c82a1ecSDimitry Andric 267c82a1ecSDimitry Andric bool operator==(const memory_resource& a, 277c82a1ecSDimitry Andric const memory_resource& b) noexcept; 287c82a1ecSDimitry Andric bool operator!=(const memory_resource& a, 297c82a1ecSDimitry Andric const memory_resource& b) noexcept; 307c82a1ecSDimitry Andric 317c82a1ecSDimitry Andric template <class Tp> class polymorphic_allocator; 327c82a1ecSDimitry Andric 337c82a1ecSDimitry Andric template <class T1, class T2> 347c82a1ecSDimitry Andric bool operator==(const polymorphic_allocator<T1>& a, 357c82a1ecSDimitry Andric const polymorphic_allocator<T2>& b) noexcept; 367c82a1ecSDimitry Andric template <class T1, class T2> 377c82a1ecSDimitry Andric bool operator!=(const polymorphic_allocator<T1>& a, 387c82a1ecSDimitry Andric const polymorphic_allocator<T2>& b) noexcept; 397c82a1ecSDimitry Andric 407c82a1ecSDimitry Andric // The name resource_adaptor_imp is for exposition only. 417c82a1ecSDimitry Andric template <class Allocator> class resource_adaptor_imp; 427c82a1ecSDimitry Andric 437c82a1ecSDimitry Andric template <class Allocator> 447c82a1ecSDimitry Andric using resource_adaptor = resource_adaptor_imp< 457c82a1ecSDimitry Andric allocator_traits<Allocator>::rebind_alloc<char>>; 467c82a1ecSDimitry Andric 477c82a1ecSDimitry Andric // Global memory resources 487c82a1ecSDimitry Andric memory_resource* new_delete_resource() noexcept; 497c82a1ecSDimitry Andric memory_resource* null_memory_resource() noexcept; 507c82a1ecSDimitry Andric 517c82a1ecSDimitry Andric // The default memory resource 527c82a1ecSDimitry Andric memory_resource* set_default_resource(memory_resource* r) noexcept; 537c82a1ecSDimitry Andric memory_resource* get_default_resource() noexcept; 547c82a1ecSDimitry Andric 557c82a1ecSDimitry Andric // Standard memory resources 567c82a1ecSDimitry Andric struct pool_options; 577c82a1ecSDimitry Andric class synchronized_pool_resource; 587c82a1ecSDimitry Andric class unsynchronized_pool_resource; 597c82a1ecSDimitry Andric class monotonic_buffer_resource; 607c82a1ecSDimitry Andric 617c82a1ecSDimitry Andric} // namespace pmr 627c82a1ecSDimitry Andric} // namespace fundamentals_v1 637c82a1ecSDimitry Andric} // namespace experimental 647c82a1ecSDimitry Andric} // namespace std 657c82a1ecSDimitry Andric 667c82a1ecSDimitry Andric */ 677c82a1ecSDimitry Andric 687c82a1ecSDimitry Andric#include <experimental/__config> 697c82a1ecSDimitry Andric#include <experimental/__memory> 707c82a1ecSDimitry Andric#include <limits> 717c82a1ecSDimitry Andric#include <memory> 727c82a1ecSDimitry Andric#include <new> 737c82a1ecSDimitry Andric#include <stdexcept> 744ba319b5SDimitry Andric#include <__tuple> 757c82a1ecSDimitry Andric#include <type_traits> 767c82a1ecSDimitry Andric#include <utility> 777c82a1ecSDimitry Andric#include <cstddef> 787c82a1ecSDimitry Andric#include <cstdlib> 797c82a1ecSDimitry Andric#include <__debug> 807c82a1ecSDimitry Andric 817c82a1ecSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 827c82a1ecSDimitry Andric#pragma GCC system_header 837c82a1ecSDimitry Andric#endif 847c82a1ecSDimitry Andric 85f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS 86f9448bf3SDimitry Andric#include <__undef_macros> 87f9448bf3SDimitry Andric 887c82a1ecSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR 897c82a1ecSDimitry Andric 907c82a1ecSDimitry Andric// Round __s up to next multiple of __a. 917c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 927c82a1ecSDimitry Andricsize_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT 937c82a1ecSDimitry Andric{ 947c82a1ecSDimitry Andric _LIBCPP_ASSERT(__s + __a > __s, "aligned allocation size overflows"); 957c82a1ecSDimitry Andric return (__s + __a - 1) & ~(__a - 1); 967c82a1ecSDimitry Andric} 977c82a1ecSDimitry Andric 987c82a1ecSDimitry Andric// 8.5, memory.resource 994ba319b5SDimitry Andricclass _LIBCPP_TYPE_VIS memory_resource 1007c82a1ecSDimitry Andric{ 101*b5893f02SDimitry Andric static const size_t __max_align = _LIBCPP_ALIGNOF(max_align_t); 1027c82a1ecSDimitry Andric 1037c82a1ecSDimitry Andric// 8.5.2, memory.resource.public 1047c82a1ecSDimitry Andricpublic: 1057c82a1ecSDimitry Andric virtual ~memory_resource() = default; 1067c82a1ecSDimitry Andric 1077c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1087c82a1ecSDimitry Andric void* allocate(size_t __bytes, size_t __align = __max_align) 1097c82a1ecSDimitry Andric { return do_allocate(__bytes, __align); } 1107c82a1ecSDimitry Andric 1117c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1127c82a1ecSDimitry Andric void deallocate(void * __p, size_t __bytes, size_t __align = __max_align) 1137c82a1ecSDimitry Andric { do_deallocate(__p, __bytes, __align); } 1147c82a1ecSDimitry Andric 1157c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1167c82a1ecSDimitry Andric bool is_equal(memory_resource const & __other) const _NOEXCEPT 1177c82a1ecSDimitry Andric { return do_is_equal(__other); } 1187c82a1ecSDimitry Andric 1197c82a1ecSDimitry Andric// 8.5.3, memory.resource.priv 1207c82a1ecSDimitry Andricprotected: 1217c82a1ecSDimitry Andric virtual void* do_allocate(size_t, size_t) = 0; 1227c82a1ecSDimitry Andric virtual void do_deallocate(void*, size_t, size_t) = 0; 1237c82a1ecSDimitry Andric virtual bool do_is_equal(memory_resource const &) const _NOEXCEPT = 0; 1247c82a1ecSDimitry Andric}; 1257c82a1ecSDimitry Andric 1267c82a1ecSDimitry Andric// 8.5.4, memory.resource.eq 1277c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1287c82a1ecSDimitry Andricbool operator==(memory_resource const & __lhs, 1297c82a1ecSDimitry Andric memory_resource const & __rhs) _NOEXCEPT 1307c82a1ecSDimitry Andric{ 1317c82a1ecSDimitry Andric return &__lhs == &__rhs || __lhs.is_equal(__rhs); 1327c82a1ecSDimitry Andric} 1337c82a1ecSDimitry Andric 1347c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1357c82a1ecSDimitry Andricbool operator!=(memory_resource const & __lhs, 1367c82a1ecSDimitry Andric memory_resource const & __rhs) _NOEXCEPT 1377c82a1ecSDimitry Andric{ 1387c82a1ecSDimitry Andric return !(__lhs == __rhs); 1397c82a1ecSDimitry Andric} 1407c82a1ecSDimitry Andric 1417c82a1ecSDimitry Andric_LIBCPP_FUNC_VIS 1427c82a1ecSDimitry Andricmemory_resource * new_delete_resource() _NOEXCEPT; 1437c82a1ecSDimitry Andric 1447c82a1ecSDimitry Andric_LIBCPP_FUNC_VIS 1457c82a1ecSDimitry Andricmemory_resource * null_memory_resource() _NOEXCEPT; 1467c82a1ecSDimitry Andric 1477c82a1ecSDimitry Andric_LIBCPP_FUNC_VIS 1487c82a1ecSDimitry Andricmemory_resource * get_default_resource() _NOEXCEPT; 1497c82a1ecSDimitry Andric 1507c82a1ecSDimitry Andric_LIBCPP_FUNC_VIS 1517c82a1ecSDimitry Andricmemory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT; 1527c82a1ecSDimitry Andric 1537c82a1ecSDimitry Andric// 8.6, memory.polymorphic.allocator.class 1547c82a1ecSDimitry Andric 1557c82a1ecSDimitry Andric// 8.6.1, memory.polymorphic.allocator.overview 1567c82a1ecSDimitry Andrictemplate <class _ValueType> 157aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS polymorphic_allocator 1587c82a1ecSDimitry Andric{ 1597c82a1ecSDimitry Andricpublic: 1607c82a1ecSDimitry Andric typedef _ValueType value_type; 1617c82a1ecSDimitry Andric 1627c82a1ecSDimitry Andric // 8.6.2, memory.polymorphic.allocator.ctor 1637c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1647c82a1ecSDimitry Andric polymorphic_allocator() _NOEXCEPT 1657c82a1ecSDimitry Andric : __res_(_VSTD_LFTS_PMR::get_default_resource()) 1667c82a1ecSDimitry Andric {} 1677c82a1ecSDimitry Andric 1687c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1697c82a1ecSDimitry Andric polymorphic_allocator(memory_resource * __r) _NOEXCEPT 1707c82a1ecSDimitry Andric : __res_(__r) 1717c82a1ecSDimitry Andric {} 1727c82a1ecSDimitry Andric 1737c82a1ecSDimitry Andric polymorphic_allocator(polymorphic_allocator const &) = default; 1747c82a1ecSDimitry Andric 1757c82a1ecSDimitry Andric template <class _Tp> 1767c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1777c82a1ecSDimitry Andric polymorphic_allocator(polymorphic_allocator<_Tp> const & __other) _NOEXCEPT 1787c82a1ecSDimitry Andric : __res_(__other.resource()) 1797c82a1ecSDimitry Andric {} 1807c82a1ecSDimitry Andric 1817c82a1ecSDimitry Andric polymorphic_allocator & 1827c82a1ecSDimitry Andric operator=(polymorphic_allocator const &) = delete; 1837c82a1ecSDimitry Andric 1847c82a1ecSDimitry Andric // 8.6.3, memory.polymorphic.allocator.mem 1857c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1867c82a1ecSDimitry Andric _ValueType* allocate(size_t __n) { 187540d2a8bSDimitry Andric if (__n > __max_size()) { 188aed8d94eSDimitry Andric __throw_length_error( 1897c82a1ecSDimitry Andric "std::experimental::pmr::polymorphic_allocator<T>::allocate(size_t n)" 190aed8d94eSDimitry Andric " 'n' exceeds maximum supported size"); 1917c82a1ecSDimitry Andric } 1927c82a1ecSDimitry Andric return static_cast<_ValueType*>( 193*b5893f02SDimitry Andric __res_->allocate(__n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType)) 1947c82a1ecSDimitry Andric ); 1957c82a1ecSDimitry Andric } 1967c82a1ecSDimitry Andric 1977c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 1987c82a1ecSDimitry Andric void deallocate(_ValueType * __p, size_t __n) _NOEXCEPT { 199540d2a8bSDimitry Andric _LIBCPP_ASSERT(__n <= __max_size(), 2007c82a1ecSDimitry Andric "deallocate called for size which exceeds max_size()"); 201*b5893f02SDimitry Andric __res_->deallocate(__p, __n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType)); 2027c82a1ecSDimitry Andric } 2037c82a1ecSDimitry Andric 2047c82a1ecSDimitry Andric template <class _Tp, class ..._Ts> 2057c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2067c82a1ecSDimitry Andric void construct(_Tp* __p, _Ts &&... __args) 2077c82a1ecSDimitry Andric { 2087c82a1ecSDimitry Andric _VSTD_LFTS::__lfts_user_alloc_construct( 2094ba319b5SDimitry Andric __p, *this, _VSTD::forward<_Ts>(__args)... 2107c82a1ecSDimitry Andric ); 2117c82a1ecSDimitry Andric } 2127c82a1ecSDimitry Andric 2137c82a1ecSDimitry Andric template <class _T1, class _T2, class ..._Args1, class ..._Args2> 2147c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2157c82a1ecSDimitry Andric void construct(pair<_T1, _T2>* __p, piecewise_construct_t, 2167c82a1ecSDimitry Andric tuple<_Args1...> __x, tuple<_Args2...> __y) 2177c82a1ecSDimitry Andric { 2187c82a1ecSDimitry Andric ::new ((void*)__p) pair<_T1, _T2>(piecewise_construct 2197c82a1ecSDimitry Andric , __transform_tuple( 2207c82a1ecSDimitry Andric typename __lfts_uses_alloc_ctor< 2214ba319b5SDimitry Andric _T1, polymorphic_allocator&, _Args1... 2227c82a1ecSDimitry Andric >::type() 2237c82a1ecSDimitry Andric , _VSTD::move(__x) 2247c82a1ecSDimitry Andric , typename __make_tuple_indices<sizeof...(_Args1)>::type{} 2257c82a1ecSDimitry Andric ) 2267c82a1ecSDimitry Andric , __transform_tuple( 2277c82a1ecSDimitry Andric typename __lfts_uses_alloc_ctor< 2284ba319b5SDimitry Andric _T2, polymorphic_allocator&, _Args2... 2297c82a1ecSDimitry Andric >::type() 2307c82a1ecSDimitry Andric , _VSTD::move(__y) 2317c82a1ecSDimitry Andric , typename __make_tuple_indices<sizeof...(_Args2)>::type{} 2327c82a1ecSDimitry Andric ) 2337c82a1ecSDimitry Andric ); 2347c82a1ecSDimitry Andric } 2357c82a1ecSDimitry Andric 2367c82a1ecSDimitry Andric template <class _T1, class _T2> 2377c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2387c82a1ecSDimitry Andric void construct(pair<_T1, _T2>* __p) { 2397c82a1ecSDimitry Andric construct(__p, piecewise_construct, tuple<>(), tuple<>()); 2407c82a1ecSDimitry Andric } 2417c82a1ecSDimitry Andric 2427c82a1ecSDimitry Andric template <class _T1, class _T2, class _Up, class _Vp> 2437c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2447c82a1ecSDimitry Andric void construct(pair<_T1, _T2> * __p, _Up && __u, _Vp && __v) { 2457c82a1ecSDimitry Andric construct(__p, piecewise_construct 2467c82a1ecSDimitry Andric , _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__u)) 2477c82a1ecSDimitry Andric , _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__v))); 2487c82a1ecSDimitry Andric } 2497c82a1ecSDimitry Andric 2507c82a1ecSDimitry Andric template <class _T1, class _T2, class _U1, class _U2> 2517c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2527c82a1ecSDimitry Andric void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> const & __pr) { 2537c82a1ecSDimitry Andric construct(__p, piecewise_construct 2547c82a1ecSDimitry Andric , _VSTD::forward_as_tuple(__pr.first) 2557c82a1ecSDimitry Andric , _VSTD::forward_as_tuple(__pr.second)); 2567c82a1ecSDimitry Andric } 2577c82a1ecSDimitry Andric 2587c82a1ecSDimitry Andric template <class _T1, class _T2, class _U1, class _U2> 2597c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2607c82a1ecSDimitry Andric void construct(pair<_T1, _T2> * __p, pair<_U1, _U2> && __pr){ 2617c82a1ecSDimitry Andric construct(__p, piecewise_construct 2627c82a1ecSDimitry Andric , _VSTD::forward_as_tuple(_VSTD::forward<_U1>(__pr.first)) 2637c82a1ecSDimitry Andric , _VSTD::forward_as_tuple(_VSTD::forward<_U2>(__pr.second))); 2647c82a1ecSDimitry Andric } 2657c82a1ecSDimitry Andric 2667c82a1ecSDimitry Andric template <class _Tp> 2677c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2687c82a1ecSDimitry Andric void destroy(_Tp * __p) _NOEXCEPT 2697c82a1ecSDimitry Andric { __p->~_Tp(); } 2707c82a1ecSDimitry Andric 2717c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2727c82a1ecSDimitry Andric polymorphic_allocator 2737c82a1ecSDimitry Andric select_on_container_copy_construction() const _NOEXCEPT 2747c82a1ecSDimitry Andric { return polymorphic_allocator(); } 2757c82a1ecSDimitry Andric 2767c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2777c82a1ecSDimitry Andric memory_resource * resource() const _NOEXCEPT 2787c82a1ecSDimitry Andric { return __res_; } 2797c82a1ecSDimitry Andric 2807c82a1ecSDimitry Andricprivate: 2817c82a1ecSDimitry Andric template <class ..._Args, size_t ..._Idx> 2827c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2837c82a1ecSDimitry Andric tuple<_Args&&...> 2847c82a1ecSDimitry Andric __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, 2857c82a1ecSDimitry Andric __tuple_indices<_Idx...>) const 2867c82a1ecSDimitry Andric { 2877c82a1ecSDimitry Andric return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...); 2887c82a1ecSDimitry Andric } 2897c82a1ecSDimitry Andric 2907c82a1ecSDimitry Andric template <class ..._Args, size_t ..._Idx> 2917c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2924ba319b5SDimitry Andric tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...> 2937c82a1ecSDimitry Andric __transform_tuple(integral_constant<int, 1>, tuple<_Args...> && __t, 2944ba319b5SDimitry Andric __tuple_indices<_Idx...>) 2957c82a1ecSDimitry Andric { 2964ba319b5SDimitry Andric using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>; 2974ba319b5SDimitry Andric return _Tup(allocator_arg, *this, 2987c82a1ecSDimitry Andric _VSTD::get<_Idx>(_VSTD::move(__t))...); 2997c82a1ecSDimitry Andric } 3007c82a1ecSDimitry Andric 3017c82a1ecSDimitry Andric template <class ..._Args, size_t ..._Idx> 3027c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3034ba319b5SDimitry Andric tuple<_Args&&..., polymorphic_allocator&> 3047c82a1ecSDimitry Andric __transform_tuple(integral_constant<int, 2>, tuple<_Args...> && __t, 3054ba319b5SDimitry Andric __tuple_indices<_Idx...>) 3067c82a1ecSDimitry Andric { 3074ba319b5SDimitry Andric using _Tup = tuple<_Args&&..., polymorphic_allocator&>; 3084ba319b5SDimitry Andric return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., *this); 3097c82a1ecSDimitry Andric } 3107c82a1ecSDimitry Andric 311540d2a8bSDimitry Andric _LIBCPP_INLINE_VISIBILITY 312540d2a8bSDimitry Andric size_t __max_size() const _NOEXCEPT 313540d2a8bSDimitry Andric { return numeric_limits<size_t>::max() / sizeof(value_type); } 314540d2a8bSDimitry Andric 3157c82a1ecSDimitry Andric memory_resource * __res_; 3167c82a1ecSDimitry Andric}; 3177c82a1ecSDimitry Andric 3187c82a1ecSDimitry Andric// 8.6.4, memory.polymorphic.allocator.eq 3197c82a1ecSDimitry Andric 3207c82a1ecSDimitry Andrictemplate <class _Tp, class _Up> 3217c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 3227c82a1ecSDimitry Andricbool operator==(polymorphic_allocator<_Tp> const & __lhs, 3237c82a1ecSDimitry Andric polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT 3247c82a1ecSDimitry Andric{ 3257c82a1ecSDimitry Andric return *__lhs.resource() == *__rhs.resource(); 3267c82a1ecSDimitry Andric} 3277c82a1ecSDimitry Andric 3287c82a1ecSDimitry Andrictemplate <class _Tp, class _Up> 3297c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 3307c82a1ecSDimitry Andricbool operator!=(polymorphic_allocator<_Tp> const & __lhs, 3317c82a1ecSDimitry Andric polymorphic_allocator<_Up> const & __rhs) _NOEXCEPT 3327c82a1ecSDimitry Andric{ 3337c82a1ecSDimitry Andric return !(__lhs == __rhs); 3347c82a1ecSDimitry Andric} 3357c82a1ecSDimitry Andric 3367c82a1ecSDimitry Andric// 8.7, memory.resource.adaptor 3377c82a1ecSDimitry Andric 3387c82a1ecSDimitry Andric// 8.7.1, memory.resource.adaptor.overview 3397c82a1ecSDimitry Andrictemplate <class _CharAlloc> 340aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __resource_adaptor_imp 3417c82a1ecSDimitry Andric : public memory_resource 3427c82a1ecSDimitry Andric{ 3437c82a1ecSDimitry Andric using _CTraits = allocator_traits<_CharAlloc>; 3447c82a1ecSDimitry Andric static_assert(is_same<typename _CTraits::value_type, char>::value 3457c82a1ecSDimitry Andric && is_same<typename _CTraits::pointer, char*>::value 3467c82a1ecSDimitry Andric && is_same<typename _CTraits::void_pointer, void*>::value, ""); 3477c82a1ecSDimitry Andric 348*b5893f02SDimitry Andric static const size_t _MaxAlign = _LIBCPP_ALIGNOF(max_align_t); 3497c82a1ecSDimitry Andric 3507c82a1ecSDimitry Andric using _Alloc = typename _CTraits::template rebind_alloc< 3517c82a1ecSDimitry Andric typename aligned_storage<_MaxAlign, _MaxAlign>::type 3527c82a1ecSDimitry Andric >; 3537c82a1ecSDimitry Andric 3547c82a1ecSDimitry Andric using _ValueType = typename _Alloc::value_type; 3557c82a1ecSDimitry Andric 3567c82a1ecSDimitry Andric _Alloc __alloc_; 3577c82a1ecSDimitry Andric 3587c82a1ecSDimitry Andricpublic: 3597c82a1ecSDimitry Andric typedef _CharAlloc allocator_type; 3607c82a1ecSDimitry Andric 3617c82a1ecSDimitry Andric __resource_adaptor_imp() = default; 3627c82a1ecSDimitry Andric __resource_adaptor_imp(__resource_adaptor_imp const &) = default; 3637c82a1ecSDimitry Andric __resource_adaptor_imp(__resource_adaptor_imp &&) = default; 3647c82a1ecSDimitry Andric 3657c82a1ecSDimitry Andric // 8.7.2, memory.resource.adaptor.ctor 3667c82a1ecSDimitry Andric 3677c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3687c82a1ecSDimitry Andric explicit __resource_adaptor_imp(allocator_type const & __a) 3697c82a1ecSDimitry Andric : __alloc_(__a) 3707c82a1ecSDimitry Andric {} 3717c82a1ecSDimitry Andric 3727c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3737c82a1ecSDimitry Andric explicit __resource_adaptor_imp(allocator_type && __a) 3747c82a1ecSDimitry Andric : __alloc_(_VSTD::move(__a)) 3757c82a1ecSDimitry Andric {} 3767c82a1ecSDimitry Andric 3777c82a1ecSDimitry Andric __resource_adaptor_imp & 3787c82a1ecSDimitry Andric operator=(__resource_adaptor_imp const &) = default; 3797c82a1ecSDimitry Andric 3807c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 3817c82a1ecSDimitry Andric allocator_type get_allocator() const 3827c82a1ecSDimitry Andric { return __alloc_; } 3837c82a1ecSDimitry Andric 3847c82a1ecSDimitry Andric// 8.7.3, memory.resource.adaptor.mem 3857c82a1ecSDimitry Andricprotected: 3867c82a1ecSDimitry Andric virtual void * do_allocate(size_t __bytes, size_t) 3877c82a1ecSDimitry Andric { 3887c82a1ecSDimitry Andric if (__bytes > __max_size()) { 389aed8d94eSDimitry Andric __throw_length_error( 3907c82a1ecSDimitry Andric "std::experimental::pmr::resource_adaptor<T>::do_allocate(size_t bytes, size_t align)" 391aed8d94eSDimitry Andric " 'bytes' exceeds maximum supported size"); 3927c82a1ecSDimitry Andric } 3937c82a1ecSDimitry Andric size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign; 3947c82a1ecSDimitry Andric return __alloc_.allocate(__s); 3957c82a1ecSDimitry Andric } 3967c82a1ecSDimitry Andric 3977c82a1ecSDimitry Andric virtual void do_deallocate(void * __p, size_t __bytes, size_t) 3987c82a1ecSDimitry Andric { 3997c82a1ecSDimitry Andric _LIBCPP_ASSERT(__bytes <= __max_size(), 4007c82a1ecSDimitry Andric "do_deallocate called for size which exceeds the maximum allocation size"); 4017c82a1ecSDimitry Andric size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign; 4027c82a1ecSDimitry Andric __alloc_.deallocate((_ValueType*)__p, __s); 4037c82a1ecSDimitry Andric } 4047c82a1ecSDimitry Andric 4057c82a1ecSDimitry Andric virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT { 4067c82a1ecSDimitry Andric __resource_adaptor_imp const * __p 4077c82a1ecSDimitry Andric = dynamic_cast<__resource_adaptor_imp const *>(&__other); 4087c82a1ecSDimitry Andric return __p ? __alloc_ == __p->__alloc_ : false; 4097c82a1ecSDimitry Andric } 4107c82a1ecSDimitry Andric 4117c82a1ecSDimitry Andricprivate: 4127c82a1ecSDimitry Andric _LIBCPP_INLINE_VISIBILITY 4137c82a1ecSDimitry Andric size_t __max_size() const _NOEXCEPT { 4147c82a1ecSDimitry Andric return numeric_limits<size_t>::max() - _MaxAlign; 4157c82a1ecSDimitry Andric } 4167c82a1ecSDimitry Andric}; 4177c82a1ecSDimitry Andric 4187c82a1ecSDimitry Andrictemplate <class _Alloc> 4197c82a1ecSDimitry Andricusing resource_adaptor = __resource_adaptor_imp< 4207c82a1ecSDimitry Andric typename allocator_traits<_Alloc>::template rebind_alloc<char> 4217c82a1ecSDimitry Andric >; 4227c82a1ecSDimitry Andric 4237c82a1ecSDimitry Andric_LIBCPP_END_NAMESPACE_LFTS_PMR 4247c82a1ecSDimitry Andric 425f9448bf3SDimitry Andric_LIBCPP_POP_MACROS 426f9448bf3SDimitry Andric 4277c82a1ecSDimitry Andric#endif /* _LIBCPP_EXPERIMENTAL_MEMORY_RESOURCE */ 428