Files
boost_unordered/test/helpers/memory.hpp
Daniel James 4f27a146ef Merge from trunk. Fix some inspect errors, try to avoid instantiating the
equality operators when not required, and some bookkeeping.

................
  r42539 | danieljames | 2008-01-06 17:48:11 +0000 (Sun, 06 Jan 2008) | 2 lines
  
  Add the unordered library to the maintainers list.
................
  r46579 | danieljames | 2008-06-21 16:32:11 +0100 (Sat, 21 Jun 2008) | 10 lines
  
  Define unordered containers' friend functions outside of the class.
  
  On some compilers, friend functions are being instantiated when the main class
  is explicitly instantiated. This is slightly problematic because the equality
  functions (which are an extension) put extra requirements on the types used. So
  I'm going to try defining the functions outside of the class, in the hope that
  they won't get instantiated. If someone wants non-member functions to be
  instantiated, I think it's reasonable to expect them to explicitly instantiate
  them, especially as compilers don't seem to be consistent about this.
................
  r46587 | danieljames | 2008-06-21 20:58:39 +0100 (Sat, 21 Jun 2008) | 8 lines
  
  Get the test to pass when pair's default constructor creates two instances of
  the member classes.
  
  With some standard libraries I was getting two copies of the object after
  creating a default pair, probably because it was creating an instance for its
  default parameter. So only test after creating the pair object - since it isn't
  our concern how many instances that creates.
................
  r46588 | danieljames | 2008-06-21 21:11:26 +0100 (Sat, 21 Jun 2008) | 1 line
  
  Markup an expected failure for unordered.
................
  r46594 | danieljames | 2008-06-21 23:02:15 +0100 (Sat, 21 Jun 2008) | 19 lines
  
  Merge inspect fixes for the unordered library.
  
  Merged revisions 46470-46592 via svnmerge from 
  https://svn.boost.org/svn/boost/branches/unordered/trunk
  
  ................
    r46589 | danieljames | 2008-06-21 21:37:42 +0100 (Sat, 21 Jun 2008) | 2 lines
    
    Fix some inspect errors (tabs and missing copyright/license).
  ................
    r46591 | danieljames | 2008-06-21 21:47:51 +0100 (Sat, 21 Jun 2008) | 1 line
    
    Move memory.hpp into the helpers subdirectory.
  ................
    r46592 | danieljames | 2008-06-21 22:08:53 +0100 (Sat, 21 Jun 2008) | 1 line
    
    Prevent inspect errors for unnamed namespaces in some of the test header files.
  ................
................
  r46607 | danieljames | 2008-06-22 14:54:45 +0100 (Sun, 22 Jun 2008) | 9 lines
  
  Extract the hash and equality functions from hash_table_data_*.
  
  As these are extensions and add extra requirements to the container elements,
  they shouldn't be part of hash_table_data_* so that they won't get instantiated
  if an unordered container is explicitly instantiated.
  
  Merged revisions 46594-46604 via svnmerge from 
  https://svn.boost.org/svn/boost/branches/unordered/trunk
................
  r46608 | danieljames | 2008-06-22 16:00:02 +0100 (Sun, 22 Jun 2008) | 5 lines
  
  Remove the svnmerge integration information for the unordered branch.
  
  Now that the unordered library is moving towards release, the main development
  version is in trunk. New features will be developed on a new branch.
................


[SVN r46629]
2008-06-23 17:44:53 +00:00

171 lines
5.9 KiB
C++

// Copyright 2006-2008 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_TEST_MEMORY_HEADER)
#define BOOST_UNORDERED_TEST_MEMORY_HEADER
#include <memory>
#include <map>
#include <boost/mpl/apply.hpp>
#include <boost/assert.hpp>
#include <boost/unordered/detail/allocator_helpers.hpp>
#include <boost/mpl/aux_/config/eti.hpp>
#include "../helpers/test.hpp"
namespace test
{
namespace detail
{
// This annoymous namespace won't cause ODR violations as I won't
// be linking multiple translation units together. I'll probably
// move this into a cpp file before a full release, but for now it's
// the most convenient way.
struct memory_area {
void const* start;
void const* end;
memory_area(void const* s, void const* e)
: start(s), end(e)
{
BOOST_ASSERT(start != end);
}
};
struct memory_track {
explicit memory_track(int tag = -1) :
constructed_(0),
tag_(tag) {}
int constructed_;
int tag_;
};
// This is a bit dodgy as it defines overlapping
// areas as 'equal', so this isn't a total ordering.
// But it is for non-overlapping memory regions - which
// is what'll be stored.
//
// All searches will be for areas entirely contained by
// a member of the set - so it should find the area that contains
// the region that is searched for.
struct memory_area_compare {
bool operator()(memory_area const& x, memory_area const& y) const {
return x.end <= y.start;
}
};
template <class Alloc>
struct allocator_memory_type_gen {
typedef std::map<memory_area, memory_track, memory_area_compare,
Alloc> type;
};
#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
template <>
struct allocator_memory_type_gen<int> {
typedef std::map<memory_area, memory_track, memory_area_compare> type;
};
#endif
template <class Alloc = std::allocator<int> >
struct memory_tracker {
typedef BOOST_DEDUCED_TYPENAME
boost::unordered_detail::rebind_wrap<Alloc,
std::pair<memory_area const, memory_track> >::type
allocator_type;
typedef BOOST_DEDUCED_TYPENAME allocator_memory_type_gen<allocator_type>::type
allocated_memory_type;
allocated_memory_type allocated_memory;
unsigned int count_allocators;
unsigned int count_allocations;
unsigned int count_constructions;
memory_tracker() :
count_allocators(0), count_allocations(0),
count_constructions(0)
{}
void allocator_ref()
{
if(count_allocators == 0) {
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
}
++count_allocators;
}
void allocator_unref()
{
BOOST_CHECK(count_allocators > 0);
if(count_allocators > 0) {
--count_allocators;
if(count_allocators == 0) {
bool no_allocations_left = (count_allocations == 0);
bool no_constructions_left = (count_constructions == 0);
bool allocated_memory_empty = allocated_memory.empty();
// Clearing the data before the checks terminate the tests.
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
BOOST_CHECK(no_allocations_left);
BOOST_CHECK(no_constructions_left);
BOOST_CHECK(allocated_memory_empty);
}
}
}
void track_allocate(void *ptr, std::size_t n, std::size_t size, int tag)
{
if(n == 0) {
BOOST_ERROR("Allocating 0 length array.");
}
else {
++count_allocations;
allocated_memory.insert(
std::pair<memory_area const, memory_track>(
memory_area(ptr, (char*) ptr + n * size),
memory_track(tag)));
}
}
void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag)
{
BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos
= allocated_memory.find(memory_area(ptr, (char*) ptr + n * size));
if(pos == allocated_memory.end()) {
BOOST_ERROR("Deallocating unknown pointer.");
} else {
BOOST_CHECK(pos->first.start == ptr);
BOOST_CHECK(pos->first.end == (char*) ptr + n * size);
BOOST_CHECK(pos->second.tag_ == tag);
allocated_memory.erase(pos);
}
BOOST_CHECK(count_allocations > 0);
if(count_allocations > 0) --count_allocations;
}
void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
++count_constructions;
}
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{
BOOST_CHECK(count_constructions > 0);
if(count_constructions > 0) --count_constructions;
}
};
}
}
#endif