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 19 class test_alloc_base 20 { 21 public: 22 static int count; 23 public: 24 static int throw_after; 25 }; 26 27 int test_alloc_base::count = 0; 28 int test_alloc_base::throw_after = INT_MAX; 29 30 template <class T> 31 class test_allocator 32 : public test_alloc_base 33 { 34 int data_; 35 36 template <class U> friend class test_allocator; 37 public: 38 39 typedef unsigned size_type; 40 typedef int difference_type; 41 typedef T value_type; 42 typedef value_type* pointer; 43 typedef const value_type* const_pointer; 44 typedef typename std::add_lvalue_reference<value_type>::type reference; 45 typedef typename std::add_lvalue_reference<const value_type>::type const_reference; 46 47 template <class U> struct rebind {typedef test_allocator<U> other;}; 48 throw()49 test_allocator() throw() : data_(-1) {} test_allocator(int i)50 explicit test_allocator(int i) throw() : data_(i) {} throw()51 test_allocator(const test_allocator& a) throw() 52 : data_(a.data_) {} test_allocator(const test_allocator<U> & a)53 template <class U> test_allocator(const test_allocator<U>& a) throw() 54 : data_(a.data_) {} throw()55 ~test_allocator() throw() {data_ = 0;} address(reference x)56 pointer address(reference x) const {return &x;} address(const_reference x)57 const_pointer address(const_reference x) const {return &x;} 58 pointer allocate(size_type n, const void* = 0) 59 { 60 if (count >= throw_after) { 61 #ifndef _LIBCPP_NO_EXCEPTIONS 62 throw std::bad_alloc(); 63 #else 64 std::terminate(); 65 #endif 66 } 67 ++count; 68 return (pointer)std::malloc(n * sizeof(T)); 69 } deallocate(pointer p,size_type n)70 void deallocate(pointer p, size_type n) 71 {--count; std::free(p);} max_size()72 size_type max_size() const throw() 73 {return UINT_MAX / sizeof(T);} construct(pointer p,const T & val)74 void construct(pointer p, const T& val) 75 {::new(p) T(val);} 76 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES construct(pointer p,T && val)77 void construct(pointer p, T&& val) 78 {::new(p) T(std::move(val));} 79 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES destroy(pointer p)80 void destroy(pointer p) {p->~T();} 81 82 friend bool operator==(const test_allocator& x, const test_allocator& y) 83 {return x.data_ == y.data_;} 84 friend bool operator!=(const test_allocator& x, const test_allocator& y) 85 {return !(x == y);} 86 }; 87 88 template <> 89 class test_allocator<void> 90 : public test_alloc_base 91 { 92 int data_; 93 94 template <class U> friend class test_allocator; 95 public: 96 97 typedef unsigned size_type; 98 typedef int difference_type; 99 typedef void value_type; 100 typedef value_type* pointer; 101 typedef const value_type* const_pointer; 102 103 template <class U> struct rebind {typedef test_allocator<U> other;}; 104 throw()105 test_allocator() throw() : data_(-1) {} test_allocator(int i)106 explicit test_allocator(int i) throw() : data_(i) {} throw()107 test_allocator(const test_allocator& a) throw() 108 : data_(a.data_) {} test_allocator(const test_allocator<U> & a)109 template <class U> test_allocator(const test_allocator<U>& a) throw() 110 : data_(a.data_) {} throw()111 ~test_allocator() throw() {data_ = 0;} 112 113 friend bool operator==(const test_allocator& x, const test_allocator& y) 114 {return x.data_ == y.data_;} 115 friend bool operator!=(const test_allocator& x, const test_allocator& y) 116 {return !(x == y);} 117 }; 118 119 template <class T> 120 class other_allocator 121 { 122 int data_; 123 124 template <class U> friend class other_allocator; 125 126 public: 127 typedef T value_type; 128 other_allocator()129 other_allocator() : data_(-1) {} other_allocator(int i)130 explicit other_allocator(int i) : data_(i) {} other_allocator(const other_allocator<U> & a)131 template <class U> other_allocator(const other_allocator<U>& a) 132 : data_(a.data_) {} allocate(std::size_t n)133 T* allocate(std::size_t n) 134 {return (T*)std::malloc(n * sizeof(T));} deallocate(T * p,std::size_t n)135 void deallocate(T* p, std::size_t n) 136 {std::free(p);} 137 select_on_container_copy_construction()138 other_allocator select_on_container_copy_construction() const 139 {return other_allocator(-2);} 140 141 friend bool operator==(const other_allocator& x, const other_allocator& y) 142 {return x.data_ == y.data_;} 143 friend bool operator!=(const other_allocator& x, const other_allocator& y) 144 {return !(x == y);} 145 146 typedef std::true_type propagate_on_container_copy_assignment; 147 typedef std::true_type propagate_on_container_move_assignment; 148 typedef std::true_type propagate_on_container_swap; 149 150 #ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE max_size()151 std::size_t max_size() const 152 {return UINT_MAX / sizeof(T);} 153 #endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE 154 155 }; 156 157 #endif // TEST_ALLOCATOR_H 158