Unordered: Remove malloc_allocator.

It was originally introduced because of some issues with Boost.Test and older
compilers, neither of which I'm using now. Simplifies a few things.

[SVN r79352]
This commit is contained in:
Daniel James
2012-07-08 11:53:39 +00:00
parent b8d96be8f7
commit 98083078a3
7 changed files with 56 additions and 167 deletions

View File

@ -32,7 +32,7 @@ struct insert_test_base : public test::exception_base
std::string scope(test::scope); std::string scope(test::scope);
if(scope.find("hash::operator()") == std::string::npos) if(scope.find("hash::operator()") == std::string::npos)
strong.test(x, test::exception::detail::tracker.count_allocations); strong.test(x, test::detail::tracker.count_allocations);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
@ -49,7 +49,7 @@ struct emplace_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end(); it = this->values.begin(), end = this->values.end();
it != end; ++it) it != end; ++it)
{ {
strong.store(x, test::exception::detail::tracker.count_allocations); strong.store(x, test::detail::tracker.count_allocations);
x.emplace(*it); x.emplace(*it);
} }
} }
@ -67,7 +67,7 @@ struct insert_test1 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end(); it = this->values.begin(), end = this->values.end();
it != end; ++it) it != end; ++it)
{ {
strong.store(x, test::exception::detail::tracker.count_allocations); strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it); x.insert(*it);
} }
} }
@ -83,7 +83,7 @@ struct insert_test2 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end(); it = this->values.begin(), end = this->values.end();
it != end; ++it) it != end; ++it)
{ {
strong.store(x, test::exception::detail::tracker.count_allocations); strong.store(x, test::detail::tracker.count_allocations);
x.insert(x.begin(), *it); x.insert(x.begin(), *it);
} }
} }
@ -111,7 +111,7 @@ struct insert_test4 : public insert_test_base<T>
it = this->values.begin(), end = this->values.end(); it = this->values.begin(), end = this->values.end();
it != end; ++it) it != end; ++it)
{ {
strong.store(x, test::exception::detail::tracker.count_allocations); strong.store(x, test::detail::tracker.count_allocations);
x.insert(it, boost::next(it)); x.insert(it, boost::next(it));
} }
} }
@ -150,7 +150,7 @@ struct insert_test_rehash1 : public insert_test_base<T>
end = this->values.end(); end = this->values.end();
it != end && count < 10; ++it, ++count) it != end && count < 10; ++it, ++count)
{ {
strong.store(x, test::exception::detail::tracker.count_allocations); strong.store(x, test::detail::tracker.count_allocations);
pos = x.insert(pos, *it); pos = x.insert(pos, *it);
} }
@ -174,7 +174,7 @@ struct insert_test_rehash2 : public insert_test_rehash1<T>
end = this->values.end(); end = this->values.end();
it != end && count < 10; ++it, ++count) it != end && count < 10; ++it, ++count)
{ {
strong.store(x, test::exception::detail::tracker.count_allocations); strong.store(x, test::detail::tracker.count_allocations);
x.insert(*it); x.insert(*it);
} }

View File

@ -1,84 +0,0 @@
// Copyright 2006-2009 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_MALLOC_ALLOCATOR_HEADER)
#define BOOST_UNORDERED_TEST_MALLOC_ALLOCATOR_HEADER
#include <cstddef>
#include <cstdlib>
#include <boost/limits.hpp>
#include <new>
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
namespace test
{
template <class T>
struct malloc_allocator
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T const* const_pointer;
typedef T& reference;
typedef T const& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef malloc_allocator<U> other; };
malloc_allocator() {}
template <class Y> malloc_allocator(malloc_allocator<Y> const&) {}
malloc_allocator(malloc_allocator const&) {}
pointer address(reference r) { return &r; }
const_pointer address(const_reference r) { return &r; }
pointer allocate(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(T)));
if(!ptr) throw std::bad_alloc();
return ptr;
}
pointer allocate(size_type n, void const* u) { return allocate(n); }
void deallocate(pointer p, size_type) {
using namespace std;
free(p);
}
void construct(pointer p, T const& t) { new(p) T(t); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const {
return (std::numeric_limits<size_type>::max)();
}
bool operator==(malloc_allocator const&) const { return true; }
bool operator!=(malloc_allocator const&) const { return false; }
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template <class T> void deallocate(T* p, size_type) {
using namespace std;
free(p);
}
char* _Charalloc(size_type n) {
using namespace std;
T* ptr = static_cast<T*>(malloc(n * sizeof(char)));
if(!ptr) throw std::bad_alloc();
return (char*) ptr;
}
#endif
};
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#endif

