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 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 95 template <> 96 class test_allocator<void> 97 : public test_alloc_base 98 { 99 int data_; 100 101 template <class U> friend class test_allocator; 102 public: 103 104 typedef unsigned size_type; 105 typedef int difference_type; 106 typedef void value_type; 107 typedef value_type* pointer; 108 typedef const value_type* const_pointer; 109 110 template <class U> struct rebind {typedef test_allocator<U> other;}; 111 112 test_allocator() throw() : data_(-1) {} 113 explicit test_allocator(int i) throw() : data_(i) {} 114 test_allocator(const test_allocator& a) throw() 115 : data_(a.data_) {} 116 template <class U> test_allocator(const test_allocator<U>& a) throw() 117 : data_(a.data_) {} 118 ~test_allocator() throw() {data_ = 0;} 119 120 friend bool operator==(const test_allocator& x, const test_allocator& y) 121 {return x.data_ == y.data_;} 122 friend bool operator!=(const test_allocator& x, const test_allocator& y) 123 {return !(x == y);} 124 }; 125 126 template <class T> 127 class other_allocator 128 { 129 int data_; 130 131 template <class U> friend class other_allocator; 132 133 public: 134 typedef T value_type; 135 136 other_allocator() : data_(-1) {} 137 explicit other_allocator(int i) : data_(i) {} 138 template <class U> other_allocator(const other_allocator<U>& a) 139 : data_(a.data_) {} 140 T* allocate(std::size_t n) 141 {return (T*)std::malloc(n * sizeof(T));} 142 void deallocate(T* p, std::size_t n) 143 {std::free(p);} 144 145 other_allocator select_on_container_copy_construction() const 146 {return other_allocator(-2);} 147 148 friend bool operator==(const other_allocator& x, const other_allocator& y) 149 {return x.data_ == y.data_;} 150 friend bool operator!=(const other_allocator& x, const other_allocator& y) 151 {return !(x == y);} 152 153 typedef std::true_type propagate_on_container_copy_assignment; 154 typedef std::true_type propagate_on_container_move_assignment; 155 typedef std::true_type propagate_on_container_swap; 156 157 #ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE 158 std::size_t max_size() const 159 {return UINT_MAX / sizeof(T);} 160 #endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE 161 162 }; 163 164 #endif // TEST_ALLOCATOR_H 165