diff options
author | Evan Brown <ezb@google.com> | 2022-05-04 11:53:25 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-05-04 11:54:24 -0700 |
commit | 02934b492135d7c9c40fecf8e7873380b46c2223 (patch) | |
tree | 7c0fd00bc694da6082bc6f0b8b051db4afd3b8a7 /absl/container | |
parent | 981e2c888094c26f54adce260e05fd29e07e5fc8 (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.h | 85 |
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); } |