View File

@ -13,7 +13,6 @@
#include <cmath> #include <cmath>
#include "./metafunctions.hpp" #include "./metafunctions.hpp"
#include "./helpers.hpp" #include "./helpers.hpp"
#include "./allocator.hpp"
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
#pragma warning(push) #pragma warning(push)
@ -29,10 +28,7 @@ namespace test
{ {
BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq(); BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq();
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
// Boost.Test was reporting memory leaks for std::set on g++-3.3. std::set<key_type, std::less<key_type> > found_;
// So I work around it by using malloc.
std::set<key_type, std::less<key_type>,
test::malloc_allocator<key_type> > found_;
BOOST_DEDUCED_TYPENAME X::const_iterator BOOST_DEDUCED_TYPENAME X::const_iterator
it = x1.begin(), end = x1.end(); it = x1.begin(), end = x1.end();

View File

@ -53,30 +53,10 @@ namespace test
} }
}; };
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 { struct memory_tracker {
typedef BOOST_DEDUCED_TYPENAME typedef std::map<memory_area, memory_track, memory_area_compare,
::boost::unordered::detail::rebind_wrap<Alloc, std::allocator<std::pair<memory_area const, memory_track> >
std::pair<memory_area const, memory_track> >::type > allocated_memory_type;
allocator_type;
typedef BOOST_DEDUCED_TYPENAME
allocator_memory_type_gen<allocator_type>::type
allocated_memory_type;
allocated_memory_type allocated_memory; allocated_memory_type allocated_memory;
unsigned int count_allocators; unsigned int count_allocators;
@ -139,7 +119,7 @@ namespace test
void track_deallocate(void* ptr, std::size_t n, std::size_t size, void track_deallocate(void* ptr, std::size_t n, std::size_t size,
int tag, bool check_tag_ = true) int tag, bool check_tag_ = true)
{ {
BOOST_DEDUCED_TYPENAME allocated_memory_type::iterator pos = allocated_memory_type::iterator pos =
allocated_memory.find( allocated_memory.find(
memory_area(ptr, (char*) ptr + n * size)); memory_area(ptr, (char*) ptr + n * size));
if(pos == allocated_memory.end()) { if(pos == allocated_memory.end()) {
@ -177,7 +157,7 @@ namespace test
// //
// boostinspect:nounnamed // boostinspect:nounnamed
namespace { namespace {
test::detail::memory_tracker<std::allocator<int> > tracker; test::detail::memory_tracker tracker;
} }
} }

View File

@ -21,7 +21,8 @@ namespace test
is_select_on_copy = 0, is_select_on_copy = 0,
is_propagate_on_swap = 0, is_propagate_on_swap = 0,
is_propagate_on_assign = 0, is_propagate_on_assign = 0,
is_propagate_on_move = 0 is_propagate_on_move = 0,
cxx11_construct = 0
}; };
}; };
@ -31,7 +32,8 @@ namespace test
is_select_on_copy = 1, is_select_on_copy = 1,
is_propagate_on_swap = 1, is_propagate_on_swap = 1,
is_propagate_on_assign = 1, is_propagate_on_assign = 1,
is_propagate_on_move = 1 is_propagate_on_move = 1,
cxx11_construct = 1
}; };
}; };

