Delete nodes directly instead of through previous node

This commit is contained in:
Daniel James
2017-05-03 23:37:42 +01:00
parent 77bd45b1fa
commit d49d0e90a8

View File

@ -3013,16 +3013,12 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
~table() { delete_buckets(); } ~table() { delete_buckets(); }
void delete_node(link_pointer prev) void destroy_node(node_pointer n)
{ {
node_pointer n = next_node(prev);
prev->next_ = n->next_;
BOOST_UNORDERED_CALL_DESTROY( BOOST_UNORDERED_CALL_DESTROY(
node_allocator_traits, node_alloc(), n->value_ptr()); node_allocator_traits, node_alloc(), n->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*n)); boost::unordered::detail::func::destroy(boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1); node_allocator_traits::deallocate(node_alloc(), n, 1);
--size_;
} }
std::size_t delete_nodes(link_pointer prev, node_pointer end) std::size_t delete_nodes(link_pointer prev, node_pointer end)
@ -3031,11 +3027,16 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
std::size_t count = 0; std::size_t count = 0;
node_pointer n = next_node(prev);
prev->next_ = end;
do { do {
delete_node(prev); node_pointer next = next_node(n);
destroy_node(n);
n = next;
++count; ++count;
} while (prev->next_ != end); } while (n != end);
size_ -= count;
return count; return count;
} }
@ -3072,12 +3073,14 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Fix buckets after delete // Fix buckets after delete/extract
// //
// (prev,next) should mark an open range of nodes in a single bucket which
// have either been unlinked, or are about to be.
std::size_t fix_bucket(std::size_t bucket_index, link_pointer prev) std::size_t fix_bucket(
std::size_t bucket_index, link_pointer prev, node_pointer next)
{ {
node_pointer next = next_node(prev);
std::size_t bucket_index2 = bucket_index; std::size_t bucket_index2 = bucket_index;
if (next) { if (next) {
@ -3305,7 +3308,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
} }
prev->next_ = n2; prev->next_ = n2;
--this->size_; --this->size_;
this->fix_bucket(bucket_index, prev); this->fix_bucket(bucket_index, prev, n2);
n->next_ = link_pointer(); n->next_ = link_pointer();
return n; return n;
@ -3586,12 +3589,14 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
prev = n; prev = n;
} else { } else {
this->reserve_for_insert(this->size_ + 1); this->reserve_for_insert(this->size_ + 1);
prev->next_ = n->next_; node_pointer n2 = next_node(n);
if (prev->next_ && n->is_first_in_group()) { prev->next_ = n2;
next_node(prev)->set_first_in_group(); if (n2 && n->is_first_in_group()) {
n2->set_first_in_group();
} }
--other.size_; --other.size_;
other.fix_bucket(other.node_bucket(n), prev); other.fix_bucket(
other.node_bucket(n), prev, n2);
this->add_node_unique(n, key_hash); this->add_node_unique(n, key_hash);
} }
} }
@ -3675,9 +3680,10 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
while (prev->next_ != n) { while (prev->next_ != n) {
prev = prev->next_; prev = prev->next_;
} }
prev->next_ = n->next_; node_pointer n2 = next_node(n);
prev->next_ = n2;
--this->size_; --this->size_;
this->fix_bucket(bucket_index, prev); this->fix_bucket(bucket_index, prev, n2);
n->next_ = link_pointer(); n->next_ = link_pointer();
return n; return n;
} }
@ -3698,7 +3704,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
return 0; return 0;
node_pointer end = next_node(next_node(prev)); node_pointer end = next_node(next_node(prev));
this->delete_nodes(prev, end); this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev); this->fix_bucket(bucket_index, prev, end);
return 1; return 1;
} }
@ -3712,10 +3718,14 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
prev = prev->next_; prev = prev->next_;
// Delete the nodes. // Delete the nodes.
prev->next_ = j;
do { do {
this->delete_node(prev); node_pointer next = next_node(i);
bucket_index = this->fix_bucket(bucket_index, prev); destroy_node(i);
} while (prev->next_ != j); --size_;
bucket_index = this->fix_bucket(bucket_index, prev, next);
i = next;
} while (i != j);
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -4046,12 +4056,12 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
prev = next_node(prev); prev = next_node(prev);
} }
prev->next_ = i->next_; prev->next_ = j;
if (j && i->is_first_in_group()) { if (j && i->is_first_in_group()) {
j->set_first_in_group(); j->set_first_in_group();
} }
--this->size_; --this->size_;
this->fix_bucket(bucket_index, prev); this->fix_bucket(bucket_index, prev, j);
i->next_ = link_pointer(); i->next_ = link_pointer();
return i; return i;
@ -4077,7 +4087,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
node_pointer end = next_group(first_node); node_pointer end = next_group(first_node);
std::size_t deleted_count = this->delete_nodes(prev, end); std::size_t deleted_count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev); this->fix_bucket(bucket_index, prev, end);
return deleted_count; return deleted_count;
} }
@ -4093,12 +4103,15 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
// Delete the nodes. // Delete the nodes.
// Is it inefficient to call fix_bucket for every node? // Is it inefficient to call fix_bucket for every node?
bool includes_first = false; bool includes_first = false;
prev->next_ = j;
do { do {
includes_first = includes_first = includes_first || i->is_first_in_group();
includes_first || next_node(prev)->is_first_in_group(); node_pointer next = next_node(i);
this->delete_node(prev); destroy_node(i);
bucket_index = this->fix_bucket(bucket_index, prev); --size_;
} while (prev->next_ != j); bucket_index = this->fix_bucket(bucket_index, prev, next);
i = next;
} while (i != j);
if (j && includes_first) { if (j && includes_first) {
j->set_first_in_group(); j->set_first_in_group();
} }