Support node_handle

This commit is contained in:
Daniel James
2017-02-27 03:59:02 +00:00
parent 9c4c3a754a
commit 21a24d6cd7
17 changed files with 2419 additions and 49 deletions
+231 -34
View File
@@ -3800,6 +3800,46 @@ struct table_impl : boost::unordered::detail::table<Types>
}
}
template <typename NodeType, typename InsertReturnType>
void move_insert_node_type(NodeType& np, InsertReturnType& result)
{
if (np) {
const_key_type& k = this->get_key(np.ptr_->value());
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
result.node = boost::move(np);
result.position = iterator(pos);
} else {
this->reserve_for_insert(this->size_ + 1);
result.position = iterator(this->add_node(np.ptr_, key_hash));
result.inserted = true;
np.ptr_ = node_pointer();
}
}
}
template <typename NodeType>
iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np)
{
if (!np) {
return iterator();
}
const_key_type& k = this->get_key(np.ptr_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
return iterator(hint.node_);
}
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (!pos) {
this->reserve_for_insert(this->size_ + 1);
pos = this->add_node(np.ptr_, key_hash);
np.ptr_ = node_pointer();
}
return iterator(pos);
}
////////////////////////////////////////////////////////////////////////
// Insert range methods
//
@@ -3876,39 +3916,87 @@ struct table_impl : boost::unordered::detail::table<Types>
} while (++i != j);
}
////////////////////////////////////////////////////////////////////////
// Extract
inline node_pointer extract_by_key(const_key_type& k)
{
if (!this->size_) {
return node_pointer();
}
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
if (!prev) {
return node_pointer();
}
node_pointer n = next_node(prev);
prev->next_ = n->next_;
--this->size_;
this->fix_bucket(bucket_index, prev);
n->next_ = link_pointer();
return n;
}
inline node_pointer extract_by_iterator(c_iterator i)
{
node_pointer n = i.node_;
BOOST_ASSERT(n);
std::size_t key_hash = n->hash_;
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
while (prev->next_ != n) {
prev = prev->next_;
}
prev->next_ = n->next_;
--this->size_;
this->fix_bucket(bucket_index, prev);
n->next_ = link_pointer();
return n;
}
////////////////////////////////////////////////////////////////////////
// Erase
//
// no throw
link_pointer find_previous_node(
const_key_type& k, std::size_t key_hash, std::size_t bucket_index)
{
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) {
return prev;
}
for (;;) {
if (!prev->next_) {
return link_pointer();
}
std::size_t node_hash = next_node(prev)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index) {
return link_pointer();
}
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(next_node(prev)->value()))) {
return prev;
}
prev = prev->next_;
}
}
std::size_t erase_key(const_key_type& k)
{
if (!this->size_)
return 0;
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
if (!prev)
return 0;
for (;;) {
if (!prev->next_)
return 0;
std::size_t node_hash = next_node(prev)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(next_node(prev)->value())))
break;
prev = prev->next_;
}
link_pointer end = next_node(prev)->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
return 1;
}
iterator erase(c_iterator r)
@@ -4459,6 +4547,45 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
this->add_node(a.release(), key_hash, position);
}
template <typename NodeType> iterator move_insert_node_type(NodeType& np)
{
iterator result;
if (np) {
const_key_type& k = this->get_key(np.ptr_->value());
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
result = iterator(this->add_node(np.ptr_, key_hash, pos));
np.ptr_ = node_pointer();
}
return result;
}
template <typename NodeType>
iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np)
{
iterator result;
if (np) {
const_key_type& k = this->get_key(np.ptr_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
this->reserve_for_insert(this->size_ + 1);
result = iterator(this->add_using_hint(np.ptr_, hint.node_));
} else {
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
result = iterator(this->add_node(np.ptr_, key_hash, pos));
}
np.ptr_ = node_pointer();
}
return result;
}
////////////////////////////////////////////////////////////////////////
// Insert range methods
@@ -4499,11 +4626,95 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
}
}
////////////////////////////////////////////////////////////////////////
// Extract
inline node_pointer extract_by_key(const_key_type& k)
{
if (!this->size_) {
return node_pointer();
}
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
if (!prev) {
return node_pointer();
}
node_pointer n = next_node(prev);
if (n->group_prev_ != n) {
node_pointer next = next_node(n);
next->group_prev_ = n->group_prev_;
n->group_prev_ = n;
}
prev->next_ = n->next_;
--this->size_;
this->fix_bucket(bucket_index, prev);
n->next_ = link_pointer();
return n;
}
inline node_pointer extract_by_iterator(c_iterator n)
{
node_pointer i = n.node_;
BOOST_ASSERT(i);
node_pointer j(next_node(i));
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
// Split the groups containing 'i' and 'j'.
// And get the pointer to the node before i while
// we're at it.
link_pointer prev = split_groups(i, j);
// If we don't have a 'prev' it means that i is at the
// beginning of a block, so search through the blocks in the
// same bucket.
if (!prev) {
prev = this->get_previous_start(bucket_index);
while (prev->next_ != i) {
prev = next_node(prev)->group_prev_;
}
}
prev->next_ = i->next_;
--this->size_;
this->fix_bucket(bucket_index, prev);
i->next_ = link_pointer();
return i;
}
////////////////////////////////////////////////////////////////////////
// Erase
//
// no throw
link_pointer find_previous_node(
const_key_type& k, std::size_t key_hash, std::size_t bucket_index)
{
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) {
return prev;
}
for (;;) {
if (!prev->next_) {
return link_pointer();
}
node_pointer first_node = next_node(prev);
std::size_t node_hash = first_node->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index) {
return link_pointer();
}
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(first_node->value()))) {
return prev;
}
prev = first_node->group_prev_;
}
}
std::size_t erase_key(const_key_type& k)
{
if (!this->size_)
@@ -4511,25 +4722,11 @@ struct grouped_table_impl : boost::unordered::detail::table<Types>
std::size_t key_hash = this->hash(k);
std::size_t bucket_index = this->hash_to_bucket(key_hash);
link_pointer prev = this->get_previous_start(bucket_index);
link_pointer prev = find_previous_node(k, key_hash, bucket_index);
if (!prev)
return 0;
node_pointer first_node;
for (;;) {
if (!prev->next_)
return 0;
first_node = next_node(prev);
std::size_t node_hash = first_node->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(first_node->value())))
break;
prev = first_node->group_prev_;
}
node_pointer first_node = next_node(prev);
link_pointer end = first_node->group_prev_->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);