9 #ifndef INCLUDED_POLYMORPHIC_ALLOCATOR_DOT_H 10 #define INCLUDED_POLYMORPHIC_ALLOCATOR_DOT_H 12 #if __cpp_lib_memory_resource < 201603 18 #include <scoped_allocator> 20 #include <cpp17/cstddef.h> 29 static constexpr
size_t max_align =
alignof(max_align_t);
31 static std::atomic<memory_resource*> s_default_resource;
39 void* allocate(
size_t bytes,
size_t alignment = max_align)
41 return do_allocate(bytes, alignment);
43 void deallocate(
void* p,
size_t bytes,
size_t alignment = max_align)
45 return do_deallocate(p, bytes, alignment);
55 return do_is_equal(other);
59 virtual void* do_allocate(
size_t bytes,
size_t alignment) = 0;
60 virtual void do_deallocate(
void* p,
size_t bytes,
size_t alignment) = 0;
61 virtual bool do_is_equal(
const memory_resource& other)
const noexcept = 0;
70 return &a == &b || a.is_equal(b);
87 using value_type = Tp;
91 using size_type = size_t;
92 using difference_type = ptrdiff_t;
93 using reference = Tp&;
94 using const_reference = Tp
const&;
96 using const_pointer = Tp
const*;
105 Tp* allocate(
size_t n);
106 void deallocate(Tp* p,
size_t n);
114 template <
class T1,
class T2>
119 template <
class T1,
class T2>
124 template <
size_t Align>
159 template <
class Allocator>
161 typename std::allocator_traits<Allocator>::template rebind_alloc<
165 template <
size_t Align>
166 void* allocate_imp(
size_t bytes);
168 template <
size_t Align>
169 void deallocate_imp(
void* p,
size_t bytes);
172 typedef Allocator allocator_type;
178 template <
class Allocator2>
181 typename std::enable_if<
182 std::is_convertible<Allocator2, Allocator>::value,
187 void* do_allocate(
size_t bytes,
size_t alignment = 0)
override;
188 void do_deallocate(
void* p,
size_t bytes,
size_t alignment = 0)
override;
190 bool do_is_equal(
const memory_resource& other)
const noexcept
override;
192 allocator_type get_allocator()
const 206 template <
class Allocator>
208 typename std::allocator_traits<Allocator>::template rebind_alloc<byte>>;
225 __details::polymorphic_allocator_imp<Tp>> {
227 typedef std::scoped_allocator_adaptor<Imp> Base;
232 template <
typename U>
245 : Base(Imp((other.resource())))
264 return this->outer_allocator().resource();
268 template <
class T1,
class T2>
269 inline bool operator==(
272 return a.outer_allocator() == b.outer_allocator();
275 template <
class T1,
class T2>
276 inline bool operator!=(
288 inline pmr::memory_resource::~memory_resource() =
default;
292 memory_resource* ret = pmr::memory_resource::s_default_resource.load();
293 if (
nullptr == ret) {
294 ret = new_delete_resource_singleton();
303 r = new_delete_resource_singleton();
308 pmr::memory_resource::s_default_resource.store(r);
312 template <
class Allocator>
313 template <
class Allocator2>
316 typename std::enable_if<
317 std::is_convertible<Allocator2, Allocator>::value,
319 : m_alloc(std::forward<Allocator2>(a2))
323 template <
class Allocator>
324 template <
size_t Align>
329 size_t chunks = (bytes + Align - 1) / Align;
332 typename std::allocator_traits<Allocator>::template rebind_traits<chunk>
334 typename chunk_traits::allocator_type rebound(m_alloc);
335 return chunk_traits::allocate(rebound, chunks);
338 template <
class Allocator>
339 template <
size_t Align>
341 void* p,
size_t bytes)
344 size_t chunks = (bytes + Align - 1) / Align;
347 typename std::allocator_traits<Allocator>::template rebind_traits<chunk>
349 typename chunk_traits::allocator_type rebound(m_alloc);
350 return chunk_traits::deallocate(rebound, static_cast<chunk*>(p), chunks);
353 template <
class Allocator>
355 size_t bytes,
size_t alignment)
357 static const size_t max_natural_alignment =
sizeof(max_align_t);
359 if (0 == alignment) {
361 alignment = ((bytes ^ (bytes - 1)) >> 1) + 1;
362 if (alignment > max_natural_alignment) {
363 alignment = max_natural_alignment;
369 return allocate_imp<1>(bytes);
371 return allocate_imp<2>(bytes);
373 return allocate_imp<4>(bytes);
375 return allocate_imp<8>(bytes);
377 return allocate_imp<16>(bytes);
379 return allocate_imp<32>(bytes);
381 return allocate_imp<64>(bytes);
383 size_t chunks = (bytes +
sizeof(
void*) + alignment - 1) / 64;
384 size_t chunkbytes = chunks * 64;
385 void* original = allocate_imp<64>(chunkbytes);
388 char* p =
static_cast<char*
>(original) +
sizeof(
void*);
392 p -= (size_t(p)) & (alignment - 1);
395 reinterpret_cast<void**
>(p)[-1] = original;
402 template <
class Allocator>
404 void* p,
size_t bytes,
size_t alignment)
406 static const size_t max_natural_alignment =
sizeof(max_align_t);
408 if (0 == alignment) {
410 alignment = ((bytes ^ (bytes - 1)) >> 1) + 1;
411 if (alignment > max_natural_alignment) {
412 alignment = max_natural_alignment;
418 deallocate_imp<1>(p, bytes);
421 deallocate_imp<2>(p, bytes);
424 deallocate_imp<4>(p, bytes);
427 deallocate_imp<8>(p, bytes);
430 deallocate_imp<16>(p, bytes);
433 deallocate_imp<32>(p, bytes);
436 deallocate_imp<64>(p, bytes);
439 size_t chunks = (bytes +
sizeof(
void*) + alignment - 1) / 64;
440 size_t chunkbytes = chunks * 64;
441 void* original =
reinterpret_cast<void**
>(p)[-1];
443 deallocate_imp<64>(original, chunkbytes);
448 template <
class Allocator>
452 const auto* other_p =
dynamic_cast<const resource_adaptor_imp*
>(&other);
455 return this->m_alloc == other_p->m_alloc;
462 namespace __pmrd = pmr::__details;
466 : m_resource(get_default_resource())
473 : m_resource(r !=
nullptr ? r : get_default_resource())
481 : m_resource(other.resource())
488 return static_cast<Tp*
>(m_resource->allocate(n *
sizeof(Tp),
alignof(Tp)));
494 m_resource->deallocate(p, n *
sizeof(Tp),
alignof(Tp));
512 template <
class T1,
class T2>
513 inline bool __pmrd::operator==(
523 return *a.resource() == *b.resource();
526 template <
class T1,
class T2>
527 inline bool __pmrd::operator!=(
531 return *a.resource() != *b.resource();
537 #endif // ! defined(INCLUDED_POLYMORPHIC_ALLOCATOR_DOT_H)
static __attribute__((unused)) dart_ret_t dart_gptr_incaddr(dart_gptr_t *gptr
Add 'offs' to the address specified by the global pointer.
see https://en.cppreference.com/w/cpp/feature_test for recommended feature tests