X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Ftestsuite%2Futil%2Ftestsuite_allocator.h;fp=libstdc%2B%2B-v3%2Ftestsuite%2Futil%2Ftestsuite_allocator.h;h=d2759f4653fa812f3a70a6cfecbd84bf95d00118;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=0000000000000000000000000000000000000000;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h new file mode 100644 index 00000000..d2759f46 --- /dev/null +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h @@ -0,0 +1,379 @@ +// -*- C++ -*- +// Testing allocator for the C++ library testsuite. +// +// Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +// Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// + +// This file provides an test instrumentation allocator that can be +// used to verify allocation functionality of standard library +// containers. 2002.11.25 smw + +#ifndef _GLIBCXX_TESTSUITE_ALLOCATOR_H +#define _GLIBCXX_TESTSUITE_ALLOCATOR_H + +#include +#include +#include +#include + +namespace +{ + bool new_called = false; + bool delete_called = false; +} + +namespace __gnu_test +{ + class tracker_allocator_counter + { + public: + typedef std::size_t size_type; + + static void* + allocate(size_type blocksize) + { + allocationCount_ += blocksize; + return ::operator new(blocksize); + } + + static void + construct() { constructCount_++; } + + static void + destroy() { destructCount_++; } + + static void + deallocate(void* p, size_type blocksize) + { + ::operator delete(p); + deallocationCount_ += blocksize; + } + + static size_type + get_allocation_count() { return allocationCount_; } + + static size_type + get_deallocation_count() { return deallocationCount_; } + + static int + get_construct_count() { return constructCount_; } + + static int + get_destruct_count() { return destructCount_; } + + static void + reset() + { + allocationCount_ = 0; + deallocationCount_ = 0; + constructCount_ = 0; + destructCount_ = 0; + } + + private: + static size_type allocationCount_; + static size_type deallocationCount_; + static int constructCount_; + static int destructCount_; + }; + + // A simple basic allocator that just forwards to the + // tracker_allocator_counter to fulfill memory requests. This class + // is templated on the target object type, but tracker isn't. + template + class tracker_allocator + { + private: + typedef tracker_allocator_counter counter_type; + + public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + template struct rebind { typedef tracker_allocator other; }; + + pointer + address(reference value) const + { return &value; } + + const_pointer + address(const_reference value) const + { return &value; } + + tracker_allocator() throw() + { } + + tracker_allocator(const tracker_allocator&) throw() + { } + + template + tracker_allocator(const tracker_allocator&) throw() + { } + + ~tracker_allocator() throw() + { } + + size_type + max_size() const throw() + { return size_type(-1) / sizeof(T); } + + pointer + allocate(size_type n, const void* = 0) + { return static_cast(counter_type::allocate(n * sizeof(T))); } + + void + construct(pointer p, const T& value) + { + ::new ((void *)p) T(value); + counter_type::construct(); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template + void + construct(pointer p, Args&&... args) + { + ::new((void *)p) T(std::forward(args)...); + counter_type::construct(); + } +#endif + + void + destroy(pointer p) + { + p->~T(); + counter_type::destroy(); + } + + void + deallocate(pointer p, size_type num) + { counter_type::deallocate(p, num * sizeof(T)); } + }; + + template + bool + operator==(const tracker_allocator&, + const tracker_allocator&) throw() + { return true; } + + template + bool + operator!=(const tracker_allocator&, + const tracker_allocator&) throw() + { return false; } + + bool + check_construct_destroy(const char* tag, int expected_c, int expected_d); + + template + bool + check_new(Alloc a = Alloc()) + { + bool test __attribute__((unused)) = true; + a.allocate(10); + test &= ( new_called == uses_global_new ); + return test; + } + + template + bool + check_delete(Alloc a = Alloc()) + { + bool test __attribute__((unused)) = true; + typename Alloc::pointer p = a.allocate(10); + a.deallocate(p, 10); + test &= ( delete_called == uses_global_delete ); + return test; + } + + template + bool + check_deallocate_null() + { + // Let's not core here... + Alloc a; + a.deallocate(NULL, 1); + a.deallocate(NULL, 10); + return true; + } + + template + bool + check_allocate_max_size() + { + Alloc a; + try + { + a.allocate(a.max_size() + 1); + } + catch(std::bad_alloc&) + { + return true; + } + catch(...) + { + throw; + } + throw; + } + + + // A simple allocator which can be constructed endowed of a given + // "personality" (an integer), queried in operator== to simulate the + // behavior of realworld "unequal" allocators (i.e., not exploiting + // the provision in 20.1.5/4, first bullet). A global unordered_map, + // filled at allocation time with (pointer, personality) pairs, is + // then consulted to enforce the requirements in Table 32 about + // deallocation vs allocator equality. Note that this allocator is + // swappable, not assignable, consistently with Option 3 of DR 431 + // (see N1599). + struct uneq_allocator_base + { + typedef std::tr1::unordered_map map_type; + + // Avoid static initialization troubles and/or bad interactions + // with tests linking testsuite_allocator.o and playing globally + // with operator new/delete. + static map_type& + get_map() + { + static map_type alloc_map; + return alloc_map; + } + }; + + template + class uneq_allocator + : private uneq_allocator_base + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef Tp* pointer; + typedef const Tp* const_pointer; + typedef Tp& reference; + typedef const Tp& const_reference; + typedef Tp value_type; + + template + struct rebind + { typedef uneq_allocator other; }; + + uneq_allocator() throw() + : personality(0) { } + + uneq_allocator(int person) throw() + : personality(person) { } + + template + uneq_allocator(const uneq_allocator& b) throw() + : personality(b.get_personality()) { } + + int get_personality() const { return personality; } + + pointer + address(reference x) const { return &x; } + + const_pointer + address(const_reference x) const { return &x; } + + pointer + allocate(size_type n, const void* = 0) + { + if (__builtin_expect(n > this->max_size(), false)) + std::__throw_bad_alloc(); + + pointer p = static_cast(::operator new(n * sizeof(Tp))); + try + { + get_map().insert(map_type::value_type(reinterpret_cast(p), + personality)); + } + catch(...) + { + ::operator delete(p); + __throw_exception_again; + } + return p; + } + + void + deallocate(pointer p, size_type) + { + assert( p ); + + map_type::iterator it = get_map().find(reinterpret_cast(p)); + assert( it != get_map().end() ); + + // Enforce requirements in Table 32 about deallocation vs + // allocator equality. + assert( it->second == personality ); + + get_map().erase(it); + ::operator delete(p); + } + + size_type + max_size() const throw() + { return size_type(-1) / sizeof(Tp); } + + void + construct(pointer p, const Tp& val) + { ::new((void *)p) Tp(val); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template + void + construct(pointer p, Args&&... args) + { ::new((void *)p) Tp(std::forward(args)...); } +#endif + + void + destroy(pointer p) { p->~Tp(); } + + private: + // Not assignable... + uneq_allocator& + operator=(const uneq_allocator&); + + // ... yet swappable! + friend inline void + swap(uneq_allocator& a, uneq_allocator& b) + { std::swap(a.personality, b.personality); } + + template + friend inline bool + operator==(const uneq_allocator& a, const uneq_allocator& b) + { return a.personality == b.personality; } + + template + friend inline bool + operator!=(const uneq_allocator& a, const uneq_allocator& b) + { return !(a == b); } + + int personality; + }; +} // namespace __gnu_test + +#endif // _GLIBCXX_TESTSUITE_ALLOCATOR_H