blob: 7ce60025f688647741cff0ca5efacea91e8c0276 [file] [log] [blame]
Marshall Clow354d39c2014-01-16 16:58:45 +00001//===----------------------------------------------------------------------===//
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
Howard Hinnant3e519522010-05-11 19:42:16 +000010#ifndef TEST_ALLOCATOR_H
11#define TEST_ALLOCATOR_H
12
Howard Hinnant3e519522010-05-11 19:42:16 +000013#include <type_traits>
Howard Hinnant3e519522010-05-11 19:42:16 +000014#include <new>
Eric Fiselier653179b2016-10-08 00:57:56 +000015#include <memory>
16#include <cstddef>
17#include <cstdlib>
Howard Hinnant3e519522010-05-11 19:42:16 +000018#include <climits>
Marshall Clowc3deeb52013-12-03 00:18:10 +000019#include <cassert>
Howard Hinnant3e519522010-05-11 19:42:16 +000020
Marshall Clowcbf166a2015-06-03 19:56:43 +000021#include "test_macros.h"
22
Eric Fiselier55b31b4e2016-11-23 01:18:56 +000023template <class Alloc>
24inline size_t alloc_max_size(Alloc const &a) {
25 typedef std::allocator_traits<Alloc> AT;
26 return AT::max_size(a);
27}
28
Howard Hinnant3e519522010-05-11 19:42:16 +000029class test_alloc_base
30{
31protected:
Marshall Clowc3deeb52013-12-03 00:18:10 +000032 static int time_to_throw;
Howard Hinnant3e519522010-05-11 19:42:16 +000033public:
34 static int throw_after;
Marshall Clowc3deeb52013-12-03 00:18:10 +000035 static int count;
36 static int alloc_count;
Howard Hinnant3e519522010-05-11 19:42:16 +000037};
38
39int test_alloc_base::count = 0;
Marshall Clowc3deeb52013-12-03 00:18:10 +000040int test_alloc_base::time_to_throw = 0;
41int test_alloc_base::alloc_count = 0;
Howard Hinnant3e519522010-05-11 19:42:16 +000042int test_alloc_base::throw_after = INT_MAX;
43
44template <class T>
45class test_allocator
46 : public test_alloc_base
47{
48 int data_;
49
50 template <class U> friend class test_allocator;
51public:
52
53 typedef unsigned size_type;
54 typedef int difference_type;
55 typedef T value_type;
56 typedef value_type* pointer;
57 typedef const value_type* const_pointer;
58 typedef typename std::add_lvalue_reference<value_type>::type reference;
59 typedef typename std::add_lvalue_reference<const value_type>::type const_reference;
60
61 template <class U> struct rebind {typedef test_allocator<U> other;};
62
Marshall Clowc3deeb52013-12-03 00:18:10 +000063 test_allocator() throw() : data_(0) {++count;}
64 explicit test_allocator(int i) throw() : data_(i) {++count;}
Howard Hinnant3e519522010-05-11 19:42:16 +000065 test_allocator(const test_allocator& a) throw()
Marshall Clowc3deeb52013-12-03 00:18:10 +000066 : data_(a.data_) {++count;}
Howard Hinnant3e519522010-05-11 19:42:16 +000067 template <class U> test_allocator(const test_allocator<U>& a) throw()
Marshall Clowc3deeb52013-12-03 00:18:10 +000068 : data_(a.data_) {++count;}
69 ~test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;}
Howard Hinnant3e519522010-05-11 19:42:16 +000070 pointer address(reference x) const {return &x;}
71 const_pointer address(const_reference x) const {return &x;}
72 pointer allocate(size_type n, const void* = 0)
73 {
Marshall Clowc3deeb52013-12-03 00:18:10 +000074 assert(data_ >= 0);
75 if (time_to_throw >= throw_after) {
Eric Fiselier54613ab2016-09-25 03:34:28 +000076#ifndef TEST_HAS_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +000077 throw std::bad_alloc();
Howard Hinnant65a87cc2013-03-23 17:27:16 +000078#else
79 std::terminate();
80#endif
81 }
Marshall Clowc3deeb52013-12-03 00:18:10 +000082 ++time_to_throw;
83 ++alloc_count;
Eric Fiselierb11df182015-06-14 23:30:09 +000084 return (pointer)::operator new(n * sizeof(T));
Howard Hinnant3e519522010-05-11 19:42:16 +000085 }
Eric Fiselier7626f772016-04-28 03:17:56 +000086 void deallocate(pointer p, size_type)
Eric Fiselierb11df182015-06-14 23:30:09 +000087 {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p);}
Howard Hinnant3e519522010-05-11 19:42:16 +000088 size_type max_size() const throw()
89 {return UINT_MAX / sizeof(T);}
Eric Fiselier4fae5022016-06-15 01:53:32 +000090#if TEST_STD_VER < 11
Howard Hinnant3e519522010-05-11 19:42:16 +000091 void construct(pointer p, const T& val)
Eric Fiselier4fae5022016-06-15 01:53:32 +000092 {::new(static_cast<void*>(p)) T(val);}
93#else
94 template <class U> void construct(pointer p, U&& val)
95 {::new(static_cast<void*>(p)) T(std::forward<U>(val));}
96#endif
Eric Fiselier408d6eb2016-06-22 01:02:08 +000097 void destroy(pointer p)
Eric Fiselier89c91912016-10-07 18:51:33 +000098 {p->~T();}
Howard Hinnant3e519522010-05-11 19:42:16 +000099 friend bool operator==(const test_allocator& x, const test_allocator& y)
100 {return x.data_ == y.data_;}
101 friend bool operator!=(const test_allocator& x, const test_allocator& y)
102 {return !(x == y);}
103};
104
Marshall Clow5f7c2db2014-04-18 17:23:36 +0000105template <class T>
106class non_default_test_allocator
107 : public test_alloc_base
108{
109 int data_;
110
111 template <class U> friend class non_default_test_allocator;
112public:
113
114 typedef unsigned size_type;
115 typedef int difference_type;
116 typedef T value_type;
117 typedef value_type* pointer;
118 typedef const value_type* const_pointer;
119 typedef typename std::add_lvalue_reference<value_type>::type reference;
120 typedef typename std::add_lvalue_reference<const value_type>::type const_reference;
121
122 template <class U> struct rebind {typedef non_default_test_allocator<U> other;};
123
124// non_default_test_allocator() throw() : data_(0) {++count;}
125 explicit non_default_test_allocator(int i) throw() : data_(i) {++count;}
126 non_default_test_allocator(const non_default_test_allocator& a) throw()
127 : data_(a.data_) {++count;}
128 template <class U> non_default_test_allocator(const non_default_test_allocator<U>& a) throw()
129 : data_(a.data_) {++count;}
130 ~non_default_test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;}
131 pointer address(reference x) const {return &x;}
132 const_pointer address(const_reference x) const {return &x;}
133 pointer allocate(size_type n, const void* = 0)
134 {
135 assert(data_ >= 0);
136 if (time_to_throw >= throw_after) {
Eric Fiselier54613ab2016-09-25 03:34:28 +0000137#ifndef TEST_HAS_NO_EXCEPTIONS
Marshall Clow5f7c2db2014-04-18 17:23:36 +0000138 throw std::bad_alloc();
139#else
140 std::terminate();
141#endif
142 }
143 ++time_to_throw;
144 ++alloc_count;
Eric Fiselierb11df182015-06-14 23:30:09 +0000145 return (pointer)::operator new (n * sizeof(T));
Marshall Clow5f7c2db2014-04-18 17:23:36 +0000146 }
Eric Fiselier7626f772016-04-28 03:17:56 +0000147 void deallocate(pointer p, size_type)
Eric Fiselierb11df182015-06-14 23:30:09 +0000148 {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p); }
Marshall Clow5f7c2db2014-04-18 17:23:36 +0000149 size_type max_size() const throw()
150 {return UINT_MAX / sizeof(T);}
Eric Fiselier4fae5022016-06-15 01:53:32 +0000151#if TEST_STD_VER < 11
Marshall Clow5f7c2db2014-04-18 17:23:36 +0000152 void construct(pointer p, const T& val)
Eric Fiselier4fae5022016-06-15 01:53:32 +0000153 {::new(static_cast<void*>(p)) T(val);}
154#else
155 template <class U> void construct(pointer p, U&& val)
156 {::new(static_cast<void*>(p)) T(std::forward<U>(val));}
157#endif
Marshall Clow5f7c2db2014-04-18 17:23:36 +0000158 void destroy(pointer p) {p->~T();}
159
160 friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y)
161 {return x.data_ == y.data_;}
162 friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y)
163 {return !(x == y);}
164};
165
Marshall Clowc3deeb52013-12-03 00:18:10 +0000166template <>
167class test_allocator<void>
168 : public test_alloc_base
169{
170 int data_;
171
172 template <class U> friend class test_allocator;
173public:
174
175 typedef unsigned size_type;
176 typedef int difference_type;
177 typedef void value_type;
178 typedef value_type* pointer;
179 typedef const value_type* const_pointer;
180
181 template <class U> struct rebind {typedef test_allocator<U> other;};
182
Eric Fiselierfc8e8c02015-08-28 05:00:25 +0000183 test_allocator() throw() : data_(0) {}
Marshall Clowc3deeb52013-12-03 00:18:10 +0000184 explicit test_allocator(int i) throw() : data_(i) {}
185 test_allocator(const test_allocator& a) throw()
186 : data_(a.data_) {}
187 template <class U> test_allocator(const test_allocator<U>& a) throw()
188 : data_(a.data_) {}
Eric Fiselierfc8e8c02015-08-28 05:00:25 +0000189 ~test_allocator() throw() {data_ = -1;}
Marshall Clowc3deeb52013-12-03 00:18:10 +0000190
191 friend bool operator==(const test_allocator& x, const test_allocator& y)
192 {return x.data_ == y.data_;}
193 friend bool operator!=(const test_allocator& x, const test_allocator& y)
194 {return !(x == y);}
195};
196
Howard Hinnant3e519522010-05-11 19:42:16 +0000197template <class T>
198class other_allocator
199{
200 int data_;
201
202 template <class U> friend class other_allocator;
203
204public:
205 typedef T value_type;
206
207 other_allocator() : data_(-1) {}
208 explicit other_allocator(int i) : data_(i) {}
209 template <class U> other_allocator(const other_allocator<U>& a)
210 : data_(a.data_) {}
211 T* allocate(std::size_t n)
Eric Fiselierb11df182015-06-14 23:30:09 +0000212 {return (T*)::operator new(n * sizeof(T));}
Eric Fiselier7626f772016-04-28 03:17:56 +0000213 void deallocate(T* p, std::size_t)
Eric Fiselierb11df182015-06-14 23:30:09 +0000214 {::operator delete((void*)p);}
Howard Hinnant3e519522010-05-11 19:42:16 +0000215
216 other_allocator select_on_container_copy_construction() const
217 {return other_allocator(-2);}
218
219 friend bool operator==(const other_allocator& x, const other_allocator& y)
220 {return x.data_ == y.data_;}
221 friend bool operator!=(const other_allocator& x, const other_allocator& y)
222 {return !(x == y);}
223
224 typedef std::true_type propagate_on_container_copy_assignment;
225 typedef std::true_type propagate_on_container_move_assignment;
226 typedef std::true_type propagate_on_container_swap;
227
Eric Fiselier54613ab2016-09-25 03:34:28 +0000228#if TEST_STD_VER < 11
Howard Hinnant3e519522010-05-11 19:42:16 +0000229 std::size_t max_size() const
230 {return UINT_MAX / sizeof(T);}
Eric Fiselier54613ab2016-09-25 03:34:28 +0000231#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000232
233};
234
Marshall Clowdc3eb832016-07-11 21:38:08 +0000235#if TEST_STD_VER >= 11
236
237struct Ctor_Tag {};
238
239template <typename T> class TaggingAllocator;
240
241struct Tag_X {
242 // All constructors must be passed the Tag type.
243
244 // DefaultInsertable into vector<X, TaggingAllocator<X>>,
245 Tag_X(Ctor_Tag) {}
246 // CopyInsertable into vector<X, TaggingAllocator<X>>,
247 Tag_X(Ctor_Tag, const Tag_X&) {}
248 // MoveInsertable into vector<X, TaggingAllocator<X>>, and
249 Tag_X(Ctor_Tag, Tag_X&&) {}
250
251 // EmplaceConstructible into vector<X, TaggingAllocator<X>> from args.
252 template<typename... Args>
253 Tag_X(Ctor_Tag, Args&&...) { }
254
255 // not DefaultConstructible, CopyConstructible or MoveConstructible.
256 Tag_X() = delete;
257 Tag_X(const Tag_X&) = delete;
258 Tag_X(Tag_X&&) = delete;
259
260 // CopyAssignable.
261 Tag_X& operator=(const Tag_X&) { return *this; }
262
263 // MoveAssignable.
264 Tag_X& operator=(Tag_X&&) { return *this; }
265
266private:
267 // Not Destructible.
268 ~Tag_X() { }
269
270 // Erasable from vector<X, TaggingAllocator<X>>.
271 friend class TaggingAllocator<Tag_X>;
272};
273
274
275template<typename T>
276class TaggingAllocator {
277public:
278 using value_type = T;
279 TaggingAllocator() = default;
280
281 template<typename U>
282 TaggingAllocator(const TaggingAllocator<U>&) { }
283
284 T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
285
286 void deallocate(T* p, std::size_t n) { std::allocator<T>{}.deallocate(p, n); }
287
288 template<typename... Args>
289 void construct(Tag_X* p, Args&&... args)
290 { ::new((void*)p) Tag_X(Ctor_Tag{}, std::forward<Args>(args)...); }
291
292 template<typename U, typename... Args>
293 void construct(U* p, Args&&... args)
294 { ::new((void*)p) U(std::forward<Args>(args)...); }
295
296 template<typename U, typename... Args>
297 void destroy(U* p)
Eric Fiselier89c91912016-10-07 18:51:33 +0000298 { p->~U(); }
Marshall Clowdc3eb832016-07-11 21:38:08 +0000299};
300
301template<typename T, typename U>
302bool
303operator==(const TaggingAllocator<T>&, const TaggingAllocator<U>&)
304{ return true; }
305
306template<typename T, typename U>
307bool
308operator!=(const TaggingAllocator<T>&, const TaggingAllocator<U>&)
309{ return false; }
310#endif
311
Eric Fiselier69a4f662016-10-08 00:56:22 +0000312template <std::size_t MaxAllocs>
313struct limited_alloc_handle {
314 std::size_t outstanding_;
315 void* last_alloc_;
316
317 limited_alloc_handle() : outstanding_(0), last_alloc_(nullptr) {}
318
319 template <class T>
320 T *allocate(std::size_t N) {
321 if (N + outstanding_ > MaxAllocs)
322 TEST_THROW(std::bad_alloc());
323 last_alloc_ = ::operator new(N*sizeof(T));
324 outstanding_ += N;
325 return static_cast<T*>(last_alloc_);
326 }
327
328 void deallocate(void* ptr, std::size_t N) {
329 if (ptr == last_alloc_) {
330 last_alloc_ = nullptr;
331 assert(outstanding_ >= N);
332 outstanding_ -= N;
333 }
334 ::operator delete(ptr);
335 }
336};
337
338template <class T, std::size_t N>
339class limited_allocator
340{
Eric Fiseliera9fcc1d2016-10-12 11:35:37 +0000341 template <class U, std::size_t UN> friend class limited_allocator;
Eric Fiselier69a4f662016-10-08 00:56:22 +0000342 typedef limited_alloc_handle<N> BuffT;
343 std::shared_ptr<BuffT> handle_;
344public:
345 typedef T value_type;
346 typedef value_type* pointer;
347 typedef const value_type* const_pointer;
348 typedef value_type& reference;
349 typedef const value_type& const_reference;
350 typedef std::size_t size_type;
351 typedef std::ptrdiff_t difference_type;
352
353 template <class U> struct rebind { typedef limited_allocator<U, N> other; };
354
355 limited_allocator() : handle_(new BuffT) {}
356
357 limited_allocator(limited_allocator const& other) : handle_(other.handle_) {}
358
359 template <class U>
360 explicit limited_allocator(limited_allocator<U, N> const& other)
361 : handle_(other.handle_) {}
362
363private:
364 limited_allocator& operator=(const limited_allocator&);// = delete;
365
366public:
367 pointer allocate(size_type n) { return handle_->template allocate<T>(n); }
368 void deallocate(pointer p, size_type n) { handle_->deallocate(p, n); }
369 size_type max_size() const {return N;}
370
371 BuffT* getHandle() const { return handle_.get(); }
372};
373
374template <class T, class U, std::size_t N>
375inline bool operator==(limited_allocator<T, N> const& LHS,
376 limited_allocator<U, N> const& RHS) {
377 return LHS.getHandle() == RHS.getHandle();
378}
379
380template <class T, class U, std::size_t N>
381inline bool operator!=(limited_allocator<T, N> const& LHS,
382 limited_allocator<U, N> const& RHS) {
383 return !(LHS == RHS);
384}
385
Marshall Clowdc3eb832016-07-11 21:38:08 +0000386
Howard Hinnant8f2f7e72010-08-22 00:15:28 +0000387#endif // TEST_ALLOCATOR_H