1cc89063bSNico Weber //===----------------------------------------------------------------------===// 2cc89063bSNico Weber // 3cc89063bSNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4cc89063bSNico Weber // See https://llvm.org/LICENSE.txt for license information. 5cc89063bSNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6cc89063bSNico Weber // 7cc89063bSNico Weber //===----------------------------------------------------------------------===// 8cc89063bSNico Weber 9cc89063bSNico Weber #ifndef SUPPORT_CONTROLLED_ALLOCATORS_H 10cc89063bSNico Weber #define SUPPORT_CONTROLLED_ALLOCATORS_H 11cc89063bSNico Weber 12cc89063bSNico Weber #include <memory> 13cc89063bSNico Weber #include <type_traits> 14cc89063bSNico Weber #include <cstddef> 15cc89063bSNico Weber #include <cstdlib> 16cc89063bSNico Weber #include <cstring> 17cc89063bSNico Weber #include <cstdint> 18cc89063bSNico Weber #include <cassert> 19d5e26775SNikolas Klauser #include <new> 20d5e26775SNikolas Klauser 21cc89063bSNico Weber #include "test_macros.h" 22cc89063bSNico Weber #include "type_id.h" 23cc89063bSNico Weber 24cc89063bSNico Weber #if TEST_STD_VER < 11 25cc89063bSNico Weber #error This header requires C++11 or greater 26cc89063bSNico Weber #endif 27cc89063bSNico Weber 28cc89063bSNico Weber struct AllocController; 29cc89063bSNico Weber // 'AllocController' is a concrete type that instruments and controls the 30cc89063bSNico Weber // behavior of test allocators. 31cc89063bSNico Weber 32*fb855eb9SMark de Wever template <class T, std::size_t ID = 0> 33cc89063bSNico Weber class CountingAllocator; 34cc89063bSNico Weber // 'CountingAllocator' is an basic implementation of the 'Allocator' 35cc89063bSNico Weber // requirements that use the 'AllocController' interface. 36cc89063bSNico Weber 37cc89063bSNico Weber template <class T> 38cc89063bSNico Weber class MinAlignAllocator; 39cc89063bSNico Weber // 'MinAlignAllocator' is an instrumented test type which implements the 40cc89063bSNico Weber // 'Allocator' requirements. 'MinAlignAllocator' ensures that it *never* 41cc89063bSNico Weber // returns a pointer to over-aligned storage. For example 42cc89063bSNico Weber // 'MinAlignPointer<char>{}.allocate(...)' will never a 2-byte aligned 43cc89063bSNico Weber // pointer. 44cc89063bSNico Weber 45cc89063bSNico Weber template <class T> 46cc89063bSNico Weber class NullAllocator; 47cc89063bSNico Weber // 'NullAllocator' is an instrumented test type which implements the 48cc89063bSNico Weber // 'Allocator' requirements except that 'allocator' and 'deallocate' are 49cc89063bSNico Weber // nops. 50cc89063bSNico Weber 51cc89063bSNico Weber 52cc89063bSNico Weber #define DISALLOW_COPY(Type) \ 53cc89063bSNico Weber Type(Type const&) = delete; \ 54cc89063bSNico Weber Type& operator=(Type const&) = delete 55cc89063bSNico Weber 56cc89063bSNico Weber constexpr std::size_t MaxAlignV = alignof(std::max_align_t); 57cc89063bSNico Weber 58cc89063bSNico Weber struct TestException {}; 59cc89063bSNico Weber 60cc89063bSNico Weber struct AllocController { 61cc89063bSNico Weber int copy_constructed = 0; 62cc89063bSNico Weber int move_constructed = 0; 63cc89063bSNico Weber 64cc89063bSNico Weber int alive = 0; 65cc89063bSNico Weber int alloc_count = 0; 66cc89063bSNico Weber int dealloc_count = 0; 67cc89063bSNico Weber int is_equal_count = 0; 68cc89063bSNico Weber 69cc89063bSNico Weber std::size_t alive_size; 70cc89063bSNico Weber std::size_t allocated_size; 71cc89063bSNico Weber std::size_t deallocated_size; 72cc89063bSNico Weber 73cc89063bSNico Weber std::size_t last_size = 0; 74cc89063bSNico Weber std::size_t last_align = 0; 75cc89063bSNico Weber void * last_pointer = 0; 76cc89063bSNico Weber 77cc89063bSNico Weber std::size_t last_alloc_size = 0; 78cc89063bSNico Weber std::size_t last_alloc_align = 0; 79cc89063bSNico Weber void * last_alloc_pointer = nullptr; 80cc89063bSNico Weber 81cc89063bSNico Weber std::size_t last_dealloc_size = 0; 82cc89063bSNico Weber std::size_t last_dealloc_align = 0; 83cc89063bSNico Weber void * last_dealloc_pointer = nullptr; 84cc89063bSNico Weber 85cc89063bSNico Weber bool throw_on_alloc = false; 86cc89063bSNico Weber 87cc89063bSNico Weber int construct_called = 0; 88cc89063bSNico Weber void *last_construct_pointer = nullptr; 89cc89063bSNico Weber TypeID const* last_construct_alloc = nullptr; 90cc89063bSNico Weber TypeID const* last_construct_type = nullptr; 91cc89063bSNico Weber TypeID const* last_construct_args = nullptr; 92cc89063bSNico Weber 93cc89063bSNico Weber int destroy_called = 0; 94cc89063bSNico Weber void *last_destroy_pointer = nullptr; 95cc89063bSNico Weber TypeID const* last_destroy_alloc = nullptr; 96cc89063bSNico Weber TypeID const* last_destroy_type = nullptr; 97cc89063bSNico Weber 98cc89063bSNico Weber AllocController() = default; 99cc89063bSNico Weber countAllocAllocController100*fb855eb9SMark de Wever void countAlloc(void* p, std::size_t s, size_t a) { 101cc89063bSNico Weber ++alive; 102cc89063bSNico Weber ++alloc_count; 103cc89063bSNico Weber alive_size += s; 104cc89063bSNico Weber allocated_size += s; 105cc89063bSNico Weber last_pointer = last_alloc_pointer = p; 106cc89063bSNico Weber last_size = last_alloc_size = s; 107cc89063bSNico Weber last_align = last_alloc_align = a; 108cc89063bSNico Weber } 109cc89063bSNico Weber countDeallocAllocController110*fb855eb9SMark de Wever void countDealloc(void* p, std::size_t s, size_t a) { 111cc89063bSNico Weber --alive; 112cc89063bSNico Weber ++dealloc_count; 113cc89063bSNico Weber alive_size -= s; 114cc89063bSNico Weber deallocated_size += s; 115cc89063bSNico Weber last_pointer = last_dealloc_pointer = p; 116cc89063bSNico Weber last_size = last_dealloc_size = s; 117cc89063bSNico Weber last_align = last_dealloc_align = a; 118cc89063bSNico Weber } 119cc89063bSNico Weber 120cc89063bSNico Weber template <class ...Args, class Alloc, class Tp> countConstructAllocController121cc89063bSNico Weber void countConstruct(Alloc const&, Tp *p) { 122cc89063bSNico Weber ++construct_called; 123cc89063bSNico Weber last_construct_pointer = p; 124cc89063bSNico Weber last_construct_alloc = &makeTypeID<Alloc>(); 125cc89063bSNico Weber last_construct_type = &makeTypeID<Tp>(); 126cc89063bSNico Weber last_construct_args = &makeArgumentID<Args...>(); 127cc89063bSNico Weber } 128cc89063bSNico Weber 129cc89063bSNico Weber template <class Alloc, class Tp> countDestroyAllocController130cc89063bSNico Weber void countDestroy(Alloc const&, Tp *p) { 131cc89063bSNico Weber ++destroy_called; 132cc89063bSNico Weber last_destroy_alloc = &makeTypeID<Alloc>(); 133cc89063bSNico Weber last_destroy_type = &makeTypeID<Tp>(); 134cc89063bSNico Weber last_destroy_pointer = p; 135cc89063bSNico Weber } 136cc89063bSNico Weber resetAllocController137cc89063bSNico Weber void reset() { std::memset(this, 0, sizeof(*this)); } resetConstructDestroyAllocController138cc89063bSNico Weber void resetConstructDestroy() { 139cc89063bSNico Weber construct_called = 0; 140cc89063bSNico Weber last_construct_pointer = nullptr; 141cc89063bSNico Weber last_construct_alloc = last_construct_args = last_construct_type = nullptr; 142cc89063bSNico Weber destroy_called = 0; 143cc89063bSNico Weber last_destroy_alloc = nullptr; 144cc89063bSNico Weber last_destroy_pointer = nullptr; 145cc89063bSNico Weber } 146cc89063bSNico Weber public: checkAllocAllocController147*fb855eb9SMark de Wever bool checkAlloc(void* p, std::size_t s, size_t a) const { 148cc89063bSNico Weber return p == last_alloc_pointer && 149cc89063bSNico Weber s == last_alloc_size && 150cc89063bSNico Weber a == last_alloc_align; 151cc89063bSNico Weber } 152cc89063bSNico Weber checkAllocAllocController153*fb855eb9SMark de Wever bool checkAlloc(void* p, std::size_t s) const { 154cc89063bSNico Weber return p == last_alloc_pointer && 155cc89063bSNico Weber s == last_alloc_size; 156cc89063bSNico Weber } 157cc89063bSNico Weber checkAllocAtLeastAllocController158*fb855eb9SMark de Wever bool checkAllocAtLeast(void* p, std::size_t s, size_t a) const { 159cc89063bSNico Weber return p == last_alloc_pointer && 160cc89063bSNico Weber s <= last_alloc_size && 161cc89063bSNico Weber a <= last_alloc_align; 162cc89063bSNico Weber } 163cc89063bSNico Weber checkAllocAtLeastAllocController164*fb855eb9SMark de Wever bool checkAllocAtLeast(void* p, std::size_t s) const { 165cc89063bSNico Weber return p == last_alloc_pointer && 166cc89063bSNico Weber s <= last_alloc_size; 167cc89063bSNico Weber } 168cc89063bSNico Weber checkDeallocAllocController169*fb855eb9SMark de Wever bool checkDealloc(void* p, std::size_t s, size_t a) const { 170cc89063bSNico Weber return p == last_dealloc_pointer && 171cc89063bSNico Weber s == last_dealloc_size && 172cc89063bSNico Weber a == last_dealloc_align; 173cc89063bSNico Weber } 174cc89063bSNico Weber checkDeallocAllocController175*fb855eb9SMark de Wever bool checkDealloc(void* p, std::size_t s) const { 176cc89063bSNico Weber return p == last_dealloc_pointer && 177cc89063bSNico Weber s == last_dealloc_size; 178cc89063bSNico Weber } 179cc89063bSNico Weber checkDeallocMatchesAllocAllocController180cc89063bSNico Weber bool checkDeallocMatchesAlloc() const { 181cc89063bSNico Weber return last_dealloc_pointer == last_alloc_pointer && 182cc89063bSNico Weber last_dealloc_size == last_alloc_size && 183cc89063bSNico Weber last_dealloc_align == last_alloc_align; 184cc89063bSNico Weber } 185cc89063bSNico Weber 186cc89063bSNico Weber template <class ...Args, class Alloc, class Tp> checkConstructAllocController187cc89063bSNico Weber bool checkConstruct(Alloc const&, Tp *p) const { 188cc89063bSNico Weber auto expectAlloc = &makeTypeID<Alloc>(); 189cc89063bSNico Weber auto expectTp = &makeTypeID<Tp>(); 190cc89063bSNico Weber auto expectArgs = &makeArgumentID<Args...>(); 191e7cee55cSLouis Dionne if (last_construct_pointer != p) 192e7cee55cSLouis Dionne return false; 193e7cee55cSLouis Dionne if (last_construct_alloc != expectAlloc) 194e7cee55cSLouis Dionne return false; 195e7cee55cSLouis Dionne if (last_construct_type != expectTp) 196e7cee55cSLouis Dionne return false; 197e7cee55cSLouis Dionne if (last_construct_args != expectArgs) 198e7cee55cSLouis Dionne return false; 199e7cee55cSLouis Dionne return true; 200cc89063bSNico Weber } 201cc89063bSNico Weber 202cc89063bSNico Weber template <class Alloc, class Tp> checkDestroyAllocController203cc89063bSNico Weber bool checkDestroy(Alloc const&, Tp *p) const { 204cc89063bSNico Weber return last_destroy_pointer == p && 205cc89063bSNico Weber last_destroy_alloc == &makeTypeID<Alloc>() && 206cc89063bSNico Weber last_destroy_type == &makeTypeID<Tp>(); 207cc89063bSNico Weber } 208cc89063bSNico Weber checkDestroyMatchesConstructAllocController209cc89063bSNico Weber bool checkDestroyMatchesConstruct() const { 210cc89063bSNico Weber return last_destroy_pointer == last_construct_pointer && 211cc89063bSNico Weber last_destroy_type == last_construct_type; 212cc89063bSNico Weber } 213cc89063bSNico Weber countIsEqualAllocController214cc89063bSNico Weber void countIsEqual() { 215cc89063bSNico Weber ++is_equal_count; 216cc89063bSNico Weber } 217cc89063bSNico Weber checkIsEqualCalledEqAllocController218cc89063bSNico Weber bool checkIsEqualCalledEq(int n) const { 219cc89063bSNico Weber return is_equal_count == n; 220cc89063bSNico Weber } 221cc89063bSNico Weber private: 222cc89063bSNico Weber DISALLOW_COPY(AllocController); 223cc89063bSNico Weber }; 224cc89063bSNico Weber 225*fb855eb9SMark de Wever template <class T, std::size_t ID> 226cc89063bSNico Weber class CountingAllocator 227cc89063bSNico Weber { 228cc89063bSNico Weber public: 229cc89063bSNico Weber typedef T value_type; 230cc89063bSNico Weber typedef T* pointer; 231cc89063bSNico Weber 232cc89063bSNico Weber template <class U> 233cc89063bSNico Weber struct rebind { using other = CountingAllocator<U, ID>; }; 234cc89063bSNico Weber 235cc89063bSNico Weber CountingAllocator() = delete; CountingAllocator(AllocController & PP)236cc89063bSNico Weber explicit CountingAllocator(AllocController& PP) : P(&PP) {} 237cc89063bSNico Weber CountingAllocator(CountingAllocator const & other)238cc89063bSNico Weber CountingAllocator(CountingAllocator const& other) : P(other.P) { 239cc89063bSNico Weber P->copy_constructed += 1; 240cc89063bSNico Weber } 241cc89063bSNico Weber CountingAllocator(CountingAllocator && other)242cc89063bSNico Weber CountingAllocator(CountingAllocator&& other) : P(other.P) { 243cc89063bSNico Weber P->move_constructed += 1; 244cc89063bSNico Weber } 245cc89063bSNico Weber 246cc89063bSNico Weber template <class U> CountingAllocator(CountingAllocator<U,ID> const & other)247cc89063bSNico Weber CountingAllocator(CountingAllocator<U, ID> const& other) TEST_NOEXCEPT : P(other.P) { 248cc89063bSNico Weber P->copy_constructed += 1; 249cc89063bSNico Weber } 250cc89063bSNico Weber 251cc89063bSNico Weber template <class U> CountingAllocator(CountingAllocator<U,ID> && other)252cc89063bSNico Weber CountingAllocator(CountingAllocator<U, ID>&& other) TEST_NOEXCEPT : P(other.P) { 253cc89063bSNico Weber P->move_constructed += 1; 254cc89063bSNico Weber } 255cc89063bSNico Weber allocate(std::size_t n)256cc89063bSNico Weber T* allocate(std::size_t n) 257cc89063bSNico Weber { 258cc89063bSNico Weber void* ret = ::operator new(n*sizeof(T)); 259cc89063bSNico Weber P->countAlloc(ret, n*sizeof(T), alignof(T)); 260cc89063bSNico Weber return static_cast<T*>(ret); 261cc89063bSNico Weber } 262cc89063bSNico Weber deallocate(T * p,std::size_t n)263cc89063bSNico Weber void deallocate(T* p, std::size_t n) 264cc89063bSNico Weber { 265cc89063bSNico Weber void* vp = static_cast<void*>(p); 266cc89063bSNico Weber P->countDealloc(vp, n*sizeof(T), alignof(T)); 267cc89063bSNico Weber ::operator delete(vp); 268cc89063bSNico Weber } 269cc89063bSNico Weber 270cc89063bSNico Weber template <class U, class ...Args> construct(U * p,Args &&...args)271cc89063bSNico Weber void construct(U *p, Args&&... args) { 272cc89063bSNico Weber ::new ((void*)p) U(std::forward<Args>(args)...); 273cc89063bSNico Weber P->countConstruct<Args&&...>(*this, p); 274cc89063bSNico Weber } 275cc89063bSNico Weber 276cc89063bSNico Weber template <class U> destroy(U * p)277cc89063bSNico Weber void destroy(U* p) { 278cc89063bSNico Weber p->~U(); 279cc89063bSNico Weber P->countDestroy(*this, p); 280cc89063bSNico Weber } 281cc89063bSNico Weber getController()282cc89063bSNico Weber AllocController& getController() const { return *P; } 283cc89063bSNico Weber 284cc89063bSNico Weber private: 285*fb855eb9SMark de Wever template <class Tp, std::size_t XID> friend class CountingAllocator; 286cc89063bSNico Weber AllocController *P; 287cc89063bSNico Weber }; 288cc89063bSNico Weber 289cc89063bSNico Weber 290*fb855eb9SMark de Wever template <std::size_t ID> 291cc89063bSNico Weber class CountingAllocator<void, ID> 292cc89063bSNico Weber { 293cc89063bSNico Weber public: 294cc89063bSNico Weber typedef void* pointer; 295cc89063bSNico Weber typedef const void* const_pointer; 296cc89063bSNico Weber typedef void value_type; 297cc89063bSNico Weber 298cc89063bSNico Weber template <class U> 299cc89063bSNico Weber struct rebind { using other = CountingAllocator<U, ID>; }; 300cc89063bSNico Weber 301cc89063bSNico Weber CountingAllocator() = delete; CountingAllocator(AllocController & PP)302cc89063bSNico Weber explicit CountingAllocator(AllocController& PP) : P(&PP) {} 303cc89063bSNico Weber CountingAllocator(CountingAllocator const & other)304cc89063bSNico Weber CountingAllocator(CountingAllocator const& other) : P(other.P) { 305cc89063bSNico Weber P->copy_constructed += 1; 306cc89063bSNico Weber } 307cc89063bSNico Weber CountingAllocator(CountingAllocator && other)308cc89063bSNico Weber CountingAllocator(CountingAllocator&& other) : P(other.P) { 309cc89063bSNico Weber P->move_constructed += 1; 310cc89063bSNico Weber } 311cc89063bSNico Weber 312cc89063bSNico Weber template <class U> CountingAllocator(CountingAllocator<U,ID> const & other)313cc89063bSNico Weber CountingAllocator(CountingAllocator<U, ID> const& other) TEST_NOEXCEPT : P(other.P) { 314cc89063bSNico Weber P->copy_constructed += 1; 315cc89063bSNico Weber } 316cc89063bSNico Weber 317cc89063bSNico Weber template <class U> CountingAllocator(CountingAllocator<U,ID> && other)318cc89063bSNico Weber CountingAllocator(CountingAllocator<U, ID>&& other) TEST_NOEXCEPT : P(other.P) { 319cc89063bSNico Weber P->move_constructed += 1; 320cc89063bSNico Weber } 321cc89063bSNico Weber 322cc89063bSNico Weber void construct(...) = delete; 323cc89063bSNico Weber void destroy(void*) = delete; 324cc89063bSNico Weber getController()325cc89063bSNico Weber AllocController& getController() const { return *P; } 326cc89063bSNico Weber 327cc89063bSNico Weber private: 328*fb855eb9SMark de Wever template <class Tp, std::size_t> friend class CountingAllocator; 329cc89063bSNico Weber AllocController *P; 330cc89063bSNico Weber }; 331cc89063bSNico Weber 332*fb855eb9SMark de Wever template <class T, class U, std::size_t ID> 333cc89063bSNico Weber inline bool operator==(CountingAllocator<T, ID> const& x, 334cc89063bSNico Weber CountingAllocator<U, ID> const& y) { 335cc89063bSNico Weber return &x.getController() == &y.getController(); 336cc89063bSNico Weber } 337cc89063bSNico Weber 338*fb855eb9SMark de Wever template <class T, class U, std::size_t ID> 339cc89063bSNico Weber inline bool operator!=(CountingAllocator<T, ID> const& x, 340cc89063bSNico Weber CountingAllocator<U, ID> const& y) { 341cc89063bSNico Weber return !(x == y); 342cc89063bSNico Weber } 343cc89063bSNico Weber 344cc89063bSNico Weber template <class T> 345cc89063bSNico Weber class MinAlignedAllocator 346cc89063bSNico Weber { 347cc89063bSNico Weber public: 348cc89063bSNico Weber typedef T value_type; 349cc89063bSNico Weber typedef T* pointer; 350cc89063bSNico Weber 351cc89063bSNico Weber MinAlignedAllocator() = delete; 352cc89063bSNico Weber MinAlignedAllocator(AllocController & R)353cc89063bSNico Weber explicit MinAlignedAllocator(AllocController& R) : P(&R) {} 354cc89063bSNico Weber MinAlignedAllocator(MinAlignedAllocator const & other)355cc89063bSNico Weber MinAlignedAllocator(MinAlignedAllocator const& other) : P(other.P) { 356cc89063bSNico Weber P->copy_constructed += 1; 357cc89063bSNico Weber } 358cc89063bSNico Weber MinAlignedAllocator(MinAlignedAllocator && other)359cc89063bSNico Weber MinAlignedAllocator(MinAlignedAllocator&& other) : P(other.P) { 360cc89063bSNico Weber P->move_constructed += 1; 361cc89063bSNico Weber } 362cc89063bSNico Weber 363cc89063bSNico Weber template <class U> MinAlignedAllocator(MinAlignedAllocator<U> const & other)364cc89063bSNico Weber MinAlignedAllocator(MinAlignedAllocator<U> const& other) TEST_NOEXCEPT : P(other.P) { 365cc89063bSNico Weber P->copy_constructed += 1; 366cc89063bSNico Weber } 367cc89063bSNico Weber 368cc89063bSNico Weber template <class U> MinAlignedAllocator(MinAlignedAllocator<U> && other)369cc89063bSNico Weber MinAlignedAllocator(MinAlignedAllocator<U>&& other) TEST_NOEXCEPT : P(other.P) { 370cc89063bSNico Weber P->move_constructed += 1; 371cc89063bSNico Weber } 372cc89063bSNico Weber allocate(std::size_t n)373cc89063bSNico Weber T* allocate(std::size_t n) { 374cc89063bSNico Weber char* aligned_ptr = (char*)::operator new(alloc_size(n*sizeof(T))); 375cc89063bSNico Weber assert(is_max_aligned(aligned_ptr)); 376cc89063bSNico Weber 377cc89063bSNico Weber char* unaligned_ptr = aligned_ptr + alignof(T); 378cc89063bSNico Weber assert(is_min_aligned(unaligned_ptr)); 379cc89063bSNico Weber 380cc89063bSNico Weber P->countAlloc(unaligned_ptr, n * sizeof(T), alignof(T)); 381cc89063bSNico Weber 382cc89063bSNico Weber return ((T*)unaligned_ptr); 383cc89063bSNico Weber } 384cc89063bSNico Weber deallocate(T * p,std::size_t n)385cc89063bSNico Weber void deallocate(T* p, std::size_t n) { 386cc89063bSNico Weber assert(is_min_aligned(p)); 387cc89063bSNico Weber 388cc89063bSNico Weber char* aligned_ptr = ((char*)p) - alignof(T); 389cc89063bSNico Weber assert(is_max_aligned(aligned_ptr)); 390cc89063bSNico Weber 391cc89063bSNico Weber P->countDealloc(p, n*sizeof(T), alignof(T)); 392cc89063bSNico Weber 393cc89063bSNico Weber return ::operator delete(static_cast<void*>(aligned_ptr)); 394cc89063bSNico Weber } 395cc89063bSNico Weber 396cc89063bSNico Weber template <class U, class ...Args> construct(U * p,Args &&...args)397cc89063bSNico Weber void construct(U *p, Args&&... args) { 398cc89063bSNico Weber auto *c = ::new ((void*)p) U(std::forward<Args>(args)...); 399cc89063bSNico Weber P->countConstruct<Args&&...>(*this, p); 400cc89063bSNico Weber } 401cc89063bSNico Weber 402cc89063bSNico Weber template <class U> destroy(U * p)403cc89063bSNico Weber void destroy(U* p) { 404cc89063bSNico Weber p->~U(); 405cc89063bSNico Weber P->countDestroy(*this, p); 406cc89063bSNico Weber } 407cc89063bSNico Weber getController()408cc89063bSNico Weber AllocController& getController() const { return *P; } 409cc89063bSNico Weber 410cc89063bSNico Weber private: 411cc89063bSNico Weber static const std::size_t BlockSize = alignof(std::max_align_t); 412cc89063bSNico Weber alloc_size(std::size_t s)413cc89063bSNico Weber static std::size_t alloc_size(std::size_t s) { 414cc89063bSNico Weber std::size_t bytes = (s + BlockSize - 1) & ~(BlockSize - 1); 415cc89063bSNico Weber bytes += BlockSize; 416cc89063bSNico Weber assert(bytes % BlockSize == 0); 417cc89063bSNico Weber return bytes; 418cc89063bSNico Weber } 419cc89063bSNico Weber is_max_aligned(void * p)420cc89063bSNico Weber static bool is_max_aligned(void* p) { 421cc89063bSNico Weber return reinterpret_cast<std::uintptr_t>(p) % BlockSize == 0; 422cc89063bSNico Weber } 423cc89063bSNico Weber is_min_aligned(void * p)424cc89063bSNico Weber static bool is_min_aligned(void* p) { 425cc89063bSNico Weber if (alignof(T) == BlockSize) { 426cc89063bSNico Weber return is_max_aligned(p); 427cc89063bSNico Weber } else { 428cc89063bSNico Weber return reinterpret_cast<std::uintptr_t>(p) % BlockSize == alignof(T); 429cc89063bSNico Weber } 430cc89063bSNico Weber } 431cc89063bSNico Weber 432cc89063bSNico Weber template <class Tp> friend class MinAlignedAllocator; 433cc89063bSNico Weber mutable AllocController *P; 434cc89063bSNico Weber }; 435cc89063bSNico Weber 436cc89063bSNico Weber 437cc89063bSNico Weber template <class T, class U> 438cc89063bSNico Weber inline bool operator==(MinAlignedAllocator<T> const& x, 439cc89063bSNico Weber MinAlignedAllocator<U> const& y) { 440cc89063bSNico Weber return &x.getController() == &y.getController(); 441cc89063bSNico Weber } 442cc89063bSNico Weber 443cc89063bSNico Weber template <class T, class U> 444cc89063bSNico Weber inline bool operator!=(MinAlignedAllocator<T> const& x, 445cc89063bSNico Weber MinAlignedAllocator<U> const& y) { 446cc89063bSNico Weber return !(x == y); 447cc89063bSNico Weber } 448cc89063bSNico Weber 449cc89063bSNico Weber template <class T> 450cc89063bSNico Weber class NullAllocator 451cc89063bSNico Weber { 452cc89063bSNico Weber public: 453cc89063bSNico Weber typedef T value_type; 454cc89063bSNico Weber typedef T* pointer; 455cc89063bSNico Weber NullAllocator() = delete; NullAllocator(AllocController & PP)456cc89063bSNico Weber explicit NullAllocator(AllocController& PP) : P(&PP) {} 457cc89063bSNico Weber NullAllocator(NullAllocator const & other)458cc89063bSNico Weber NullAllocator(NullAllocator const& other) : P(other.P) { 459cc89063bSNico Weber P->copy_constructed += 1; 460cc89063bSNico Weber } 461cc89063bSNico Weber NullAllocator(NullAllocator && other)462cc89063bSNico Weber NullAllocator(NullAllocator&& other) : P(other.P) { 463cc89063bSNico Weber P->move_constructed += 1; 464cc89063bSNico Weber } 465cc89063bSNico Weber 466cc89063bSNico Weber template <class U> NullAllocator(NullAllocator<U> const & other)467cc89063bSNico Weber NullAllocator(NullAllocator<U> const& other) TEST_NOEXCEPT : P(other.P) { 468cc89063bSNico Weber P->copy_constructed += 1; 469cc89063bSNico Weber } 470cc89063bSNico Weber 471cc89063bSNico Weber template <class U> NullAllocator(NullAllocator<U> && other)472cc89063bSNico Weber NullAllocator(NullAllocator<U>&& other) TEST_NOEXCEPT : P(other.P) { 473cc89063bSNico Weber P->move_constructed += 1; 474cc89063bSNico Weber } 475cc89063bSNico Weber allocate(std::size_t n)476cc89063bSNico Weber T* allocate(std::size_t n) 477cc89063bSNico Weber { 478cc89063bSNico Weber P->countAlloc(nullptr, n*sizeof(T), alignof(T)); 479cc89063bSNico Weber return nullptr; 480cc89063bSNico Weber } 481cc89063bSNico Weber deallocate(T * p,std::size_t n)482cc89063bSNico Weber void deallocate(T* p, std::size_t n) 483cc89063bSNico Weber { 484cc89063bSNico Weber void* vp = static_cast<void*>(p); 485cc89063bSNico Weber P->countDealloc(vp, n*sizeof(T), alignof(T)); 486cc89063bSNico Weber } 487cc89063bSNico Weber getController()488cc89063bSNico Weber AllocController& getController() const { return *P; } 489cc89063bSNico Weber 490cc89063bSNico Weber private: 491cc89063bSNico Weber template <class Tp> friend class NullAllocator; 492cc89063bSNico Weber AllocController *P; 493cc89063bSNico Weber }; 494cc89063bSNico Weber 495cc89063bSNico Weber template <class T, class U> 496cc89063bSNico Weber inline bool operator==(NullAllocator<T> const& x, 497cc89063bSNico Weber NullAllocator<U> const& y) { 498cc89063bSNico Weber return &x.getController() == &y.getController(); 499cc89063bSNico Weber } 500cc89063bSNico Weber 501cc89063bSNico Weber template <class T, class U> 502cc89063bSNico Weber inline bool operator!=(NullAllocator<T> const& x, 503cc89063bSNico Weber NullAllocator<U> const& y) { 504cc89063bSNico Weber return !(x == y); 505cc89063bSNico Weber } 506cc89063bSNico Weber 507cc89063bSNico Weber 508cc89063bSNico Weber #endif /* SUPPORT_CONTROLLED_ALLOCATORS_H */ 509