30#ifndef _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE
31#define _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE 1
33#pragma GCC system_header
37#if __cplusplus >= 201402L
49namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
51_GLIBCXX_BEGIN_NAMESPACE_VERSION
52 template<
typename _Tp>
class malloc_allocator;
53_GLIBCXX_END_NAMESPACE_VERSION
58_GLIBCXX_BEGIN_NAMESPACE_VERSION
60namespace experimental {
61inline namespace fundamentals_v2 {
63#define __cpp_lib_experimental_memory_resources 201402L
68 class memory_resource;
71 template<
typename _Tp>
72 class polymorphic_allocator;
74 template<
typename _Alloc,
typename _Resource = memory_resource>
75 class __resource_adaptor_imp;
78 template<
typename _Alloc>
79 using resource_adaptor = __resource_adaptor_imp<
80 typename allocator_traits<_Alloc>::template rebind_alloc<char>>;
84 memory_resource* null_memory_resource() noexcept;
85 memory_resource* get_default_resource() noexcept;
86 memory_resource* set_default_resource(memory_resource* __r) noexcept;
92 static constexpr size_t _S_max_align =
alignof(max_align_t);
95 memory_resource() =
default;
96 memory_resource(
const memory_resource&) =
default;
97 virtual ~memory_resource() =
default;
99 memory_resource& operator=(
const memory_resource&) =
default;
101 _GLIBCXX_NODISCARD
void*
102 allocate(
size_t __bytes,
size_t __alignment = _S_max_align)
103 {
return do_allocate(__bytes, __alignment); }
106 deallocate(
void* __p,
size_t __bytes,
size_t __alignment = _S_max_align)
107 {
return do_deallocate(__p, __bytes, __alignment); }
110 is_equal(
const memory_resource& __other)
const noexcept
111 {
return do_is_equal(__other); }
115 do_allocate(
size_t __bytes,
size_t __alignment) = 0;
118 do_deallocate(
void* __p,
size_t __bytes,
size_t __alignment) = 0;
121 do_is_equal(
const memory_resource& __other)
const noexcept = 0;
125 operator==(
const memory_resource& __a,
const memory_resource& __b)
noexcept
126 {
return &__a == &__b || __a.is_equal(__b); }
129 operator!=(
const memory_resource& __a,
const memory_resource& __b)
noexcept
130 {
return !(__a == __b); }
133 template<
typename _Tp>
134 class polymorphic_allocator
137 using value_type = _Tp;
139 polymorphic_allocator() noexcept
140 : _M_resource(get_default_resource())
143 polymorphic_allocator(memory_resource* __r)
145 { _GLIBCXX_DEBUG_ASSERT(__r); }
147 polymorphic_allocator(
const polymorphic_allocator& __other) =
default;
149 template <
typename _Up>
150 polymorphic_allocator(
const polymorphic_allocator<_Up>&
152 : _M_resource(__other.resource())
155 polymorphic_allocator&
156 operator=(
const polymorphic_allocator& __rhs) =
default;
158 _GLIBCXX_NODISCARD _Tp* allocate(
size_t __n)
159 {
return static_cast<_Tp*
>(_M_resource->allocate(__n *
sizeof(_Tp),
163 deallocate(_Tp* __p,
size_t __n)
164 { _M_resource->deallocate(__p, __n *
sizeof(_Tp),
alignof(_Tp)); }
166 template <
typename _Tp1,
typename... _Args>
168 construct(_Tp1* __p, _Args&&... __args)
170 std::__uses_allocator_construct(this->resource(), __p,
171 std::forward<_Args>(__args)...);
175 template <
typename _Tp1,
typename _Tp2,
176 typename... _Args1,
typename... _Args2>
178 construct(pair<_Tp1, _Tp2>* __p, piecewise_construct_t,
179 tuple<_Args1...> __x, tuple<_Args2...> __y)
181 memory_resource*
const __resource = this->resource();
183 std::__use_alloc<_Tp1, memory_resource*, _Args1...>(__resource);
185 std::__use_alloc<_Tp2, memory_resource*, _Args2...>(__resource);
188 _M_construct_p(__x_use_tag, __x),
189 _M_construct_p(__y_use_tag, __y));
192 template <
typename _Tp1,
typename _Tp2>
194 construct(pair<_Tp1,_Tp2>* __p)
197 template <
typename _Tp1,
typename _Tp2,
typename _Up,
typename _Vp>
199 construct(pair<_Tp1,_Tp2>* __p, _Up&& __x, _Vp&& __y)
206 template <
typename _Tp1,
typename _Tp2,
typename _Up,
typename _Vp>
215 template <
typename _Tp1,
typename _Tp2,
typename _Up,
typename _Vp>
217 construct(pair<_Tp1,_Tp2>* __p, pair<_Up, _Vp>&& __pr)
224 template <
typename _Up>
230 polymorphic_allocator
231 select_on_container_copy_construction()
const
232 {
return polymorphic_allocator(); }
234 memory_resource* resource()
const {
return _M_resource; }
237 using __uses_alloc1_ = __uses_alloc1<memory_resource*>;
238 using __uses_alloc2_ = __uses_alloc2<memory_resource*>;
240 template<
typename _Tuple>
242 _M_construct_p(__uses_alloc0, _Tuple& __t)
245 template<
typename... _Args>
247 _M_construct_p(__uses_alloc1_ __ua, tuple<_Args...>& __t)
251 template<
typename... _Args>
253 _M_construct_p(__uses_alloc2_ __ua, tuple<_Args...>& __t)
256 memory_resource* _M_resource;
259 template <
class _Tp1,
class _Tp2>
261 operator==(
const polymorphic_allocator<_Tp1>& __a,
262 const polymorphic_allocator<_Tp2>& __b)
noexcept
263 {
return *__a.resource() == *__b.resource(); }
265 template <
class _Tp1,
class _Tp2>
267 operator!=(
const polymorphic_allocator<_Tp1>& __a,
268 const polymorphic_allocator<_Tp2>& __b)
noexcept
269 {
return !(__a == __b); }
273 class __resource_adaptor_common
275 template<
typename,
typename>
friend class __resource_adaptor_imp;
279 _AlignMgr(
size_t __nbytes,
size_t __align)
280 : _M_nbytes(__nbytes), _M_align(__align)
285 _M_alloc_size()
const {
return _M_buf_size() + _M_token_size(); }
288 _M_adjust(
void* __ptr)
const
290 const auto __orig_ptr =
static_cast<char*
>(__ptr);
291 size_t __space = _M_buf_size();
293 std::align(_M_align, _M_nbytes, __ptr, __space);
294 const auto __aligned_ptr =
static_cast<char*
>(__ptr);
295 const auto __token_size = _M_token_size();
297 char*
const __end = __aligned_ptr + _M_nbytes;
298 if (__token_size == 1)
299 _S_write<unsigned char>(__end, __aligned_ptr - __orig_ptr);
300 else if (__token_size ==
sizeof(
short))
301 _S_write<unsigned short>(__end, __aligned_ptr - __orig_ptr);
302 else if (__token_size ==
sizeof(
int) &&
sizeof(
int) <
sizeof(
char*))
303 _S_write<unsigned int>(__end, __aligned_ptr - __orig_ptr);
306 _S_write<char*>(__end, __orig_ptr);
307 return __aligned_ptr;
311 _M_unadjust(
char* __ptr)
const
313 const char*
const __end = __ptr + _M_nbytes;
315 const auto __token_size = _M_token_size();
317 if (__token_size == 1)
318 __orig_ptr = __ptr - _S_read<unsigned char>(__end);
319 else if (__token_size ==
sizeof(
short))
320 __orig_ptr = __ptr - _S_read<unsigned short>(__end);
321 else if (__token_size ==
sizeof(
int)
322 &&
sizeof(
int) <
sizeof(
char*))
323 __orig_ptr = __ptr - _S_read<unsigned int>(__end);
325 __orig_ptr = _S_read<char*>(__end);
329 __glibcxx_assert(
static_cast<size_t>(__ptr - __orig_ptr) < _M_align);
339 _M_buf_size()
const {
return _M_nbytes + _M_align - 1; }
343 _M_token_size()
const
345 if (_M_align <= (1ul << __CHAR_BIT__))
347 if (_M_align <= (1ul << (
sizeof(
short) * __CHAR_BIT__)))
348 return sizeof(short);
349 if (_M_align <= (1ull << (
sizeof(
int) * __CHAR_BIT__)))
351 return sizeof(
char*);
354 template<
typename _Tp>
356 _S_write(
void* __to, _Tp __val)
357 { __builtin_memcpy(__to, &__val,
sizeof(_Tp)); }
359 template<
typename _Tp>
361 _S_read(
const void* __from)
364 __builtin_memcpy(&__val, __from,
sizeof(_Tp));
372 template<
typename _Alloc,
typename _Resource>
373 class __resource_adaptor_imp
374 :
public _Resource,
private __resource_adaptor_common
376 using memory_resource = _Resource;
378 static_assert(is_same<char,
380 "Allocator's value_type is char");
381 static_assert(is_same<
char*,
383 "Allocator's pointer type is value_type*");
384 static_assert(is_same<
const char*,
386 "Allocator's const_pointer type is value_type const*");
387 static_assert(is_same<
void*,
389 "Allocator's void_pointer type is void*");
390 static_assert(is_same<
const void*,
392 "Allocator's const_void_pointer type is void const*");
395 using allocator_type = _Alloc;
397 __resource_adaptor_imp() =
default;
398 __resource_adaptor_imp(
const __resource_adaptor_imp&) =
default;
399 __resource_adaptor_imp(__resource_adaptor_imp&&) =
default;
401 explicit __resource_adaptor_imp(
const _Alloc& __a2)
405 explicit __resource_adaptor_imp(_Alloc&& __a2)
409 __resource_adaptor_imp&
410 operator=(
const __resource_adaptor_imp&) =
default;
412 allocator_type get_allocator() const noexcept {
return _M_alloc; }
416 do_allocate(
size_t __bytes,
size_t __alignment)
override
419#if ! ((defined __sun__ || defined __VXWORKS__) && defined __i386__)
420 if (__alignment ==
alignof(max_align_t))
421 return _M_allocate<alignof(max_align_t)>(__bytes);
426 return _M_alloc.allocate(__bytes);
428 return _M_allocate<2>(__bytes);
430 return _M_allocate<4>(__bytes);
432 return _M_allocate<8>(__bytes);
434 const _AlignMgr __mgr(__bytes, __alignment);
438 return __mgr._M_adjust(_M_alloc.allocate(__mgr._M_alloc_size()));
442 do_deallocate(
void* __ptr,
size_t __bytes,
size_t __alignment)
noexcept
445#if ! ((defined __sun__ || defined __VXWORKS__) && defined __i386__)
446 if (__alignment ==
alignof(max_align_t))
447 return (
void) _M_deallocate<alignof(max_align_t)>(__ptr, __bytes);
452 return (
void) _M_alloc.deallocate((
char*)__ptr, __bytes);
454 return (
void) _M_deallocate<2>(__ptr, __bytes);
456 return (
void) _M_deallocate<4>(__ptr, __bytes);
458 return (
void) _M_deallocate<8>(__ptr, __bytes);
460 const _AlignMgr __mgr(__bytes, __alignment);
462 _M_alloc.deallocate(__mgr._M_unadjust((
char*)__ptr),
463 __mgr._M_alloc_size());
467 do_is_equal(
const memory_resource& __other)
const noexcept override
470 if (
auto __p =
dynamic_cast<const __resource_adaptor_imp*
>(&__other))
471 return _M_alloc == __p->_M_alloc;
473 if (
this == &__other)
480 template<
size_t _Num>
481 struct _Aligned_type {
alignas(_Num)
char __c[_Num]; };
484 template<
size_t _Num,
typename _Tp = _Aligned_type<_Num>>
486 _M_allocate(
size_t __bytes)
488 typename allocator_traits<_Alloc>::template
489 rebind_alloc<_Tp> __a2(_M_alloc);
490 const size_t __n = (__bytes + _Num - 1) / _Num;
491 return __a2.allocate(__n);
495 template<
size_t _Num,
typename _Tp = _Aligned_type<_Num>>
497 _M_deallocate(
void* __ptr,
size_t __bytes)
noexcept
499 typename allocator_traits<_Alloc>::template
500 rebind_alloc<_Tp> __a2(_M_alloc);
501 const size_t __n = (__bytes + _Num - 1) / _Num;
502 __a2.deallocate((_Tp*)__ptr, __n);
510 inline memory_resource*
513 using type = resource_adaptor<std::__new_allocator<char>>;
514 alignas(type)
static unsigned char __buf[
sizeof(type)];
515 static type* __r =
new(__buf) type;
519 inline memory_resource*
522 class type final :
public memory_resource
525 do_allocate(
size_t,
size_t)
override
526 { std::__throw_bad_alloc(); }
529 do_deallocate(
void*,
size_t,
size_t)
noexcept override
533 do_is_equal(
const memory_resource& __other)
const noexcept override
534 {
return this == &__other; }
537 alignas(type)
static unsigned char __buf[
sizeof(type)];
538 static type* __r =
new(__buf) type;
546 __get_default_resource()
548 using type = atomic<memory_resource*>;
549 alignas(type)
static unsigned char __buf[
sizeof(type)];
556 inline memory_resource*
557 get_default_resource() noexcept
558 {
return __get_default_resource().load(); }
561 inline memory_resource*
562 set_default_resource(memory_resource* __r)
noexcept
565 __r = new_delete_resource();
566 return __get_default_resource().exchange(__r);
573_GLIBCXX_END_NAMESPACE_VERSION
memory_resource * new_delete_resource() noexcept
A pmr::memory_resource that uses new to allocate memory.
memory_resource * null_memory_resource() noexcept
A pmr::memory_resource that always throws bad_alloc
void * align(size_t __align, size_t __size, void *&__ptr, size_t &__space) noexcept
Fit aligned storage in buffer.
constexpr auto tuple_cat(_Tpls &&... __tpls) -> typename __tuple_cat_result< _Tpls... >::__type
Create a tuple containing all elements from multiple tuple-like objects.
constexpr tuple< _Elements &&... > forward_as_tuple(_Elements &&... __args) noexcept
Create a tuple of lvalue or rvalue references to the arguments.
constexpr tuple< typename __decay_and_strip< _Elements >::__type... > make_tuple(_Elements &&... __args)
Create a tuple containing copies of the arguments.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
constexpr piecewise_construct_t piecewise_construct
Tag for piecewise construction of std::pair objects.
ISO C++ entities toplevel namespace is std.
GNU extensions for public use.
Generic atomic type, primary class template.
typename _Ptr< __v_pointer, void >::type void_pointer
The allocator's void pointer type.
__detected_or_t< value_type *, __pointer, _Alloc > pointer
The allocator's pointer type.
typename _Ptr< __cv_pointer, const void >::type const_void_pointer
The allocator's const void pointer type.
typename _Ptr< __c_pointer, const value_type >::type const_pointer
The allocator's const pointer type.
_Alloc::value_type value_type
The allocated type.
Struct holding two objects of arbitrary type.
_T1 first
The first member.
_T2 second
The second member.