re PR libstdc++/53115 (_Hashtable::_M_rehash_aux(false_type) is broken)
2012-05-01 François Dumont <fdumont@gcc.gnu.org> PR libstdc++/53115 * include/bits/hashtable.h (_Hashtable<>::_M_rehash_aux(size_type, false_type)): Fix buckets after insertion of several equivalent elements. * testsuite/23_containers/unordered_multiset/insert/53115.cc: New. * testsuite/23_containers/unordered_multimap/insert/53115.cc: New. From-SVN: r187025
This commit is contained in:
parent
fb99ee9ba6
commit
b7a9facb2c
@ -1,3 +1,12 @@
|
||||
2012-05-01 François Dumont <fdumont@gcc.gnu.org>
|
||||
|
||||
PR libstdc++/53115
|
||||
* include/bits/hashtable.h
|
||||
(_Hashtable<>::_M_rehash_aux(size_type, false_type)): Fix buckets
|
||||
after insertion of several equivalent elements.
|
||||
* testsuite/23_containers/unordered_multiset/insert/53115.cc: New.
|
||||
* testsuite/23_containers/unordered_multimap/insert/53115.cc: New.
|
||||
|
||||
2012-04-29 Marc Glisse <marc.glisse@inria.fr>
|
||||
Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
|
@ -1698,36 +1698,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
while (__p)
|
||||
{
|
||||
bool __check_now = true;
|
||||
__node_type* __next = __p->_M_next();
|
||||
std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
|
||||
|
||||
if (!__new_buckets[__bkt])
|
||||
if (__prev_p && __prev_bkt == __bkt)
|
||||
{
|
||||
__p->_M_nxt = _M_before_begin._M_nxt;
|
||||
_M_before_begin._M_nxt = __p;
|
||||
__new_buckets[__bkt] = &_M_before_begin;
|
||||
if (__p->_M_nxt)
|
||||
__new_buckets[__bbegin_bkt] = __p;
|
||||
__bbegin_bkt = __bkt;
|
||||
// Previous insert was already in this bucket, we insert after
|
||||
// the previously inserted one to preserve equivalent elements
|
||||
// relative order.
|
||||
__p->_M_nxt = __prev_p->_M_nxt;
|
||||
__prev_p->_M_nxt = __p;
|
||||
|
||||
// Inserting after a node in a bucket require to check that we
|
||||
// haven't change the bucket last node, in this case next
|
||||
// bucket containing its before begin node must be updated. We
|
||||
// schedule a check as soon as we move out of the sequence of
|
||||
// equivalent nodes to limit the number of checks.
|
||||
__check_bucket = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (__prev_p && __prev_bkt == __bkt)
|
||||
if (__check_bucket)
|
||||
{
|
||||
// Previous insert was already in this bucket, we insert after
|
||||
// the previously inserted one to preserve equivalent elements
|
||||
// relative order.
|
||||
__p->_M_nxt = __prev_p->_M_nxt;
|
||||
__prev_p->_M_nxt = __p;
|
||||
// Check if we shall update the next bucket because of insertions
|
||||
// into __prev_bkt bucket.
|
||||
if (__prev_p->_M_nxt)
|
||||
{
|
||||
std::size_t __next_bkt
|
||||
= __hash_code_base::_M_bucket_index(__prev_p->_M_next(),
|
||||
__n);
|
||||
if (__next_bkt != __prev_bkt)
|
||||
__new_buckets[__next_bkt] = __prev_p;
|
||||
}
|
||||
__check_bucket = false;
|
||||
}
|
||||
|
||||
// Inserting after a node in a bucket require to check that we
|
||||
// haven't change the bucket last node, in this case next
|
||||
// bucket containing its before begin node must be updated. We
|
||||
// schedule a check as soon as we move out of the sequence of
|
||||
// equivalent nodes to limit the number of checks.
|
||||
__check_bucket = true;
|
||||
__check_now = false;
|
||||
if (!__new_buckets[__bkt])
|
||||
{
|
||||
__p->_M_nxt = _M_before_begin._M_nxt;
|
||||
_M_before_begin._M_nxt = __p;
|
||||
__new_buckets[__bkt] = &_M_before_begin;
|
||||
if (__p->_M_nxt)
|
||||
__new_buckets[__bbegin_bkt] = __p;
|
||||
__bbegin_bkt = __bkt;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1735,21 +1748,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
__new_buckets[__bkt]->_M_nxt = __p;
|
||||
}
|
||||
}
|
||||
|
||||
if (__check_now && __check_bucket)
|
||||
{
|
||||
// Check if we shall update the next bucket because of insertions
|
||||
// into __prev_bkt bucket.
|
||||
if (__prev_p->_M_nxt)
|
||||
{
|
||||
std::size_t __next_bkt
|
||||
= __hash_code_base::_M_bucket_index(__prev_p->_M_next(),
|
||||
__n);
|
||||
if (__next_bkt != __prev_bkt)
|
||||
__new_buckets[__next_bkt] = __prev_p;
|
||||
}
|
||||
__check_bucket = false;
|
||||
}
|
||||
__prev_p = __p;
|
||||
__prev_bkt = __bkt;
|
||||
__p = __next;
|
||||
|
@ -0,0 +1,101 @@
|
||||
// { dg-options "-std=gnu++11" }
|
||||
//
|
||||
// Copyright (C) 2012 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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <unordered_map>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::size_t
|
||||
get_nb_bucket_elems(const std::unordered_multimap<int, int>& us)
|
||||
{
|
||||
std::size_t nb = 0;
|
||||
for (std::size_t b = 0; b != us.bucket_count(); ++b)
|
||||
nb += us.bucket_size(b);
|
||||
return nb;
|
||||
}
|
||||
}
|
||||
|
||||
void test01()
|
||||
{
|
||||
using namespace std;
|
||||
bool test __attribute__((unused)) = true;
|
||||
|
||||
std::unordered_multimap<int, int> umm;
|
||||
umm.insert(make_pair(10, 1));
|
||||
VERIFY( umm.size() == 1 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(10, 2));
|
||||
VERIFY( umm.size() == 2 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(10, 3));
|
||||
VERIFY( umm.size() == 3 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(10, 4));
|
||||
VERIFY( umm.size() == 4 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(10, 5));
|
||||
VERIFY( umm.size() == 5 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(24, 6));
|
||||
VERIFY( umm.size() == 6 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(25, 7));
|
||||
VERIFY( umm.size() == 7 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(2, 8));
|
||||
VERIFY( umm.size() == 8 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(2, 9));
|
||||
VERIFY( umm.size() == 9 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(1, 10));
|
||||
VERIFY( umm.size() == 10 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
|
||||
umm.insert(make_pair(10, 11));
|
||||
VERIFY( umm.size() == 11 );
|
||||
VERIFY( std::distance(umm.begin(), umm.end()) == umm.size() );
|
||||
VERIFY( get_nb_bucket_elems(umm) == umm.size() );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
// { dg-options "-std=gnu++11" }
|
||||
//
|
||||
// Copyright (C) 2012 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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <unordered_set>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::size_t
|
||||
get_nb_bucket_elems(const std::unordered_multiset<int>& us)
|
||||
{
|
||||
std::size_t nb = 0;
|
||||
for (std::size_t b = 0; b != us.bucket_count(); ++b)
|
||||
nb += us.bucket_size(b);
|
||||
return nb;
|
||||
}
|
||||
}
|
||||
|
||||
void test01()
|
||||
{
|
||||
using namespace std;
|
||||
bool test __attribute__((unused)) = true;
|
||||
|
||||
std::unordered_multiset<int> mms;
|
||||
mms.insert(10);
|
||||
VERIFY( mms.size() == 1 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(10);
|
||||
VERIFY( mms.size() == 2 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(10);
|
||||
VERIFY( mms.size() == 3 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(10);
|
||||
VERIFY( mms.size() == 4 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(10);
|
||||
VERIFY( mms.size() == 5 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(24);
|
||||
VERIFY( mms.size() == 6 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(25);
|
||||
VERIFY( mms.size() == 7 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(2);
|
||||
VERIFY( mms.size() == 8 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(2);
|
||||
VERIFY( mms.size() == 9 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(1);
|
||||
VERIFY( mms.size() == 10 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
|
||||
mms.insert(10);
|
||||
VERIFY( mms.size() == 11 );
|
||||
VERIFY( std::distance(mms.begin(), mms.end()) == mms.size() );
|
||||
VERIFY( get_nb_bucket_elems(mms) == mms.size() );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user