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