1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef TEST_ALLOCATOR_H 11 #define TEST_ALLOCATOR_H 12 13 #include <cstddef> 14 #include <type_traits> 15 #include <cstdlib> 16 #include <new> 17 #include <climits> 18 #include <cassert> 19 20 class test_alloc_base 21 { 22 protected: 23 static int time_to_throw; 24 public: 25 static int throw_after; 26 static int count; 27 static int alloc_count; 28 }; 29 30 int test_alloc_base::count = 0; 31 int test_alloc_base::time_to_throw = 0; 32 int test_alloc_base::alloc_count = 0; 33 int test_alloc_base::throw_after = INT_MAX; 34 35 template <class T> 36 class test_allocator 37 : public test_alloc_base 38 { 39 int data_; 40 41 template <class U> friend class test_allocator; 42 public: 43 44 typedef unsigned size_type; 45 typedef int difference_type; 46 typedef T value_type; 47 typedef value_type* pointer; 48 typedef const value_type* const_pointer; 49 typedef typename std::add_lvalue_reference<value_type>::type reference; 50 typedef typename std::add_lvalue_reference<const value_type>::type const_reference; 51 52 template <class U> struct rebind {typedef test_allocator<U> other;}; 53 throw()54 test_allocator() throw() : data_(0) {++count;} test_allocator(int i)55 explicit test_allocator(int i) throw() : data_(i) {++count;} throw()56 test_allocator(const test_allocator& a) throw() 57 : data_(a.data_) {++count;} test_allocator(const test_allocator<U> & a)58 template <class U> test_allocator(const test_allocator<U>& a) throw() 59 : data_(a.data_) {++count;} throw()60 ~test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;} address(reference x)61 pointer address(reference x) const {return &x;} address(const_reference x)62 const_pointer address(const_reference x) const {return &x;} 63 pointer allocate(size_type n, const void* = 0) 64 { 65 assert(data_ >= 0); 66 if (time_to_throw >= throw_after) { 67 #ifndef _LIBCPP_NO_EXCEPTIONS 68 throw std::bad_alloc(); 69 #else 70 std::terminate(); 71 #endif 72 } 73 ++time_to_throw; 74 ++alloc_count; 75 return (pointer)std::malloc(n * sizeof(T)); 76 } deallocate(pointer p,size_type n)77 void deallocate(pointer p, size_type n) 78 {assert(data_ >= 0); --alloc_count; std::free(p);} max_size()79 size_type max_size() const throw() 80 {return UINT_MAX / sizeof(T);} construct(pointer p,const T & val)81 void construct(pointer p, const T& val) 82 {::new(p) T(val);} 83 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES construct(pointer p,T && val)84 void construct(pointer p, T&& val) 85 {::new(p) T(std::move(val));} 86 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES destroy(pointer p)87 void destroy(pointer p) {p->~T();} 88 89 friend bool operator==(const test_allocator& x, const test_allocator& y) 90 {return x.data_ == y.data_;} 91 friend bool operator!=(const test_allocator& x, const test_allocator& y) 92 {return !(x == y);} 93 }; 94 95 template <class T> 96 class non_default_test_allocator 97 : public test_alloc_base 98 { 99 int data_; 100 101 template <class U> friend class non_default_test_allocator; 102 public: 103 104 typedef unsigned size_type; 105 typedef int difference_type; 106 typedef T value_type; 107 typedef value_type* pointer; 108 typedef const value_type* const_pointer; 109 typedef typename std::add_lvalue_reference<value_type>::type reference; 110 typedef typename std::add_lvalue_reference<const value_type>::type const_reference; 111 112 template <class U> struct rebind {typedef non_default_test_allocator<U> other;}; 113 114 // non_default_test_allocator() throw() : data_(0) {++count;} non_default_test_allocator(int i)115 explicit non_default_test_allocator(int i) throw() : data_(i) {++count;} throw()116 non_default_test_allocator(const non_default_test_allocator& a) throw() 117 : data_(a.data_) {++count;} non_default_test_allocator(const non_default_test_allocator<U> & a)118 template <class U> non_default_test_allocator(const non_default_test_allocator<U>& a) throw() 119 : data_(a.data_) {++count;} throw()120 ~non_default_test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;} address(reference x)121 pointer address(reference x) const {return &x;} address(const_reference x)122 const_pointer address(const_reference x) const {return &x;} 123 pointer allocate(size_type n, const void* = 0) 124 { 125 assert(data_ >= 0); 126 if (time_to_throw >= throw_after) { 127 #ifndef _LIBCPP_NO_EXCEPTIONS 128 throw std::bad_alloc(); 129 #else 130 std::terminate(); 131 #endif 132 } 133 ++time_to_throw; 134 ++alloc_count; 135 return (pointer)std::malloc(n * sizeof(T)); 136 } deallocate(pointer p,size_type n)137 void deallocate(pointer p, size_type n) 138 {assert(data_ >= 0); --alloc_count; std::free(p);} max_size()139 size_type max_size() const throw() 140 {return UINT_MAX / sizeof(T);} construct(pointer p,const T & val)141 void construct(pointer p, const T& val) 142 {::new(p) T(val);} 143 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES construct(pointer p,T && val)144 void construct(pointer p, T&& val) 145 {::new(p) T(std::move(val));} 146 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES destroy(pointer p)147 void destroy(pointer p) {p->~T();} 148 149 friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y) 150 {return x.data_ == y.data_;} 151 friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y) 152 {return !(x == y);} 153 }; 154 155 template <> 156 class test_allocator<void> 157 : public test_alloc_base 158 { 159 int data_; 160 161 template <class U> friend class test_allocator; 162 public: 163 164 typedef unsigned size_type; 165 typedef int difference_type; 166 typedef void value_type; 167 typedef value_type* pointer; 168 typedef const value_type* const_pointer; 169 170 template <class U> struct rebind {typedef test_allocator<U> other;}; 171 throw()172 test_allocator() throw() : data_(-1) {} test_allocator(int i)173 explicit test_allocator(int i) throw() : data_(i) {} throw()174 test_allocator(const test_allocator& a) throw() 175 : data_(a.data_) {} test_allocator(const test_allocator<U> & a)176 template <class U> test_allocator(const test_allocator<U>& a) throw() 177 : data_(a.data_) {} throw()178 ~test_allocator() throw() {data_ = 0;} 179 180 friend bool operator==(const test_allocator& x, const test_allocator& y) 181 {return x.data_ == y.data_;} 182 friend bool operator!=(const test_allocator& x, const test_allocator& y) 183 {return !(x == y);} 184 }; 185 186 template <class T> 187 class other_allocator 188 { 189 int data_; 190 191 template <class U> friend class other_allocator; 192 193 public: 194 typedef T value_type; 195 other_allocator()196 other_allocator() : data_(-1) {} other_allocator(int i)197 explicit other_allocator(int i) : data_(i) {} other_allocator(const other_allocator<U> & a)198 template <class U> other_allocator(const other_allocator<U>& a) 199 : data_(a.data_) {} allocate(std::size_t n)200 T* allocate(std::size_t n) 201 {return (T*)std::malloc(n * sizeof(T));} deallocate(T * p,std::size_t n)202 void deallocate(T* p, std::size_t n) 203 {std::free(p);} 204 select_on_container_copy_construction()205 other_allocator select_on_container_copy_construction() const 206 {return other_allocator(-2);} 207 208 friend bool operator==(const other_allocator& x, const other_allocator& y) 209 {return x.data_ == y.data_;} 210 friend bool operator!=(const other_allocator& x, const other_allocator& y) 211 {return !(x == y);} 212 213 typedef std::true_type propagate_on_container_copy_assignment; 214 typedef std::true_type propagate_on_container_move_assignment; 215 typedef std::true_type propagate_on_container_swap; 216 217 #ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE max_size()218 std::size_t max_size() const 219 {return UINT_MAX / sizeof(T);} 220 #endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE 221 222 }; 223 224 #endif // TEST_ALLOCATOR_H 225