// -*- C++ -*- // Testing allocator for the C++ library testsuite. // // Copyright (C) 2002, 2003, 2004 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 2, 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 COPYING. If not, write to the Free // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, // USA. // // As a special exception, you may use this file as part of a free software // library without restriction. Specifically, if other files instantiate // templates or use macros or inline functions from this file, or you compile // this file and link it with other files to produce an executable, this // file does not by itself cause the resulting executable to be covered by // the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. // 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 namespace { bool new_called = false; bool delete_called = false; std::size_t requested = 0; }; namespace __gnu_test { class allocation_tracker { public: typedef std::size_t size_type; static void* allocate(size_type blocksize) { allocationTotal_ += blocksize; return ::operator new(blocksize); } static void construct() { constructCount_++; } static void destroy() { destructCount_++; } static void deallocate(void* p, size_type blocksize) { ::operator delete(p); deallocationTotal_ += blocksize; } static size_type allocationTotal() { return allocationTotal_; } static size_type deallocationTotal() { return deallocationTotal_; } static int constructCount() { return constructCount_; } static int destructCount() { return destructCount_; } static void resetCounts() { allocationTotal_ = 0; deallocationTotal_ = 0; constructCount_ = 0; destructCount_ = 0; } private: static size_type allocationTotal_; static size_type deallocationTotal_; static int constructCount_; static int destructCount_; }; // A simple basic allocator that just forwards to the // allocation_tracker to fulfill memory requests. This class is // templated on the target object type, but tracker isn't. template class tracker_alloc { 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_alloc other; }; pointer address(reference value) const { return &value; } const_pointer address(const_reference value) const { return &value; } tracker_alloc() throw() { } tracker_alloc(const tracker_alloc&) throw() { } template tracker_alloc(const tracker_alloc&) throw() { } ~tracker_alloc() throw() { } size_type max_size() const throw() { return std::numeric_limits::max() / sizeof(T); } pointer allocate(size_type n, const void* = 0) { return static_cast(allocation_tracker::allocate(n * sizeof(T))); } void construct(pointer p, const T& value) { new (p) T(value); allocation_tracker::construct(); } void destroy(pointer p) { p->~T(); allocation_tracker::destroy(); } void deallocate(pointer p, size_type num) { allocation_tracker::deallocate(p, num * sizeof(T)); } }; template bool operator==(const tracker_alloc&, const tracker_alloc&) throw() { return true; } template bool operator!=(const tracker_alloc&, const tracker_alloc&) 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; typename Alloc::pointer p = a.allocate(10); if (uses_global_new_and_delete) test &= ( requested >= (10 * 15 * sizeof(long)) ); test &= ( new_called == uses_global_new_and_delete ); a.deallocate(p, 10); test &= ( delete_called == uses_global_new_and_delete ); return test; } template bool check_deallocate_null() { // Let's not core here... Alloc a; a.deallocate(NULL, 1); a.deallocate(NULL, 10); } template bool check_allocate_max_size() { Alloc a; try { a.allocate(a.max_size() + 1); } catch(std::bad_alloc&) { return true; } catch(...) { throw; } throw; } }; // namespace __gnu_test #endif // _GLIBCXX_TESTSUITE_ALLOCATOR_H