summaryrefslogtreecommitdiff
path: root/absl/container
diff options
context:
space:
mode:
authorGravatar Evan Brown <ezb@google.com>2022-05-04 11:53:25 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2022-05-04 11:54:24 -0700
commit02934b492135d7c9c40fecf8e7873380b46c2223 (patch)
tree7c0fd00bc694da6082bc6f0b8b051db4afd3b8a7 /absl/container
parent981e2c888094c26f54adce260e05fd29e07e5fc8 (diff)
In btree, move rightmost_ into the CompressedTuple instead of root_.
We also add accessors for rightmost()/mutable_rightmost(). PiperOrigin-RevId: 446515231 Change-Id: I4b8cb46f4bd209a0f51dcdcb96c9479e480828a3
Diffstat (limited to 'absl/container')
-rw-r--r--absl/container/internal/btree.h85
1 files changed, 45 insertions, 40 deletions
diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h
index da2abcb9..cb39b161 100644
--- a/absl/container/internal/btree.h
+++ b/absl/container/internal/btree.h
@@ -191,8 +191,8 @@ struct key_compare_adapter {
// Inherit from checked_compare_base to support function pointers and also
// keep empty-base-optimization (EBO) support for classes.
// Note: we can't use CompressedTuple here because that would interfere
- // with the EBO for `btree::root_`. `btree::root_` is itself a CompressedTuple
- // and nested `CompressedTuple`s don't support EBO.
+ // with the EBO for `btree::rightmost_`. `btree::rightmost_` is itself a
+ // CompressedTuple and nested `CompressedTuple`s don't support EBO.
// TODO(b/214288561): use CompressedTuple instead once it supports EBO for
// nested `CompressedTuple`s.
struct checked_compare : checked_compare_base<Compare> {
@@ -1329,7 +1329,7 @@ class btree {
public:
btree(const key_compare &comp, const allocator_type &alloc)
- : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
+ : root_(EmptyNode()), rightmost_(comp, alloc, EmptyNode()), size_(0) {}
btree(const btree &other) : btree(other, other.allocator()) {}
btree(const btree &other, const allocator_type &alloc)
@@ -1337,10 +1337,10 @@ class btree {
copy_or_move_values_in_order(other);
}
btree(btree &&other) noexcept
- : root_(std::move(other.root_)),
- rightmost_(absl::exchange(other.rightmost_, EmptyNode())),
+ : root_(absl::exchange(other.root_, EmptyNode())),
+ rightmost_(std::move(other.rightmost_)),
size_(absl::exchange(other.size_, 0)) {
- other.mutable_root() = EmptyNode();
+ other.mutable_rightmost() = EmptyNode();
}
btree(btree &&other, const allocator_type &alloc)
: btree(other.key_comp(), alloc) {
@@ -1365,9 +1365,9 @@ class btree {
iterator begin() { return iterator(leftmost()); }
const_iterator begin() const { return const_iterator(leftmost()); }
- iterator end() { return iterator(rightmost_, rightmost_->finish()); }
+ iterator end() { return iterator(rightmost(), rightmost()->finish()); }
const_iterator end() const {
- return const_iterator(rightmost_, rightmost_->finish());
+ return const_iterator(rightmost(), rightmost()->finish());
}
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {
@@ -1493,7 +1493,7 @@ class btree {
void swap(btree &other);
const key_compare &key_comp() const noexcept {
- return root_.template get<0>();
+ return rightmost_.template get<0>();
}
template <typename K1, typename K2>
bool compare_keys(const K1 &a, const K2 &b) const {
@@ -1587,10 +1587,17 @@ class btree {
friend struct btree_access;
// Internal accessor routines.
- node_type *root() { return root_.template get<2>(); }
- const node_type *root() const { return root_.template get<2>(); }
- node_type *&mutable_root() noexcept { return root_.template get<2>(); }
- key_compare *mutable_key_comp() noexcept { return &root_.template get<0>(); }
+ node_type *root() { return root_; }
+ const node_type *root() const { return root_; }
+ node_type *&mutable_root() noexcept { return root_; }
+ node_type *rightmost() { return rightmost_.template get<2>(); }
+ const node_type *rightmost() const { return rightmost_.template get<2>(); }
+ node_type *&mutable_rightmost() noexcept {
+ return rightmost_.template get<2>();
+ }
+ key_compare *mutable_key_comp() noexcept {
+ return &rightmost_.template get<0>();
+ }
// The leftmost node is stored as the parent of the root node.
node_type *leftmost() { return root()->parent(); }
@@ -1598,10 +1605,10 @@ class btree {
// Allocator routines.
allocator_type *mutable_allocator() noexcept {
- return &root_.template get<1>();
+ return &rightmost_.template get<1>();
}
const allocator_type &allocator() const noexcept {
- return root_.template get<1>();
+ return rightmost_.template get<1>();
}
// Allocates a correctly aligned node of at least size bytes using the
@@ -1709,15 +1716,14 @@ class btree {
return res;
}
- // We use compressed tuple in order to save space because key_compare and
- // allocator_type are usually empty.
- absl::container_internal::CompressedTuple<key_compare, allocator_type,
- node_type *>
- root_;
+ node_type *root_;
// A pointer to the rightmost node. Note that the leftmost node is stored as
- // the root's parent.
- node_type *rightmost_;
+ // the root's parent. We use compressed tuple in order to save space because
+ // key_compare and allocator_type are usually empty.
+ absl::container_internal::CompressedTuple<key_compare, allocator_type,
+ node_type *>
+ rightmost_;
// Number of values.
size_type size_;
@@ -2141,7 +2147,7 @@ template <typename K, typename... Args>
auto btree<P>::insert_unique(const K &key, Args &&... args)
-> std::pair<iterator, bool> {
if (empty()) {
- mutable_root() = rightmost_ = new_leaf_root_node(1);
+ mutable_root() = mutable_rightmost() = new_leaf_root_node(1);
}
SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
@@ -2208,7 +2214,7 @@ template <typename P>
template <typename ValueType>
auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator {
if (empty()) {
- mutable_root() = rightmost_ = new_leaf_root_node(1);
+ mutable_root() = mutable_rightmost() = new_leaf_root_node(1);
}
iterator iter = internal_upper_bound(key);
@@ -2272,15 +2278,15 @@ auto btree<P>::operator=(btree &&other) noexcept -> btree & {
using std::swap;
if (absl::allocator_traits<
allocator_type>::propagate_on_container_copy_assignment::value) {
- // Note: `root_` also contains the allocator and the key comparator.
swap(root_, other.root_);
+ // Note: `rightmost_` also contains the allocator and the key comparator.
swap(rightmost_, other.rightmost_);
swap(size_, other.size_);
} else {
if (allocator() == other.allocator()) {
swap(mutable_root(), other.mutable_root());
swap(*mutable_key_comp(), *other.mutable_key_comp());
- swap(rightmost_, other.rightmost_);
+ swap(mutable_rightmost(), other.mutable_rightmost());
swap(size_, other.size_);
} else {
// We aren't allowed to propagate the allocator and the allocator is
@@ -2422,8 +2428,7 @@ void btree<P>::clear() {
if (!empty()) {
node_type::clear_and_delete(root(), mutable_allocator());
}
- mutable_root() = EmptyNode();
- rightmost_ = EmptyNode();
+ mutable_root() = mutable_rightmost() = EmptyNode();
size_ = 0;
}
@@ -2432,15 +2437,15 @@ void btree<P>::swap(btree &other) {
using std::swap;
if (absl::allocator_traits<
allocator_type>::propagate_on_container_swap::value) {
- // Note: `root_` also contains the allocator and the key comparator.
- swap(root_, other.root_);
+ // Note: `rightmost_` also contains the allocator and the key comparator.
+ swap(rightmost_, other.rightmost_);
} else {
// It's undefined behavior if the allocators are unequal here.
assert(allocator() == other.allocator());
- swap(mutable_root(), other.mutable_root());
+ swap(mutable_rightmost(), other.mutable_rightmost());
swap(*mutable_key_comp(), *other.mutable_key_comp());
}
- swap(rightmost_, other.rightmost_);
+ swap(mutable_root(), other.mutable_root());
swap(size_, other.size_);
}
@@ -2448,12 +2453,12 @@ template <typename P>
void btree<P>::verify() const {
assert(root() != nullptr);
assert(leftmost() != nullptr);
- assert(rightmost_ != nullptr);
+ assert(rightmost() != nullptr);
assert(empty() || size() == internal_verify(root(), nullptr, nullptr));
assert(leftmost() == (++const_iterator(root(), -1)).node_);
- assert(rightmost_ == (--const_iterator(root(), root()->finish())).node_);
+ assert(rightmost() == (--const_iterator(root(), root()->finish())).node_);
assert(leftmost()->is_leaf());
- assert(rightmost_->is_leaf());
+ assert(rightmost()->is_leaf());
}
template <typename P>
@@ -2539,7 +2544,7 @@ void btree<P>::rebalance_or_split(iterator *iter) {
mutable_root() = parent;
// If the former root was a leaf node, then it's now the rightmost node.
assert(parent->start_child()->is_internal() ||
- parent->start_child() == rightmost_);
+ parent->start_child() == rightmost());
}
// Split the node.
@@ -2547,7 +2552,7 @@ void btree<P>::rebalance_or_split(iterator *iter) {
if (node->is_leaf()) {
split_node = new_leaf_node(parent);
node->split(insert_position, split_node, mutable_allocator());
- if (rightmost_ == node) rightmost_ = split_node;
+ if (rightmost() == node) mutable_rightmost() = split_node;
} else {
split_node = new_internal_node(parent);
node->split(insert_position, split_node, mutable_allocator());
@@ -2562,7 +2567,7 @@ void btree<P>::rebalance_or_split(iterator *iter) {
template <typename P>
void btree<P>::merge_nodes(node_type *left, node_type *right) {
left->merge(right, mutable_allocator());
- if (rightmost_ == right) rightmost_ = left;
+ if (rightmost() == right) mutable_rightmost() = left;
}
template <typename P>
@@ -2627,7 +2632,7 @@ void btree<P>::try_shrink() {
// Deleted the last item on the root node, shrink the height of the tree.
if (orig_root->is_leaf()) {
assert(size() == 0);
- mutable_root() = rightmost_ = EmptyNode();
+ mutable_root() = mutable_rightmost() = EmptyNode();
} else {
node_type *child = orig_root->start_child();
child->make_root();
@@ -2681,7 +2686,7 @@ inline auto btree<P>::internal_emplace(iterator iter, Args &&... args)
old_root->set_finish(old_root->start());
new_root->set_generation(old_root->generation());
node_type::clear_and_delete(old_root, alloc);
- mutable_root() = rightmost_ = new_root;
+ mutable_root() = mutable_rightmost() = new_root;
} else {
rebalance_or_split(&iter);
}