aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorPaolo Carlini <paolo.carlini@oracle.com>2010-08-31 17:39:51 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2010-08-31 17:39:51 +0000
commit18dbb8590310fedf2948bf0677d18cddb85fa5c9 (patch)
treeabf771e125f7ff3903e8b48ccac872d9b91c645d /libstdc++-v3
parent6208468d29f6c51810131721cb205d81f1b7d23e (diff)
downloadgcc-18dbb8590310fedf2948bf0677d18cddb85fa5c9.zip
gcc-18dbb8590310fedf2948bf0677d18cddb85fa5c9.tar.gz
gcc-18dbb8590310fedf2948bf0677d18cddb85fa5c9.tar.bz2
re PR libstdc++/44480 ([C++0x] Linear performance of begin() in unordered associative containers)
2010-08-31 Paolo Carlini <paolo.carlini@oracle.com> PR libstdc++/44480 * include/bits/hashtable.h (_Hashtable<>::_M_begin_bucket_index): Add, caching the index of the first non-empty bucket. (begin, cbegin): Use it. (_Hashtable<>::_Hashtable(_InputIterator, _InputIterator, ...), _Hashtable(const _Hashtable&), _Hashtable(_Hashtable&&), swap(_Hashtable&), clear): Adjust. (_M_insert_bucket, _M_insert, erase(const_iterator), erase(const key_type&), _M_rehash): Update it. * include/bits/hashtable.h (_Hashtable<>::_M_erase): Remove. (erase(const_iterator)): Inline the latter. From-SVN: r163686
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog15
-rw-r--r--libstdc++-v3/include/bits/hashtable.h114
2 files changed, 76 insertions, 53 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 1f435ff..07b058e 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,20 @@
2010-08-31 Paolo Carlini <paolo.carlini@oracle.com>
+ PR libstdc++/44480
+ * include/bits/hashtable.h (_Hashtable<>::_M_begin_bucket_index):
+ Add, caching the index of the first non-empty bucket.
+ (begin, cbegin): Use it.
+ (_Hashtable<>::_Hashtable(_InputIterator, _InputIterator, ...),
+ _Hashtable(const _Hashtable&), _Hashtable(_Hashtable&&),
+ swap(_Hashtable&), clear): Adjust.
+ (_M_insert_bucket, _M_insert, erase(const_iterator),
+ erase(const key_type&), _M_rehash): Update it.
+
+ * include/bits/hashtable.h (_Hashtable<>::_M_erase): Remove.
+ (erase(const_iterator)): Inline the latter.
+
+2010-08-31 Paolo Carlini <paolo.carlini@oracle.com>
+
* testsuite/23_containers/forward_list/operations/remove_freed.cc:
Fix test01 return type to void.
* testsuite/util/exception/safety.h: Avoid -Wall -m32 warnings.
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index e62e156..be6d9a1 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -175,6 +175,7 @@ namespace std
_Node_allocator_type _M_node_allocator;
_Node** _M_buckets;
size_type _M_bucket_count;
+ size_type _M_begin_bucket_index; // First non-empty bucket.
size_type _M_element_count;
_RehashPolicy _M_rehash_policy;
@@ -236,21 +237,11 @@ namespace std
// Basic container operations
iterator
begin()
- {
- iterator __i(_M_buckets);
- if (!__i._M_cur_node)
- __i._M_incr_bucket();
- return __i;
- }
+ { return iterator(_M_buckets + _M_begin_bucket_index); }
const_iterator
begin() const
- {
- const_iterator __i(_M_buckets);
- if (!__i._M_cur_node)
- __i._M_incr_bucket();
- return __i;
- }
+ { return const_iterator(_M_buckets + _M_begin_bucket_index); }
iterator
end()
@@ -262,12 +253,7 @@ namespace std
const_iterator
cbegin() const
- {
- const_iterator __i(_M_buckets);
- if (!__i._M_cur_node)
- __i._M_incr_bucket();
- return __i;
- }
+ { return const_iterator(_M_buckets + _M_begin_bucket_index); }
const_iterator
cend() const
@@ -408,10 +394,7 @@ namespace std
iterator
_M_insert(const value_type&, std::false_type);
- void
- _M_erase_node(_Node*, _Node**);
-
- public:
+ public:
// Insert and erase
_Insert_Return_Type
insert(const value_type& __v)
@@ -571,6 +554,7 @@ namespace std
{
_M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
_M_buckets = _M_allocate_buckets(_M_bucket_count);
+ _M_begin_bucket_index = _M_bucket_count;
}
template<typename _Key, typename _Value,
@@ -601,6 +585,7 @@ namespace std
__distance_fw(__f,
__l)));
_M_buckets = _M_allocate_buckets(_M_bucket_count);
+ _M_begin_bucket_index = _M_bucket_count;
__try
{
for (; __f != __l; ++__f)
@@ -627,6 +612,7 @@ namespace std
__detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(__ht),
_M_node_allocator(__ht._M_node_allocator),
_M_bucket_count(__ht._M_bucket_count),
+ _M_begin_bucket_index(__ht._M_begin_bucket_index),
_M_element_count(__ht._M_element_count),
_M_rehash_policy(__ht._M_rehash_policy)
{
@@ -668,12 +654,14 @@ namespace std
_M_node_allocator(__ht._M_node_allocator),
_M_buckets(__ht._M_buckets),
_M_bucket_count(__ht._M_bucket_count),
+ _M_begin_bucket_index(__ht._M_begin_bucket_index),
_M_element_count(__ht._M_element_count),
_M_rehash_policy(__ht._M_rehash_policy)
{
size_type __n_bkt = __ht._M_rehash_policy._M_next_bkt(0);
__ht._M_buckets = __ht._M_allocate_buckets(__n_bkt);
__ht._M_bucket_count = __n_bkt;
+ __ht._M_begin_bucket_index = __ht._M_bucket_count;
__ht._M_element_count = 0;
__ht._M_rehash_policy = _RehashPolicy();
}
@@ -713,6 +701,7 @@ namespace std
std::swap(_M_rehash_policy, __x._M_rehash_policy);
std::swap(_M_buckets, __x._M_buckets);
std::swap(_M_bucket_count, __x._M_bucket_count);
+ std::swap(_M_begin_bucket_index, __x._M_begin_bucket_index);
std::swap(_M_element_count, __x._M_element_count);
}
@@ -915,6 +904,8 @@ namespace std
this->_M_store_code(__new_node, __code);
_M_buckets[__n] = __new_node;
++_M_element_count;
+ if (__n < _M_begin_bucket_index)
+ _M_begin_bucket_index = __n;
return iterator(__new_node, _M_buckets + __n);
}
__catch(...)
@@ -981,6 +972,8 @@ namespace std
{
__new_node->_M_next = _M_buckets[__n];
_M_buckets[__n] = __new_node;
+ if (__n < _M_begin_bucket_index)
+ _M_begin_bucket_index = __n;
}
this->_M_store_code(__new_node, __code);
@@ -988,34 +981,6 @@ namespace std
return iterator(__new_node, _M_buckets + __n);
}
- // For erase(iterator) and erase(const_iterator).
- template<typename _Key, typename _Value,
- typename _Allocator, typename _ExtractKey, typename _Equal,
- typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
- bool __chc, bool __cit, bool __uk>
- void
- _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
- _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
- _M_erase_node(_Node* __p, _Node** __b)
- {
- _Node* __cur = *__b;
- if (__cur == __p)
- *__b = __cur->_M_next;
- else
- {
- _Node* __next = __cur->_M_next;
- while (__next != __p)
- {
- __cur = __next;
- __next = __cur->_M_next;
- }
- __cur->_M_next = __next->_M_next;
- }
-
- _M_deallocate_node(__p);
- --_M_element_count;
- }
-
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
@@ -1050,7 +1015,31 @@ namespace std
{
iterator __result(__it._M_cur_node, __it._M_cur_bucket);
++__result;
- _M_erase_node(__it._M_cur_node, __it._M_cur_bucket);
+
+ _Node* __cur = *__it._M_cur_bucket;
+ if (__cur == __it._M_cur_node)
+ {
+ *__it._M_cur_bucket = __cur->_M_next;
+
+ // If _M_begin_bucket_index no longer indexes the first non-empty
+ // bucket - its single node is being erased - update it.
+ if (!_M_buckets[_M_begin_bucket_index])
+ _M_begin_bucket_index = __result._M_cur_bucket - _M_buckets;
+ }
+ else
+ {
+ _Node* __next = __cur->_M_next;
+ while (__next != __it._M_cur_node)
+ {
+ __cur = __next;
+ __next = __cur->_M_next;
+ }
+ __cur->_M_next = __next->_M_next;
+ }
+
+ _M_deallocate_node(__it._M_cur_node);
+ --_M_element_count;
+
return __result;
}
@@ -1104,6 +1093,20 @@ namespace std
++__result;
}
+ // If the entire bucket indexed by _M_begin_bucket_index has been
+ // erased look forward for the first non-empty bucket.
+ if (!_M_buckets[_M_begin_bucket_index])
+ {
+ if (!_M_element_count)
+ _M_begin_bucket_index = _M_bucket_count;
+ else
+ {
+ ++_M_begin_bucket_index;
+ while (!_M_buckets[_M_begin_bucket_index])
+ ++_M_begin_bucket_index;
+ }
+ }
+
return __result;
}
@@ -1121,8 +1124,8 @@ namespace std
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
erase(const_iterator __first, const_iterator __last)
{
- while (__first != __last)
- __first = this->erase(__first);
+ while (__first != __last)
+ __first = this->erase(__first);
return iterator(__last._M_cur_node, __last._M_cur_bucket);
}
@@ -1137,6 +1140,7 @@ namespace std
{
_M_deallocate_nodes(_M_buckets, _M_bucket_count);
_M_element_count = 0;
+ _M_begin_bucket_index = _M_bucket_count;
}
template<typename _Key, typename _Value,
@@ -1165,6 +1169,7 @@ namespace std
_Node** __new_array = _M_allocate_buckets(__n);
__try
{
+ _M_begin_bucket_index = __n;
for (size_type __i = 0; __i < _M_bucket_count; ++__i)
while (_Node* __p = _M_buckets[__i])
{
@@ -1172,6 +1177,8 @@ namespace std
_M_buckets[__i] = __p->_M_next;
__p->_M_next = __new_array[__new_index];
__new_array[__new_index] = __p;
+ if (__new_index < _M_begin_bucket_index)
+ _M_begin_bucket_index = __new_index;
}
_M_deallocate_buckets(_M_buckets, _M_bucket_count);
_M_bucket_count = __n;
@@ -1187,6 +1194,7 @@ namespace std
_M_deallocate_buckets(__new_array, __n);
_M_deallocate_nodes(_M_buckets, _M_bucket_count);
_M_element_count = 0;
+ _M_begin_bucket_index = _M_bucket_count;
__throw_exception_again;
}
}