mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-30 03:17:15 +02:00
Store bucket + whether first in group in node
Instead of the hash value.
This commit is contained in:
@ -1935,7 +1935,7 @@ struct l_iterator : public std::iterator<std::forward_iterator_tag,
|
|||||||
l_iterator& operator++()
|
l_iterator& operator++()
|
||||||
{
|
{
|
||||||
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
||||||
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) != bucket_)
|
if (ptr_ && ptr_->get_bucket() != bucket_)
|
||||||
ptr_ = node_pointer();
|
ptr_ = node_pointer();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -1999,7 +1999,7 @@ struct cl_iterator
|
|||||||
cl_iterator& operator++()
|
cl_iterator& operator++()
|
||||||
{
|
{
|
||||||
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
ptr_ = static_cast<node_pointer>(ptr_->next_);
|
||||||
if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) != bucket_)
|
if (ptr_ && ptr_->get_bucket() != bucket_)
|
||||||
ptr_ = node_pointer();
|
ptr_ = node_pointer();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -2706,7 +2706,11 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
|
|
||||||
static node_pointer next_for_find(link_pointer n)
|
static node_pointer next_for_find(link_pointer n)
|
||||||
{
|
{
|
||||||
return static_cast<node_pointer>(n->next_);
|
node_pointer n2 = static_cast<node_pointer>(n);
|
||||||
|
do {
|
||||||
|
n2 = next_node(n2);
|
||||||
|
} while (n2 && !n2->is_first_in_group());
|
||||||
|
return n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static link_pointer next_for_erase(link_pointer prev)
|
static link_pointer next_for_erase(link_pointer prev)
|
||||||
@ -2719,7 +2723,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
node_pointer n1 = n;
|
node_pointer n1 = n;
|
||||||
do {
|
do {
|
||||||
n1 = next_node(n1);
|
n1 = next_node(n1);
|
||||||
} while (n1 && this->key_eq()(get_key(n), get_key(n1)));
|
} while (n1 && !n1->is_first_in_group());
|
||||||
return n1;
|
return n1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2730,15 +2734,12 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
do {
|
do {
|
||||||
++x;
|
++x;
|
||||||
it = next_node(it);
|
it = next_node(it);
|
||||||
} while (it && this->key_eq()(get_key(n), get_key(it)));
|
} while (it && !it->is_first_in_group());
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t node_bucket(node_pointer n) const
|
std::size_t node_bucket(node_pointer n) const { return n->get_bucket(); }
|
||||||
{
|
|
||||||
return this->hash_to_bucket(n->hash_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bucket_allocator const& bucket_alloc() const { return allocators_.first(); }
|
bucket_allocator const& bucket_alloc() const { return allocators_.first(); }
|
||||||
|
|
||||||
@ -3282,15 +3283,17 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!prev->next_) {
|
node_pointer n = next_node(prev);
|
||||||
|
if (!n) {
|
||||||
return link_pointer();
|
return link_pointer();
|
||||||
|
} else if (n->is_first_in_group()) {
|
||||||
|
if (node_bucket(n) != bucket_index) {
|
||||||
|
return link_pointer();
|
||||||
|
} else if (this->key_eq()(k, this->get_key(n))) {
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (node_bucket(next_node(prev)) != bucket_index) {
|
prev = n;
|
||||||
return link_pointer();
|
|
||||||
} else if (this->key_eq()(k, this->get_key(next_node(prev)))) {
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
prev = next_for_erase(prev);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3308,7 +3311,11 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
return node_pointer();
|
return node_pointer();
|
||||||
}
|
}
|
||||||
node_pointer n = next_node(prev);
|
node_pointer n = next_node(prev);
|
||||||
prev->next_ = n->next_;
|
node_pointer n2 = next_node(n);
|
||||||
|
if (n2) {
|
||||||
|
n2->set_first_in_group();
|
||||||
|
}
|
||||||
|
prev->next_ = n2;
|
||||||
--this->size_;
|
--this->size_;
|
||||||
this->fix_bucket(bucket_index, prev);
|
this->fix_bucket(bucket_index, prev);
|
||||||
n->next_ = link_pointer();
|
n->next_ = link_pointer();
|
||||||
@ -3347,9 +3354,12 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
|
|
||||||
inline node_pointer add_node_unique(node_pointer n, std::size_t key_hash)
|
inline node_pointer add_node_unique(node_pointer n, std::size_t key_hash)
|
||||||
{
|
{
|
||||||
n->hash_ = key_hash;
|
std::size_t bucket = this->hash_to_bucket(key_hash);
|
||||||
|
bucket_pointer b = this->get_bucket(bucket);
|
||||||
|
|
||||||
bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
|
// TODO: Do this need to set_first_in_group ?
|
||||||
|
n->bucket_info_ = bucket;
|
||||||
|
n->set_first_in_group();
|
||||||
|
|
||||||
if (!b->next_) {
|
if (!b->next_) {
|
||||||
link_pointer start_node = this->get_previous_start();
|
link_pointer start_node = this->get_previous_start();
|
||||||
@ -3567,6 +3577,8 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
return iterator(pos);
|
return iterator(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Could speed this up a little by only considering
|
||||||
|
// the first node in a group.
|
||||||
template <typename Types2>
|
template <typename Types2>
|
||||||
void merge_unique(boost::unordered::detail::table<Types2>& other)
|
void merge_unique(boost::unordered::detail::table<Types2>& other)
|
||||||
{
|
{
|
||||||
@ -3588,8 +3600,10 @@ 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);
|
||||||
// other_table::split_groups(n, other_table::next_node(n));
|
|
||||||
prev->next_ = n->next_;
|
prev->next_ = n->next_;
|
||||||
|
if (prev->next_ && n->is_first_in_group()) {
|
||||||
|
next_node(prev)->set_first_in_group();
|
||||||
|
}
|
||||||
--other.size_;
|
--other.size_;
|
||||||
other.fix_bucket(other.node_bucket(n), prev);
|
other.fix_bucket(other.node_bucket(n), prev);
|
||||||
this->add_node_unique(n, key_hash);
|
this->add_node_unique(n, key_hash);
|
||||||
@ -3726,10 +3740,11 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
this->create_buckets(this->bucket_count_);
|
this->create_buckets(this->bucket_count_);
|
||||||
|
|
||||||
for (node_pointer n = src.begin(); n; n = next_node(n)) {
|
for (node_pointer n = src.begin(); n; n = next_node(n)) {
|
||||||
|
std::size_t key_hash = this->hash(this->get_key(n));
|
||||||
this->add_node_unique(
|
this->add_node_unique(
|
||||||
boost::unordered::detail::func::construct_node(
|
boost::unordered::detail::func::construct_node(
|
||||||
this->node_alloc(), n->value()),
|
this->node_alloc(), n->value()),
|
||||||
n->hash_);
|
key_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3739,10 +3754,11 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
this->create_buckets(this->bucket_count_);
|
this->create_buckets(this->bucket_count_);
|
||||||
|
|
||||||
for (node_pointer n = src.begin(); n; n = next_node(n)) {
|
for (node_pointer n = src.begin(); n; n = next_node(n)) {
|
||||||
|
std::size_t key_hash = this->hash(this->get_key(n));
|
||||||
this->add_node_unique(
|
this->add_node_unique(
|
||||||
boost::unordered::detail::func::construct_node(
|
boost::unordered::detail::func::construct_node(
|
||||||
this->node_alloc(), boost::move(n->value())),
|
this->node_alloc(), boost::move(n->value())),
|
||||||
n->hash_);
|
key_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3750,7 +3766,8 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
{
|
{
|
||||||
node_holder<node_allocator> holder(*this);
|
node_holder<node_allocator> holder(*this);
|
||||||
for (node_pointer n = src.begin(); n; n = next_node(n)) {
|
for (node_pointer n = src.begin(); n; n = next_node(n)) {
|
||||||
this->add_node_unique(holder.copy_of(n->value()), n->hash_);
|
std::size_t key_hash = this->hash(this->get_key(n));
|
||||||
|
this->add_node_unique(holder.copy_of(n->value()), key_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3758,7 +3775,8 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
{
|
{
|
||||||
node_holder<node_allocator> holder(*this);
|
node_holder<node_allocator> holder(*this);
|
||||||
for (node_pointer n = src.begin(); n; n = next_node(n)) {
|
for (node_pointer n = src.begin(); n; n = next_node(n)) {
|
||||||
this->add_node_unique(holder.move_copy_of(n->value()), n->hash_);
|
std::size_t key_hash = this->hash(this->get_key(n));
|
||||||
|
this->add_node_unique(holder.move_copy_of(n->value()), key_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3856,18 +3874,21 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
inline node_pointer add_node_equiv(
|
inline node_pointer add_node_equiv(
|
||||||
node_pointer n, std::size_t key_hash, node_pointer pos)
|
node_pointer n, std::size_t key_hash, node_pointer pos)
|
||||||
{
|
{
|
||||||
n->hash_ = key_hash;
|
std::size_t bucket = this->hash_to_bucket(key_hash);
|
||||||
|
n->bucket_info_ = bucket;
|
||||||
|
|
||||||
if (pos) {
|
if (pos) {
|
||||||
n->next_ = pos->next_;
|
n->next_ = pos->next_;
|
||||||
pos->next_ = n;
|
pos->next_ = n;
|
||||||
if (n->next_) {
|
if (n->next_) {
|
||||||
std::size_t next_bucket = this->node_bucket(next_node(n));
|
std::size_t next_bucket = this->node_bucket(next_node(n));
|
||||||
if (next_bucket != this->hash_to_bucket(key_hash)) {
|
if (next_bucket != bucket) {
|
||||||
this->get_bucket(next_bucket)->next_ = n;
|
this->get_bucket(next_bucket)->next_ = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
|
n->set_first_in_group();
|
||||||
|
bucket_pointer b = this->get_bucket(bucket);
|
||||||
|
|
||||||
if (!b->next_) {
|
if (!b->next_) {
|
||||||
link_pointer start_node = this->get_previous_start();
|
link_pointer start_node = this->get_previous_start();
|
||||||
@ -3891,7 +3912,8 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
|
|
||||||
inline node_pointer add_using_hint_equiv(node_pointer n, node_pointer hint)
|
inline node_pointer add_using_hint_equiv(node_pointer n, node_pointer hint)
|
||||||
{
|
{
|
||||||
n->hash_ = hint->hash_;
|
n->bucket_info_ = hint->bucket_info_;
|
||||||
|
n->reset_first_in_group();
|
||||||
n->next_ = hint->next_;
|
n->next_ = hint->next_;
|
||||||
hint->next_ = n;
|
hint->next_ = n;
|
||||||
if (n->next_ != hint && n->next_) {
|
if (n->next_ != hint && n->next_) {
|
||||||
@ -4031,20 +4053,16 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
BOOST_ASSERT(i);
|
BOOST_ASSERT(i);
|
||||||
node_pointer j(next_node(i));
|
node_pointer j(next_node(i));
|
||||||
std::size_t bucket_index = this->node_bucket(i);
|
std::size_t bucket_index = this->node_bucket(i);
|
||||||
// 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.
|
|
||||||
link_pointer prev = this->get_previous_start(bucket_index);
|
link_pointer prev = this->get_previous_start(bucket_index);
|
||||||
while (prev->next_ != i) {
|
while (prev->next_ != i) {
|
||||||
prev = next_for_erase(prev);
|
prev = next_for_erase(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev->next_ = i->next_;
|
prev->next_ = i->next_;
|
||||||
|
if (j && i->is_first_in_group()) {
|
||||||
|
j->set_first_in_group();
|
||||||
|
}
|
||||||
--this->size_;
|
--this->size_;
|
||||||
this->fix_bucket(bucket_index, prev);
|
this->fix_bucket(bucket_index, prev);
|
||||||
i->next_ = link_pointer();
|
i->next_ = link_pointer();
|
||||||
@ -4080,14 +4098,6 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
{
|
{
|
||||||
std::size_t bucket_index = this->node_bucket(i);
|
std::size_t bucket_index = this->node_bucket(i);
|
||||||
|
|
||||||
// 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.
|
|
||||||
link_pointer prev = this->get_previous_start(bucket_index);
|
link_pointer prev = this->get_previous_start(bucket_index);
|
||||||
while (prev->next_ != i) {
|
while (prev->next_ != i) {
|
||||||
prev = next_for_erase(prev);
|
prev = next_for_erase(prev);
|
||||||
@ -4095,10 +4105,16 @@ 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;
|
||||||
do {
|
do {
|
||||||
|
includes_first =
|
||||||
|
includes_first || next_node(prev)->is_first_in_group();
|
||||||
this->delete_node(prev);
|
this->delete_node(prev);
|
||||||
bucket_index = this->fix_bucket(bucket_index, prev);
|
bucket_index = this->fix_bucket(bucket_index, prev);
|
||||||
} while (prev->next_ != j);
|
} while (prev->next_ != j);
|
||||||
|
if (j && includes_first) {
|
||||||
|
j->set_first_in_group();
|
||||||
|
}
|
||||||
|
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
@ -4111,7 +4127,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
this->create_buckets(this->bucket_count_);
|
this->create_buckets(this->bucket_count_);
|
||||||
|
|
||||||
for (node_pointer n = src.begin(); n;) {
|
for (node_pointer n = src.begin(); n;) {
|
||||||
std::size_t key_hash = n->hash_;
|
std::size_t key_hash = this->hash(this->get_key(n));
|
||||||
node_pointer group_end(next_group(n));
|
node_pointer group_end(next_group(n));
|
||||||
node_pointer pos = this->add_node_equiv(
|
node_pointer pos = this->add_node_equiv(
|
||||||
boost::unordered::detail::func::construct_node(
|
boost::unordered::detail::func::construct_node(
|
||||||
@ -4131,7 +4147,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
this->create_buckets(this->bucket_count_);
|
this->create_buckets(this->bucket_count_);
|
||||||
|
|
||||||
for (node_pointer n = src.begin(); n;) {
|
for (node_pointer n = src.begin(); n;) {
|
||||||
std::size_t key_hash = n->hash_;
|
std::size_t key_hash = this->hash(this->get_key(n));
|
||||||
node_pointer group_end(next_group(n));
|
node_pointer group_end(next_group(n));
|
||||||
node_pointer pos = this->add_node_equiv(
|
node_pointer pos = this->add_node_equiv(
|
||||||
boost::unordered::detail::func::construct_node(
|
boost::unordered::detail::func::construct_node(
|
||||||
@ -4150,7 +4166,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
{
|
{
|
||||||
node_holder<node_allocator> holder(*this);
|
node_holder<node_allocator> holder(*this);
|
||||||
for (node_pointer n = src.begin(); n;) {
|
for (node_pointer n = src.begin(); n;) {
|
||||||
std::size_t key_hash = n->hash_;
|
std::size_t key_hash = this->hash(this->get_key(n));
|
||||||
node_pointer group_end(next_group(n));
|
node_pointer group_end(next_group(n));
|
||||||
node_pointer pos = this->add_node_equiv(
|
node_pointer pos = this->add_node_equiv(
|
||||||
holder.copy_of(n->value()), key_hash, node_pointer());
|
holder.copy_of(n->value()), key_hash, node_pointer());
|
||||||
@ -4164,7 +4180,7 @@ struct table : boost::unordered::detail::functions<typename Types::hasher,
|
|||||||
{
|
{
|
||||||
node_holder<node_allocator> holder(*this);
|
node_holder<node_allocator> holder(*this);
|
||||||
for (node_pointer n = src.begin(); n;) {
|
for (node_pointer n = src.begin(); n;) {
|
||||||
std::size_t key_hash = n->hash_;
|
std::size_t key_hash = this->hash(this->get_key(n));
|
||||||
node_pointer group_end(next_group(n));
|
node_pointer group_end(next_group(n));
|
||||||
node_pointer pos = this->add_node_equiv(
|
node_pointer pos = this->add_node_equiv(
|
||||||
holder.move_copy_of(n->value()), key_hash, node_pointer());
|
holder.move_copy_of(n->value()), key_hash, node_pointer());
|
||||||
@ -4223,33 +4239,43 @@ inline void table<Types>::rehash_impl(std::size_t num_buckets)
|
|||||||
|
|
||||||
this->create_buckets(num_buckets);
|
this->create_buckets(num_buckets);
|
||||||
link_pointer prev = this->get_previous_start();
|
link_pointer prev = this->get_previous_start();
|
||||||
while (prev->next_) {
|
BOOST_TRY
|
||||||
// Group together all nodes with equal hash value, this may
|
{
|
||||||
// include nodes with different keys, but that's okay because
|
while (prev->next_) {
|
||||||
// they will end up in the same bucket.
|
node_pointer n = next_node(prev);
|
||||||
//
|
std::size_t key_hash = this->hash(this->get_key(n));
|
||||||
// TODO: Don't do this for unique keys?
|
std::size_t bucket_index = this->hash_to_bucket(key_hash);
|
||||||
node_pointer group_last = next_node(prev);
|
|
||||||
std::size_t hash = group_last->hash_;
|
|
||||||
for (;;) {
|
|
||||||
node_pointer next = next_node(group_last);
|
|
||||||
if (!next || next->hash_ != hash) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
group_last = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
bucket_pointer b = this->get_bucket(this->node_bucket(group_last));
|
n->bucket_info_ = bucket_index;
|
||||||
if (!b->next_) {
|
n->set_first_in_group();
|
||||||
b->next_ = prev;
|
|
||||||
prev = group_last;
|
// Iterator through the rest of the group of equal nodes,
|
||||||
} else {
|
// setting the bucket.
|
||||||
link_pointer next = group_last->next_;
|
for (;;) {
|
||||||
group_last->next_ = b->next_->next_;
|
node_pointer next = next_node(n);
|
||||||
b->next_->next_ = prev->next_;
|
if (!next || next->is_first_in_group()) {
|
||||||
prev->next_ = next;
|
break;
|
||||||
|
}
|
||||||
|
n = next;
|
||||||
|
n->bucket_info_ = bucket_index;
|
||||||
|
// n->reset_first_in_group();
|
||||||
|
}
|
||||||
|
|
||||||
|
// n is now the last node in the group
|
||||||
|
bucket_pointer b = this->get_bucket(bucket_index);
|
||||||
|
if (!b->next_) {
|
||||||
|
b->next_ = prev;
|
||||||
|
prev = n;
|
||||||
|
} else {
|
||||||
|
link_pointer next = n->next_;
|
||||||
|
n->next_ = b->next_->next_;
|
||||||
|
b->next_->next_ = prev->next_;
|
||||||
|
prev->next_ = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BOOST_CATCH(...) { delete_nodes(prev, link_pointer()); }
|
||||||
|
BOOST_CATCH_END
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BOOST_MSVC)
|
#if defined(BOOST_MSVC)
|
||||||
@ -4414,12 +4440,32 @@ struct node : boost::unordered::detail::value_base<T>
|
|||||||
bucket_allocator>::pointer bucket_pointer;
|
bucket_allocator>::pointer bucket_pointer;
|
||||||
|
|
||||||
link_pointer next_;
|
link_pointer next_;
|
||||||
std::size_t hash_;
|
std::size_t bucket_info_;
|
||||||
|
|
||||||
node() : next_(), hash_(0) {}
|
node() : next_(), bucket_info_(0) {}
|
||||||
|
|
||||||
void init(node_pointer) {}
|
void init(node_pointer) {}
|
||||||
|
|
||||||
|
std::size_t get_bucket() const
|
||||||
|
{
|
||||||
|
return bucket_info_ & ((std::size_t)-1 >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t is_first_in_group() const
|
||||||
|
{
|
||||||
|
return bucket_info_ & ~((std::size_t)-1 >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_first_in_group()
|
||||||
|
{
|
||||||
|
bucket_info_ = bucket_info_ | ~((std::size_t)-1 >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_first_in_group()
|
||||||
|
{
|
||||||
|
bucket_info_ = bucket_info_ & ((std::size_t)-1 >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
node& operator=(node const&);
|
node& operator=(node const&);
|
||||||
};
|
};
|
||||||
@ -4432,10 +4478,10 @@ template <typename T> struct ptr_node : boost::unordered::detail::ptr_bucket
|
|||||||
typedef ptr_bucket* link_pointer;
|
typedef ptr_bucket* link_pointer;
|
||||||
typedef ptr_bucket* bucket_pointer;
|
typedef ptr_bucket* bucket_pointer;
|
||||||
|
|
||||||
std::size_t hash_;
|
std::size_t bucket_info_;
|
||||||
boost::unordered::detail::value_base<T> value_base_;
|
boost::unordered::detail::value_base<T> value_base_;
|
||||||
|
|
||||||
ptr_node() : bucket_base(), hash_(0) {}
|
ptr_node() : bucket_base(), bucket_info_(0) {}
|
||||||
|
|
||||||
void init(node_pointer) {}
|
void init(node_pointer) {}
|
||||||
|
|
||||||
@ -4443,6 +4489,26 @@ template <typename T> struct ptr_node : boost::unordered::detail::ptr_bucket
|
|||||||
value_type& value() { return value_base_.value(); }
|
value_type& value() { return value_base_.value(); }
|
||||||
value_type* value_ptr() { return value_base_.value_ptr(); }
|
value_type* value_ptr() { return value_base_.value_ptr(); }
|
||||||
|
|
||||||
|
std::size_t get_bucket() const
|
||||||
|
{
|
||||||
|
return bucket_info_ & ((std::size_t)-1 >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t is_first_in_group() const
|
||||||
|
{
|
||||||
|
return bucket_info_ & ~((std::size_t)-1 >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_first_in_group()
|
||||||
|
{
|
||||||
|
bucket_info_ = bucket_info_ | ~((std::size_t)-1 >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_first_in_group()
|
||||||
|
{
|
||||||
|
bucket_info_ = bucket_info_ & ((std::size_t)-1 >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ptr_node& operator=(ptr_node const&);
|
ptr_node& operator=(ptr_node const&);
|
||||||
};
|
};
|
||||||
|
@ -63,20 +63,28 @@ template <class X> void check_equivalent_keys(X const& x1)
|
|||||||
BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
|
BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
|
||||||
BOOST_DEDUCED_TYPENAME X::const_local_iterator lit = x1.begin(bucket),
|
BOOST_DEDUCED_TYPENAME X::const_local_iterator lit = x1.begin(bucket),
|
||||||
lend = x1.end(bucket);
|
lend = x1.end(bucket);
|
||||||
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit)
|
|
||||||
continue;
|
unsigned int count_checked = 0;
|
||||||
if (lit == lend)
|
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) {
|
||||||
|
++count_checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lit == lend) {
|
||||||
BOOST_ERROR("Unable to find element with a local_iterator");
|
BOOST_ERROR("Unable to find element with a local_iterator");
|
||||||
unsigned int count2 = 0;
|
std::cerr << "Checked: " << count_checked << " elements"
|
||||||
for (; lit != lend && eq(get_key<X>(*lit), key); ++lit)
|
<< std::endl;
|
||||||
++count2;
|
} else {
|
||||||
if (count != count2)
|
unsigned int count2 = 0;
|
||||||
BOOST_ERROR("Element count doesn't match local_iterator.");
|
for (; lit != lend && eq(get_key<X>(*lit), key); ++lit)
|
||||||
for (; lit != lend; ++lit) {
|
++count2;
|
||||||
if (eq(get_key<X>(*lit), key)) {
|
if (count != count2)
|
||||||
BOOST_ERROR("Non-adjacent element with equivalent key "
|
BOOST_ERROR("Element count doesn't match local_iterator.");
|
||||||
"in bucket.");
|
for (; lit != lend; ++lit) {
|
||||||
break;
|
if (eq(get_key<X>(*lit), key)) {
|
||||||
|
BOOST_ERROR("Non-adjacent element with equivalent key "
|
||||||
|
"in bucket.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user