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
This commit is contained in:
parent
6208468d29
commit
18dbb85903
|
@ -1,3 +1,18 @@
|
|||
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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue