2 // Testing allocator for the C++ library testsuite.
4 // Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
5 // Free Software Foundation, Inc.
7 // This file is part of the GNU ISO C++ Library. This library is free
8 // software; you can redistribute it and/or modify it under the
9 // terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 3, or (at your option)
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License along
19 // with this library; see the file COPYING3. If not see
20 // <http://www.gnu.org/licenses/>.
23 // This file provides an test instrumentation allocator that can be
24 // used to verify allocation functionality of standard library
25 // containers. 2002.11.25 smw
27 #ifndef _GLIBCXX_TESTSUITE_ALLOCATOR_H
28 #define _GLIBCXX_TESTSUITE_ALLOCATOR_H
30 #include <tr1/unordered_map>
31 #include <bits/move.h>
32 #include <testsuite_hooks.h>
36 class tracker_allocator_counter
39 typedef std::size_t size_type;
42 allocate(size_type blocksize)
44 void* p = ::operator new(blocksize);
45 allocationCount_ += blocksize;
50 construct() { constructCount_++; }
53 destroy() { destructCount_++; }
56 deallocate(void* p, size_type blocksize)
59 deallocationCount_ += blocksize;
63 get_allocation_count() { return allocationCount_; }
66 get_deallocation_count() { return deallocationCount_; }
69 get_construct_count() { return constructCount_; }
72 get_destruct_count() { return destructCount_; }
78 deallocationCount_ = 0;
84 static size_type allocationCount_;
85 static size_type deallocationCount_;
86 static int constructCount_;
87 static int destructCount_;
90 // A simple basic allocator that just forwards to the
91 // tracker_allocator_counter to fulfill memory requests. This class
92 // is templated on the target object type, but tracker isn't.
94 class tracker_allocator
97 typedef tracker_allocator_counter counter_type;
100 typedef T value_type;
102 typedef const T* const_pointer;
103 typedef T& reference;
104 typedef const T& const_reference;
105 typedef std::size_t size_type;
106 typedef std::ptrdiff_t difference_type;
108 template<class U> struct rebind { typedef tracker_allocator<U> other; };
111 address(reference value) const _GLIBCXX_NOEXCEPT
112 { return std::__addressof(value); }
115 address(const_reference value) const _GLIBCXX_NOEXCEPT
116 { return std::__addressof(value); }
118 tracker_allocator() _GLIBCXX_USE_NOEXCEPT
121 tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT
125 tracker_allocator(const tracker_allocator<U>&) _GLIBCXX_USE_NOEXCEPT
128 ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT
132 max_size() const _GLIBCXX_USE_NOEXCEPT
133 { return size_type(-1) / sizeof(T); }
136 allocate(size_type n, const void* = 0)
137 { return static_cast<pointer>(counter_type::allocate(n * sizeof(T))); }
139 #ifdef __GXX_EXPERIMENTAL_CXX0X__
140 template<typename U, typename... Args>
142 construct(U* p, Args&&... args)
144 ::new((void *)p) U(std::forward<Args>(args)...);
145 counter_type::construct();
153 counter_type::destroy();
157 construct(pointer p, const T& value)
159 ::new ((void *)p) T(value);
160 counter_type::construct();
167 counter_type::destroy();
172 deallocate(pointer p, size_type num)
173 { counter_type::deallocate(p, num * sizeof(T)); }
176 template<class T1, class T2>
178 operator==(const tracker_allocator<T1>&,
179 const tracker_allocator<T2>&) throw()
182 template<class T1, class T2>
184 operator!=(const tracker_allocator<T1>&,
185 const tracker_allocator<T2>&) throw()
189 check_construct_destroy(const char* tag, int expected_c, int expected_d);
191 template<typename Alloc>
193 check_deallocate_null()
195 // Let's not core here...
202 template<typename Alloc>
204 check_allocate_max_size()
209 a.allocate(a.max_size() + 1);
211 catch(std::bad_alloc&)
223 // A simple allocator which can be constructed endowed of a given
224 // "personality" (an integer), queried in operator== to simulate the
225 // behavior of realworld "unequal" allocators (i.e., not exploiting
226 // the provision in 20.1.5/4, first bullet). A global unordered_map,
227 // filled at allocation time with (pointer, personality) pairs, is
228 // then consulted to enforce the requirements in Table 32 about
229 // deallocation vs allocator equality. Note that this allocator is
230 // swappable, not assignable, consistently with Option 3 of DR 431
232 struct uneq_allocator_base
234 typedef std::tr1::unordered_map<void*, int> map_type;
236 // Avoid static initialization troubles and/or bad interactions
237 // with tests linking testsuite_allocator.o and playing globally
238 // with operator new/delete.
242 static map_type alloc_map;
247 template<typename Tp>
249 : private uneq_allocator_base
252 typedef std::size_t size_type;
253 typedef std::ptrdiff_t difference_type;
255 typedef const Tp* const_pointer;
256 typedef Tp& reference;
257 typedef const Tp& const_reference;
258 typedef Tp value_type;
260 #ifdef __GXX_EXPERIMENTAL_CXX0X__
261 typedef std::true_type propagate_on_container_swap;
264 template<typename Tp1>
266 { typedef uneq_allocator<Tp1> other; };
268 uneq_allocator() _GLIBCXX_USE_NOEXCEPT
271 uneq_allocator(int person) _GLIBCXX_USE_NOEXCEPT
272 : personality(person) { }
274 template<typename Tp1>
275 uneq_allocator(const uneq_allocator<Tp1>& b) _GLIBCXX_USE_NOEXCEPT
276 : personality(b.get_personality()) { }
278 ~uneq_allocator() _GLIBCXX_USE_NOEXCEPT
281 int get_personality() const { return personality; }
284 address(reference x) const _GLIBCXX_NOEXCEPT
285 { return std::__addressof(x); }
288 address(const_reference x) const _GLIBCXX_NOEXCEPT
289 { return std::__addressof(x); }
292 allocate(size_type n, const void* = 0)
294 if (__builtin_expect(n > this->max_size(), false))
295 std::__throw_bad_alloc();
297 pointer p = static_cast<Tp*>(::operator new(n * sizeof(Tp)));
300 get_map().insert(map_type::value_type(reinterpret_cast<void*>(p),
305 ::operator delete(p);
306 __throw_exception_again;
312 deallocate(pointer p, size_type)
314 bool test __attribute__((unused)) = true;
318 map_type::iterator it = get_map().find(reinterpret_cast<void*>(p));
319 VERIFY( it != get_map().end() );
321 // Enforce requirements in Table 32 about deallocation vs
322 // allocator equality.
323 VERIFY( it->second == personality );
326 ::operator delete(p);
330 max_size() const _GLIBCXX_USE_NOEXCEPT
331 { return size_type(-1) / sizeof(Tp); }
333 #ifdef __GXX_EXPERIMENTAL_CXX0X__
334 template<typename U, typename... Args>
336 construct(U* p, Args&&... args)
337 { ::new((void *)p) U(std::forward<Args>(args)...); }
341 destroy(U* p) { p->~U(); }
343 // Not copy assignable...
345 operator=(const uneq_allocator&) = delete;
348 construct(pointer p, const Tp& val)
349 { ::new((void *)p) Tp(val); }
352 destroy(pointer p) { p->~Tp(); }
357 operator=(const uneq_allocator&);
362 // ... yet swappable!
364 swap(uneq_allocator& a, uneq_allocator& b)
365 { std::swap(a.personality, b.personality); }
367 template<typename Tp1>
369 operator==(const uneq_allocator& a, const uneq_allocator<Tp1>& b)
370 { return a.personality == b.personality; }
372 template<typename Tp1>
374 operator!=(const uneq_allocator& a, const uneq_allocator<Tp1>& b)
375 { return !(a == b); }
380 #ifdef __GXX_EXPERIMENTAL_CXX0X__
381 // An uneq_allocator which can be used to test allocator propagation.
382 template<typename Tp, bool Propagate>
383 class propagating_allocator : public uneq_allocator<Tp>
385 typedef uneq_allocator<Tp> base_alloc;
386 base_alloc& base() { return *this; }
387 const base_alloc& base() const { return *this; }
388 void swap_base(base_alloc& b) { swap(b, this->base()); }
390 typedef std::integral_constant<bool, Propagate> trait_type;
393 // default allocator_traits::rebind_alloc would select
394 // uneq_allocator::rebind so we must define rebind here
395 template<typename Up>
396 struct rebind { typedef propagating_allocator<Up, Propagate> other; };
398 propagating_allocator(int i) noexcept
402 template<typename Up>
403 propagating_allocator(const propagating_allocator<Up, Propagate>& a)
408 propagating_allocator() noexcept = default;
410 propagating_allocator(const propagating_allocator&) noexcept = default;
413 propagating_allocator&
414 operator=(const propagating_allocator<Tp, P2>& a) noexcept
416 static_assert(P2, "assigning propagating_allocator<T, true>");
417 propagating_allocator(a).swap_base(*this);
421 // postcondition: a.get_personality() == 0
422 propagating_allocator(propagating_allocator&& a) noexcept
426 // postcondition: a.get_personality() == 0
427 propagating_allocator&
428 operator=(propagating_allocator&& a) noexcept
430 propagating_allocator(std::move(a)).swap_base(*this);
434 typedef trait_type propagate_on_container_copy_assignment;
435 typedef trait_type propagate_on_container_move_assignment;
436 typedef trait_type propagate_on_container_swap;
438 propagating_allocator select_on_container_copy_construction() const
439 { return Propagate ? *this : propagating_allocator(); }
442 // Class template supporting the minimal interface that satisfies the
443 // Allocator requirements, from example in [allocator.requirements]
445 struct SimpleAllocator
447 typedef Tp value_type;
449 SimpleAllocator() { }
452 SimpleAllocator(const SimpleAllocator<T>& other) { }
454 Tp *allocate(std::size_t n)
455 { return std::allocator<Tp>().allocate(n); }
457 void deallocate(Tp *p, std::size_t n)
458 { std::allocator<Tp>().deallocate(p, n); }
461 template <class T, class U>
462 bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&)
464 template <class T, class U>
465 bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&)
470 template<typename Tp>
471 struct ExplicitConsAlloc : std::allocator<Tp>
473 ExplicitConsAlloc() { }
475 template<typename Up>
477 ExplicitConsAlloc(const ExplicitConsAlloc<Up>&) { }
479 template<typename Up>
481 { typedef ExplicitConsAlloc<Up> other; };
484 } // namespace __gnu_test
486 #endif // _GLIBCXX_TESTSUITE_ALLOCATOR_H