mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-30 11:27:15 +02:00
Merge pull request #152 from cmazakas/fix/rehash-allocation
Fix bug #147
This commit is contained in:
@ -3411,8 +3411,8 @@ namespace boost {
|
|||||||
template <typename Types>
|
template <typename Types>
|
||||||
inline void table<Types>::rehash(std::size_t num_buckets)
|
inline void table<Types>::rehash(std::size_t num_buckets)
|
||||||
{
|
{
|
||||||
num_buckets = (std::max)(
|
num_buckets = buckets_.bucket_count_for(
|
||||||
min_buckets(size_, mlf_), buckets_.bucket_count_for(num_buckets));
|
(std::max)(min_buckets(size_, mlf_), num_buckets));
|
||||||
|
|
||||||
if (num_buckets != this->bucket_count()) {
|
if (num_buckets != this->bucket_count()) {
|
||||||
this->rehash_impl(num_buckets);
|
this->rehash_impl(num_buckets);
|
||||||
|
@ -6,16 +6,48 @@
|
|||||||
|
|
||||||
#include "../helpers/unordered.hpp"
|
#include "../helpers/unordered.hpp"
|
||||||
|
|
||||||
#include "../helpers/test.hpp"
|
|
||||||
#include "../helpers/random_values.hpp"
|
|
||||||
#include "../helpers/tracker.hpp"
|
|
||||||
#include "../helpers/metafunctions.hpp"
|
#include "../helpers/metafunctions.hpp"
|
||||||
|
#include "../helpers/random_values.hpp"
|
||||||
|
#include "../helpers/test.hpp"
|
||||||
|
#include "../helpers/tracker.hpp"
|
||||||
#include "../objects/test.hpp"
|
#include "../objects/test.hpp"
|
||||||
|
|
||||||
namespace rehash_tests {
|
namespace rehash_tests {
|
||||||
|
|
||||||
test::seed_t initialize_seed(2974);
|
test::seed_t initialize_seed(2974);
|
||||||
|
|
||||||
|
static int count_allocations;
|
||||||
|
template <class T> struct monotonic_allocator
|
||||||
|
{
|
||||||
|
typedef T value_type;
|
||||||
|
monotonic_allocator() {}
|
||||||
|
monotonic_allocator(monotonic_allocator const&) {}
|
||||||
|
|
||||||
|
template <class U> monotonic_allocator(monotonic_allocator<U> const&) {}
|
||||||
|
|
||||||
|
friend bool operator==(
|
||||||
|
monotonic_allocator const&, monotonic_allocator const&)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(
|
||||||
|
monotonic_allocator const&, monotonic_allocator const&)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* allocate(std::size_t n)
|
||||||
|
{
|
||||||
|
++count_allocations;
|
||||||
|
return static_cast<T*>(::operator new(sizeof(T) * n));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(T* p, std::size_t) { ::operator delete(p); }
|
||||||
|
};
|
||||||
|
|
||||||
|
void reset_counts() { count_allocations = 0; }
|
||||||
|
|
||||||
template <class X> bool postcondition(X const& x, typename X::size_type n)
|
template <class X> bool postcondition(X const& x, typename X::size_type n)
|
||||||
{
|
{
|
||||||
return static_cast<double>(x.bucket_count()) >=
|
return static_cast<double>(x.bucket_count()) >=
|
||||||
@ -321,9 +353,10 @@ namespace rehash_tests {
|
|||||||
BOOST_TEST_GT(x.bucket_count(), 0u);
|
BOOST_TEST_GT(x.bucket_count(), 0u);
|
||||||
|
|
||||||
x.reserve(
|
x.reserve(
|
||||||
2 * (static_cast<size_type>(
|
2 *
|
||||||
std::floor(static_cast<float>(x.size()) / x.max_load_factor()) +
|
(static_cast<size_type>(
|
||||||
std::floor(static_cast<float>(x.size()) * x.max_load_factor()))));
|
std::floor(static_cast<float>(x.size()) / x.max_load_factor()) +
|
||||||
|
std::floor(static_cast<float>(x.size()) * x.max_load_factor()))));
|
||||||
|
|
||||||
BOOST_TEST_GT(x.bucket_count(), bucket_count);
|
BOOST_TEST_GT(x.bucket_count(), bucket_count);
|
||||||
|
|
||||||
@ -376,6 +409,34 @@ namespace rehash_tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class X> void rehash_stability(X*, test::random_generator generator)
|
||||||
|
{
|
||||||
|
reset_counts();
|
||||||
|
|
||||||
|
typedef typename X::size_type size_type;
|
||||||
|
|
||||||
|
size_type bucket_count = 100;
|
||||||
|
X x(bucket_count);
|
||||||
|
|
||||||
|
size_type num_elems = x.bucket_count() - 1;
|
||||||
|
|
||||||
|
test::random_values<X> v(num_elems, generator);
|
||||||
|
test::ordered<X> tracker;
|
||||||
|
tracker.insert_range(v.begin(), v.end());
|
||||||
|
|
||||||
|
typename test::random_values<X>::iterator pos = v.begin();
|
||||||
|
for (size_type i = 0; i < num_elems; ++i) {
|
||||||
|
x.insert(*pos);
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int const old_count = count_allocations;
|
||||||
|
x.rehash(0);
|
||||||
|
|
||||||
|
BOOST_TEST_EQ(count_allocations, old_count);
|
||||||
|
tracker.compare(x);
|
||||||
|
}
|
||||||
|
|
||||||
template <class X> void rehash_test1(X*, test::random_generator generator)
|
template <class X> void rehash_test1(X*, test::random_generator generator)
|
||||||
{
|
{
|
||||||
test::random_values<X> v(1000, generator);
|
test::random_values<X> v(1000, generator);
|
||||||
@ -513,6 +574,13 @@ namespace rehash_tests {
|
|||||||
test::allocator1<std::pair<test::object const, test::object> > >*
|
test::allocator1<std::pair<test::object const, test::object> > >*
|
||||||
test_map_tracking;
|
test_map_tracking;
|
||||||
|
|
||||||
|
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
|
||||||
|
monotonic_allocator<test::object> >* test_set_monotonic;
|
||||||
|
boost::unordered_flat_map<test::object, test::object, test::hash,
|
||||||
|
test::equal_to,
|
||||||
|
monotonic_allocator<std::pair<test::object const, test::object> > >*
|
||||||
|
test_map_monotonic;
|
||||||
|
|
||||||
UNORDERED_TEST(rehash_empty_test1, ((int_set_ptr)(test_map_ptr)))
|
UNORDERED_TEST(rehash_empty_test1, ((int_set_ptr)(test_map_ptr)))
|
||||||
UNORDERED_TEST(rehash_empty_test2,
|
UNORDERED_TEST(rehash_empty_test2,
|
||||||
((int_set_ptr)(test_map_ptr))(
|
((int_set_ptr)(test_map_ptr))(
|
||||||
@ -534,9 +602,11 @@ namespace rehash_tests {
|
|||||||
UNORDERED_TEST(rehash_empty_tracking,
|
UNORDERED_TEST(rehash_empty_tracking,
|
||||||
((test_set_tracking)(test_map_tracking))(
|
((test_set_tracking)(test_map_tracking))(
|
||||||
(default_generator)(generate_collisions)(limited_range)))
|
(default_generator)(generate_collisions)(limited_range)))
|
||||||
UNORDERED_TEST(rehash_nonempty_tracking,
|
UNORDERED_TEST(
|
||||||
((test_set_tracking)(test_map_tracking))(
|
rehash_nonempty_tracking, ((test_set_tracking)(test_map_tracking))(
|
||||||
(default_generator)(generate_collisions)(limited_range)))
|
(default_generator)(limited_range)))
|
||||||
|
UNORDERED_TEST(rehash_stability, ((test_set_monotonic)(test_map_monotonic))(
|
||||||
|
(default_generator)(limited_range)))
|
||||||
#else
|
#else
|
||||||
boost::unordered_set<int>* int_set_ptr;
|
boost::unordered_set<int>* int_set_ptr;
|
||||||
boost::unordered_multiset<test::object, test::hash, test::equal_to,
|
boost::unordered_multiset<test::object, test::hash, test::equal_to,
|
||||||
@ -557,6 +627,18 @@ namespace rehash_tests {
|
|||||||
test::allocator1<std::pair<test::object const, test::object> > >*
|
test::allocator1<std::pair<test::object const, test::object> > >*
|
||||||
test_multimap_tracking;
|
test_multimap_tracking;
|
||||||
|
|
||||||
|
boost::unordered_set<test::object, test::hash, test::equal_to,
|
||||||
|
monotonic_allocator<test::object> >* test_set_monotonic;
|
||||||
|
boost::unordered_multiset<test::object, test::hash, test::equal_to,
|
||||||
|
monotonic_allocator<test::object> >* test_multiset_monotonic;
|
||||||
|
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
|
||||||
|
monotonic_allocator<std::pair<test::object const, test::object> > >*
|
||||||
|
test_map_monotonic;
|
||||||
|
boost::unordered_multimap<test::object, test::object, test::hash,
|
||||||
|
test::equal_to,
|
||||||
|
monotonic_allocator<std::pair<test::object const, test::object> > >*
|
||||||
|
test_multimap_monotonic;
|
||||||
|
|
||||||
UNORDERED_TEST(rehash_empty_test1,
|
UNORDERED_TEST(rehash_empty_test1,
|
||||||
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
|
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
|
||||||
UNORDERED_TEST(rehash_empty_test2,
|
UNORDERED_TEST(rehash_empty_test2,
|
||||||
@ -584,7 +666,10 @@ namespace rehash_tests {
|
|||||||
UNORDERED_TEST(rehash_nonempty_tracking,
|
UNORDERED_TEST(rehash_nonempty_tracking,
|
||||||
((test_set_tracking)(test_multiset_tracking)(test_map_tracking)(test_multimap_tracking))(
|
((test_set_tracking)(test_multiset_tracking)(test_map_tracking)(test_multimap_tracking))(
|
||||||
(default_generator)(generate_collisions)(limited_range)))
|
(default_generator)(generate_collisions)(limited_range)))
|
||||||
|
UNORDERED_TEST(rehash_stability,
|
||||||
|
((test_set_monotonic)(test_multiset_monotonic)(test_map_monotonic)(test_multimap_monotonic))(
|
||||||
|
(default_generator)(limited_range)))
|
||||||
#endif
|
#endif
|
||||||
}
|
} // namespace rehash_tests
|
||||||
|
|
||||||
RUN_TESTS()
|
RUN_TESTS()
|
||||||
|
Reference in New Issue
Block a user