View File

@ -13,21 +13,12 @@
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <new> #include <new>
#include "../helpers/fwd.hpp" #include "../helpers/fwd.hpp"
#include "../helpers/allocator.hpp"
#include "../helpers/memory.hpp" #include "../helpers/memory.hpp"
namespace test namespace test
{ {
namespace exception namespace exception
{ {
namespace detail
{
namespace
{
test::detail::memory_tracker<test::malloc_allocator<int> > tracker;
}
}
class object; class object;
class hash; class hash;
class equal_to; class equal_to;
@ -259,7 +250,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) { UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator default constructor."); UNORDERED_EPOINT("Mock allocator default constructor.");
} }
detail::tracker.allocator_ref(); test::detail::tracker.allocator_ref();
} }
template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_) template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_)
@ -267,7 +258,7 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) { UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator template copy constructor."); UNORDERED_EPOINT("Mock allocator template copy constructor.");
} }
detail::tracker.allocator_ref(); test::detail::tracker.allocator_ref();
} }
allocator(allocator const& x) : tag_(x.tag_) allocator(allocator const& x) : tag_(x.tag_)
@ -275,11 +266,11 @@ namespace exception
UNORDERED_SCOPE(allocator::allocator()) { UNORDERED_SCOPE(allocator::allocator()) {
UNORDERED_EPOINT("Mock allocator copy constructor."); UNORDERED_EPOINT("Mock allocator copy constructor.");
} }
detail::tracker.allocator_ref(); test::detail::tracker.allocator_ref();
} }
~allocator() { ~allocator() {
detail::tracker.allocator_unref(); test::detail::tracker.allocator_unref();
} }
allocator& operator=(allocator const& x) { allocator& operator=(allocator const& x) {
@ -317,7 +308,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T)); ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc(); if(!ptr) throw std::bad_alloc();
} }
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_); test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr); return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T)))); //return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@ -333,7 +324,7 @@ namespace exception
ptr = (T*) malloc(n * sizeof(T)); ptr = (T*) malloc(n * sizeof(T));
if(!ptr) throw std::bad_alloc(); if(!ptr) throw std::bad_alloc();
} }
detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_); test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
return pointer(ptr); return pointer(ptr);
//return pointer(static_cast<T*>(::operator new(n * sizeof(T)))); //return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
@ -343,7 +334,7 @@ namespace exception
{ {
//::operator delete((void*) p); //::operator delete((void*) p);
if(p) { if(p) {
detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_); test::detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
using namespace std; using namespace std;
free(p); free(p);
} }
@ -354,7 +345,7 @@ namespace exception
UNORDERED_EPOINT("Mock allocator construct function."); UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(t); new(p) T(t);
} }
detail::tracker.track_construct((void*) p, sizeof(T), tag_); test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
} }
#if !defined(BOOST_NO_VARIADIC_TEMPLATES) #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
@ -363,12 +354,12 @@ namespace exception
UNORDERED_EPOINT("Mock allocator construct function."); UNORDERED_EPOINT("Mock allocator construct function.");
new(p) T(boost::forward<Args>(args)...); new(p) T(boost::forward<Args>(args)...);
} }
detail::tracker.track_construct((void*) p, sizeof(T), tag_); test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
} }
#endif #endif
void destroy(T* p) { void destroy(T* p) {
detail::tracker.track_destroy((void*) p, sizeof(T), tag_); test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
p->~T(); p->~T();
} }

View File

