mirror of git://gcc.gnu.org/git/gcc.git
re PR libstdc++/26132 (tr1/hashtable: rehash not implemented)
2006-02-22 Paolo Carlini <pcarlini@suse.de> PR libstdc++/26132 * include/tr1/hashtable (hashtable<>::rehash): Define. * testsuite/tr1/6_containers/unordered/hashtable/26132.cc: New. * include/tr1/hashtable: Trivial formatting and stylistic fixes. * testsuite/tr1/headers.cc: remove <tr1/hashtable>, not a tr1 header, only an implementation detail. From-SVN: r111366
This commit is contained in:
parent
e3a26d2fc5
commit
f8190ffc6c
|
|
@ -1,3 +1,14 @@
|
||||||
|
2006-02-22 Paolo Carlini <pcarlini@suse.de>
|
||||||
|
|
||||||
|
PR libstdc++/26132
|
||||||
|
* include/tr1/hashtable (hashtable<>::rehash): Define.
|
||||||
|
* testsuite/tr1/6_containers/unordered/hashtable/26132.cc: New.
|
||||||
|
|
||||||
|
* include/tr1/hashtable: Trivial formatting and stylistic fixes.
|
||||||
|
|
||||||
|
* testsuite/tr1/headers.cc: remove <tr1/hashtable>, not a tr1 header,
|
||||||
|
only an implementation detail.
|
||||||
|
|
||||||
2006-02-22 Paolo Carlini <pcarlini@suse.de>
|
2006-02-22 Paolo Carlini <pcarlini@suse.de>
|
||||||
|
|
||||||
* include/debug/list (splice): Remove splice_alloc check, redundant
|
* include/debug/list (splice): Remove splice_alloc check, redundant
|
||||||
|
|
|
||||||
|
|
@ -1132,6 +1132,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
{
|
{
|
||||||
return static_cast<float>(size()) / static_cast<float>(bucket_count());
|
return static_cast<float>(size()) / static_cast<float>(bucket_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
// max_load_factor, if present, comes from rehash_base.
|
// max_load_factor, if present, comes from rehash_base.
|
||||||
|
|
||||||
// Generalization of max_load_factor. Extension, not found in TR1. Only
|
// Generalization of max_load_factor. Extension, not found in TR1. Only
|
||||||
|
|
@ -1226,7 +1227,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Set number of buckets to be apropriate for container of n element.
|
// Set number of buckets to be appropriate for container of n element.
|
||||||
void rehash(size_type n);
|
void rehash(size_type n);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -1399,7 +1400,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
m_buckets = m_allocate_buckets(m_bucket_count);
|
m_buckets = m_allocate_buckets(m_bucket_count);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ht.m_bucket_count; ++i)
|
for (size_type i = 0; i < ht.m_bucket_count; ++i)
|
||||||
{
|
{
|
||||||
node* n = ht.m_buckets[i];
|
node* n = ht.m_buckets[i];
|
||||||
node** tail = m_buckets + i;
|
node** tail = m_buckets + i;
|
||||||
|
|
@ -1520,7 +1521,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
{
|
{
|
||||||
typename hashtable::hash_code_t code = this->m_hash_code(k);
|
typename hashtable::hash_code_t code = this->m_hash_code(k);
|
||||||
std::size_t n = this->bucket_index(k, code, this->bucket_count());
|
std::size_t n = this->bucket_index(k, code, this->bucket_count());
|
||||||
size_t result = 0;
|
std::size_t result = 0;
|
||||||
for (node* p = m_buckets[n]; p; p = p->m_next)
|
for (node* p = m_buckets[n]; p; p = p->m_next)
|
||||||
if (this->compare(k, code, p))
|
if (this->compare(k, code, p))
|
||||||
++result;
|
++result;
|
||||||
|
|
@ -1622,12 +1623,12 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
{
|
{
|
||||||
const key_type& k = this->m_extract(v);
|
const key_type& k = this->m_extract(v);
|
||||||
typename hashtable::hash_code_t code = this->m_hash_code(k);
|
typename hashtable::hash_code_t code = this->m_hash_code(k);
|
||||||
size_type n = this->bucket_index(k, code, m_bucket_count);
|
std::size_t n = this->bucket_index(k, code, m_bucket_count);
|
||||||
|
|
||||||
if (node* p = find_node(m_buckets[n], k, code))
|
if (node* p = find_node(m_buckets[n], k, code))
|
||||||
return std::make_pair(iterator(p, m_buckets + n), false);
|
return std::make_pair(iterator(p, m_buckets + n), false);
|
||||||
|
|
||||||
std::pair<bool, size_t> do_rehash
|
std::pair<bool, std::size_t> do_rehash
|
||||||
= m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
|
= m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
|
||||||
|
|
||||||
// Allocate the new node before doing the rehash so that we don't
|
// Allocate the new node before doing the rehash so that we don't
|
||||||
|
|
@ -1671,7 +1672,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
|
|
||||||
const key_type& k = this->m_extract(v);
|
const key_type& k = this->m_extract(v);
|
||||||
typename hashtable::hash_code_t code = this->m_hash_code(k);
|
typename hashtable::hash_code_t code = this->m_hash_code(k);
|
||||||
size_type n = this->bucket_index(k, code, m_bucket_count);
|
std::size_t n = this->bucket_index(k, code, m_bucket_count);
|
||||||
|
|
||||||
node* new_node = m_allocate_node(v);
|
node* new_node = m_allocate_node(v);
|
||||||
node* prev = find_node(m_buckets[n], k, code);
|
node* prev = find_node(m_buckets[n], k, code);
|
||||||
|
|
@ -1774,7 +1775,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
erase(const key_type& k)
|
erase(const key_type& k)
|
||||||
{
|
{
|
||||||
typename hashtable::hash_code_t code = this->m_hash_code(k);
|
typename hashtable::hash_code_t code = this->m_hash_code(k);
|
||||||
size_type n = this->bucket_index(k, code, m_bucket_count);
|
std::size_t n = this->bucket_index(k, code, m_bucket_count);
|
||||||
size_type result = 0;
|
size_type result = 0;
|
||||||
|
|
||||||
node** slot = m_buckets + n;
|
node** slot = m_buckets + n;
|
||||||
|
|
@ -1783,9 +1784,9 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
|
|
||||||
while (*slot && this->compare(k, code, *slot))
|
while (*slot && this->compare(k, code, *slot))
|
||||||
{
|
{
|
||||||
node* n = *slot;
|
node* p = *slot;
|
||||||
*slot = n->m_next;
|
*slot = p->m_next;
|
||||||
m_deallocate_node(n);
|
m_deallocate_node(p);
|
||||||
--m_element_count;
|
--m_element_count;
|
||||||
++result;
|
++result;
|
||||||
}
|
}
|
||||||
|
|
@ -1840,21 +1841,34 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
bool c, bool ci, bool u>
|
bool c, bool ci, bool u>
|
||||||
void
|
void
|
||||||
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
|
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
|
||||||
m_rehash(size_type N)
|
rehash(size_type n)
|
||||||
{
|
{
|
||||||
node** new_array = m_allocate_buckets(N);
|
m_rehash(std::max(m_rehash_policy.next_bkt(n),
|
||||||
|
m_rehash_policy.bkt_for_elements(m_element_count
|
||||||
|
+ 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename K, typename V,
|
||||||
|
typename A, typename Ex, typename Eq,
|
||||||
|
typename H1, typename H2, typename H, typename RP,
|
||||||
|
bool c, bool ci, bool u>
|
||||||
|
void
|
||||||
|
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
|
||||||
|
m_rehash(size_type n)
|
||||||
|
{
|
||||||
|
node** new_array = m_allocate_buckets(n);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (size_type i = 0; i < m_bucket_count; ++i)
|
for (size_type i = 0; i < m_bucket_count; ++i)
|
||||||
while (node* p = m_buckets[i])
|
while (node* p = m_buckets[i])
|
||||||
{
|
{
|
||||||
size_type new_index = this->bucket_index(p, N);
|
std::size_t new_index = this->bucket_index(p, n);
|
||||||
m_buckets[i] = p->m_next;
|
m_buckets[i] = p->m_next;
|
||||||
p->m_next = new_array[new_index];
|
p->m_next = new_array[new_index];
|
||||||
new_array[new_index] = p;
|
new_array[new_index] = p;
|
||||||
}
|
}
|
||||||
m_deallocate_buckets(m_buckets, m_bucket_count);
|
m_deallocate_buckets(m_buckets, m_bucket_count);
|
||||||
m_bucket_count = N;
|
m_bucket_count = n;
|
||||||
m_buckets = new_array;
|
m_buckets = new_array;
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
|
|
@ -1863,8 +1877,8 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
|
||||||
// We can't restore the previous state without calling the hash
|
// We can't restore the previous state without calling the hash
|
||||||
// function again, so the only sensible recovery is to delete
|
// function again, so the only sensible recovery is to delete
|
||||||
// everything.
|
// everything.
|
||||||
m_deallocate_nodes(new_array, N);
|
m_deallocate_nodes(new_array, n);
|
||||||
m_deallocate_buckets(new_array, N);
|
m_deallocate_buckets(new_array, n);
|
||||||
m_deallocate_nodes(m_buckets, m_bucket_count);
|
m_deallocate_nodes(m_buckets, m_bucket_count);
|
||||||
m_element_count = 0;
|
m_element_count = 0;
|
||||||
__throw_exception_again;
|
__throw_exception_again;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// 2006-02-22 Paolo Carlini <pcarlini@suse.de>
|
||||||
|
//
|
||||||
|
// Copyright (C) 2006 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
// USA.
|
||||||
|
|
||||||
|
// 6.3 Unordered associative containers
|
||||||
|
|
||||||
|
#include <tr1/unordered_set>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
|
// libstdc++/26132
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
|
||||||
|
for (float lf = 1.0; lf < 101.0; lf *= 10.0)
|
||||||
|
for (int size = 1; size <= 6561; size *= 3)
|
||||||
|
{
|
||||||
|
std::tr1::unordered_set<int> us1;
|
||||||
|
typedef std::tr1::unordered_set<int>::size_type size_type;
|
||||||
|
|
||||||
|
us1.max_load_factor(10.0);
|
||||||
|
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
us1.insert(i);
|
||||||
|
|
||||||
|
us1.max_load_factor(lf);
|
||||||
|
|
||||||
|
for (int i = 1; i <= 6561; i *= 81)
|
||||||
|
{
|
||||||
|
const size_type n = size * 81 / i;
|
||||||
|
us1.rehash(n);
|
||||||
|
VERIFY( us1.bucket_count() > us1.size() / us1.max_load_factor() );
|
||||||
|
VERIFY( us1.bucket_count() >= n );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -39,7 +39,6 @@
|
||||||
#include <tr1/fenv.h>
|
#include <tr1/fenv.h>
|
||||||
#include <tr1/float.h>
|
#include <tr1/float.h>
|
||||||
#include <tr1/functional>
|
#include <tr1/functional>
|
||||||
#include <tr1/hashtable>
|
|
||||||
#include <tr1/inttypes.h>
|
#include <tr1/inttypes.h>
|
||||||
#include <tr1/limits.h>
|
#include <tr1/limits.h>
|
||||||
#include <tr1/math.h>
|
#include <tr1/math.h>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue