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 20class test_alloc_base 21{ 22protected: 23 static int time_to_throw; 24public: 25 static int throw_after; 26 static int count; 27 static int alloc_count; 28}; 29 30int test_alloc_base::count = 0; 31int test_alloc_base::time_to_throw = 0; 32int test_alloc_base::alloc_count = 0; 33int test_alloc_base::throw_after = INT_MAX; 34 35template <class T> 36class test_allocator 37 : public test_alloc_base 38{ 39 int data_; 40 41 template <class U> friend class test_allocator; 42public: 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 54 test_allocator() throw() : data_(0) {++count;} 55 explicit test_allocator(int i) throw() : data_(i) {++count;} 56 test_allocator(const test_allocator& a) throw() 57 : data_(a.data_) {++count;} 58 template <class U> test_allocator(const test_allocator<U>& a) throw() 59 : data_(a.data_) {++count;} 60 ~test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;} 61 pointer address(reference x) const {return &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 } 77 void deallocate(pointer p, size_type n) 78 {assert(data_ >= 0); --alloc_count; std::free(p);} 79 size_type max_size() const throw() 80 {return UINT_MAX / sizeof(T);} 81 void construct(pointer p, const T& val) 82 {::new(p) T(val);} 83#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 84 void construct(pointer p, T&& val) 85 {::new(p) T(std::move(val));} 86#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 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 95template <class T> 96class non_default_test_allocator 97 : public test_alloc_base 98{ 99 int data_; 100 101 template <class U> friend class non_default_test_allocator; 102public: 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;} 115 explicit non_default_test_allocator(int i) throw() : data_(i) {++count;} 116 non_default_test_allocator(const non_default_test_allocator& a) throw() 117 : data_(a.data_) {++count;} 118 template <class U> non_default_test_allocator(const non_default_test_allocator<U>& a) throw() 119 : data_(a.data_) {++count;} 120 ~non_default_test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;} 121 pointer address(reference x) const {return &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 } 137 void deallocate(pointer p, size_type n) 138 {assert(data_ >= 0); --alloc_count; std::free(p);} 139 size_type max_size() const throw() 140 {return UINT_MAX / sizeof(T);} 141 void construct(pointer p, const T& val) 142 {::new(p) T(val);} 143#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 144 void construct(pointer p, T&& val) 145 {::new(p) T(std::move(val));} 146#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 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 155template <> 156class test_allocator<void> 157 : public test_alloc_base 158{ 159 int data_; 160 161 template <class U> friend class test_allocator; 162public: 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 172 test_allocator() throw() : data_(-1) {} 173 explicit test_allocator(int i) throw() : data_(i) {} 174 test_allocator(const test_allocator& a) throw() 175 : data_(a.data_) {} 176 template <class U> test_allocator(const test_allocator<U>& a) throw() 177 : data_(a.data_) {} 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 186template <class T> 187class other_allocator 188{ 189 int data_; 190 191 template <class U> friend class other_allocator; 192 193public: 194 typedef T value_type; 195 196 other_allocator() : data_(-1) {} 197 explicit other_allocator(int i) : data_(i) {} 198 template <class U> other_allocator(const other_allocator<U>& a) 199 : data_(a.data_) {} 200 T* allocate(std::size_t n) 201 {return (T*)std::malloc(n * sizeof(T));} 202 void deallocate(T* p, std::size_t n) 203 {std::free(p);} 204 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 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