@ -15,26 +15,25 @@ namespace x
struct D { boost::unordered_map<D, D> x; }; struct D { boost::unordered_map<D, D> x; };
} }
namespace test namespace incomplete_test
{ {
// Declare, but don't define some types. // Declare, but don't define some types.
struct value; struct value;
struct hash; struct hash;
struct equals; struct equals;
template <class T> template <class T> struct allocator;
struct malloc_allocator;
// Declare some instances // Declare some instances
typedef boost::unordered_map<value, value, hash, equals, typedef boost::unordered_map<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > map; allocator<std::pair<value const, value> > > map;
typedef boost::unordered_multimap<value, value, hash, equals, typedef boost::unordered_multimap<value, value, hash, equals,
malloc_allocator<std::pair<value const, value> > > multimap; allocator<std::pair<value const, value> > > multimap;
typedef boost::unordered_set<value, hash, equals, typedef boost::unordered_set<value, hash, equals,
malloc_allocator<value> > set; allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals, typedef boost::unordered_multiset<value, hash, equals,
malloc_allocator<value> > multiset; allocator<value> > multiset;
// Now define the types which are stored as members, as they are needed for // Now define the types which are stored as members, as they are needed for
// declaring struct members. // declaring struct members.
@ -49,12 +48,17 @@ namespace test
bool operator()(T const&, T const&) const { return true; } bool operator()(T const&, T const&) const { return true; }
}; };
} // This is a dubious way to implement an allocator, but good enough
// for this test.
template <typename T>
struct allocator : std::allocator<T> {
allocator() {}
#include "../helpers/allocator.hpp" template <typename T2>
allocator(const allocator<T2>& other) :
std::allocator<T>(other) {}
};
namespace test
{
// Declare some members of a structs. // Declare some members of a structs.
// //
// Incomplete hash, equals and allocator aren't here supported at the // Incomplete hash, equals and allocator aren't here supported at the
@ -62,19 +66,19 @@ namespace test
struct struct1 { struct struct1 {
boost::unordered_map<struct1, struct1, hash, equals, boost::unordered_map<struct1, struct1, hash, equals,
malloc_allocator<std::pair<struct1 const, struct1> > > x; allocator<std::pair<struct1 const, struct1> > > x;
}; };
struct struct2 { struct struct2 {
boost::unordered_multimap<struct2, struct2, hash, equals, boost::unordered_multimap<struct2, struct2, hash, equals,
malloc_allocator<std::pair<struct2 const, struct2> > > x; allocator<std::pair<struct2 const, struct2> > > x;
}; };
struct struct3 { struct struct3 {
boost::unordered_set<struct3, hash, equals, boost::unordered_set<struct3, hash, equals,
malloc_allocator<struct3> > x; allocator<struct3> > x;
}; };
struct struct4 { struct struct4 {
boost::unordered_multiset<struct4, hash, equals, boost::unordered_multiset<struct4, hash, equals,
malloc_allocator<struct4> > x; allocator<struct4> > x;
}; };
// Now define the value type. // Now define the value type.
@ -83,15 +87,15 @@ namespace test
// Create some instances. // Create some instances.
test::map m1; incomplete_test::map m1;
test::multimap m2; incomplete_test::multimap m2;
test::set s1; incomplete_test::set s1;
test::multiset s2; incomplete_test::multiset s2;
test::struct1 c1; incomplete_test::struct1 c1;
test::struct2 c2; incomplete_test::struct2 c2;
test::struct3 c3; incomplete_test::struct3 c3;
test::struct4 c4; incomplete_test::struct4 c4;
// Now declare, but don't define, the operators required for comparing // Now declare, but don't define, the operators required for comparing
// elements. // elements.
@ -113,7 +117,7 @@ namespace test
void use_types() void use_types()
{ {
test::value x; incomplete_test::value x;
m1[x] = x; m1[x] = x;
m2.insert(std::make_pair(x, x)); m2.insert(std::make_pair(x, x));
s1.insert(x); s1.insert(x);
@ -145,5 +149,5 @@ int main() {
// This could just be a compile test, but I like to be able to run these // This could just be a compile test, but I like to be able to run these
// things. It's probably irrational, but I find it reassuring. // things. It's probably irrational, but I find it reassuring.
test::use_types(); incomplete_test::use_types();
} }