From 116ee0fed75c1d032604f3b675e7e44e10d124b4 Mon Sep 17 00:00:00 2001 From: Evan Brown Date: Tue, 7 Nov 2023 08:50:48 -0800 Subject: Add control()/slot() functions to iterator/const_iterator. This allows for avoiding e.g. it.inner_.slot_ on const iterators. Also, refactor HashtableDebugAccess::AllocatedByteSize to use regular iteration instead of looking directly at control/slot_array of the table in order to support small object optimization. PiperOrigin-RevId: 580194253 Change-Id: I64cd69287834ee5c7a8daf867c532258806bfb7b --- absl/container/internal/raw_hash_set.h | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'absl/container/internal/raw_hash_set.h') diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index f702f6ad..2a2b1c4e 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -1746,6 +1746,9 @@ class raw_hash_set { if (ABSL_PREDICT_FALSE(*ctrl_ == ctrl_t::kSentinel)) ctrl_ = nullptr; } + ctrl_t* control() const { return ctrl_; } + slot_type* slot() const { return slot_; } + // We use EmptyGroup() for default-constructed iterators so that they can // be distinguished from end iterators, which have nullptr ctrl_. ctrl_t* ctrl_ = EmptyGroup(); @@ -1758,6 +1761,9 @@ class raw_hash_set { class const_iterator { friend class raw_hash_set; + template + friend struct absl::container_internal::hashtable_debug_internal:: + HashtableDebugAccess; public: using iterator_category = typename iterator::iterator_category; @@ -1791,6 +1797,8 @@ class raw_hash_set { const GenerationType* gen) : inner_(const_cast(ctrl), const_cast(slot), gen) { } + ctrl_t* control() const { return inner_.control(); } + slot_type* slot() const { return inner_.slot(); } iterator inner_; }; @@ -2257,8 +2265,8 @@ class raw_hash_set { // This overload is necessary because otherwise erase(const K&) would be // a better match if non-const iterator is passed as an argument. void erase(iterator it) { - AssertIsFull(it.ctrl_, it.generation(), it.generation_ptr(), "erase()"); - destroy(it.slot_); + AssertIsFull(it.control(), it.generation(), it.generation_ptr(), "erase()"); + destroy(it.slot()); erase_meta_only(it); } @@ -2289,8 +2297,8 @@ class raw_hash_set { assert(this != &src); for (auto it = src.begin(), e = src.end(); it != e;) { auto next = std::next(it); - if (PolicyTraits::apply(InsertSlot{*this, std::move(*it.slot_)}, - PolicyTraits::element(it.slot_)) + if (PolicyTraits::apply(InsertSlot{*this, std::move(*it.slot())}, + PolicyTraits::element(it.slot())) .second) { src.erase_meta_only(it); } @@ -2304,10 +2312,9 @@ class raw_hash_set { } node_type extract(const_iterator position) { - AssertIsFull(position.inner_.ctrl_, position.inner_.generation(), + AssertIsFull(position.control(), position.inner_.generation(), position.inner_.generation_ptr(), "extract()"); - auto node = - CommonAccess::Transfer(alloc_ref(), position.inner_.slot_); + auto node = CommonAccess::Transfer(alloc_ref(), position.slot()); erase_meta_only(position); return node; } @@ -2612,7 +2619,7 @@ class raw_hash_set { // This merely updates the pertinent control byte. This can be used in // conjunction with Policy::transfer to move the object to another place. void erase_meta_only(const_iterator it) { - EraseMetaOnly(common(), it.inner_.ctrl_, sizeof(slot_type)); + EraseMetaOnly(common(), it.control(), sizeof(slot_type)); } // Allocates a backing array for `self` and initializes its control bytes. @@ -2758,8 +2765,8 @@ class raw_hash_set { if (size == 0) return *this; reserve(size); for (iterator it = that.begin(); it != that.end(); ++it) { - insert(std::move(PolicyTraits::element(it.slot_))); - that.destroy(it.slot_); + insert(std::move(PolicyTraits::element(it.slot()))); + that.destroy(it.slot()); } that.dealloc(); that.common() = CommonFields{}; @@ -3006,11 +3013,8 @@ struct HashtableDebugAccess> { if (per_slot != ~size_t{}) { m += per_slot * c.size(); } else { - const ctrl_t* ctrl = c.control(); - for (size_t i = 0; i != capacity; ++i) { - if (container_internal::IsFull(ctrl[i])) { - m += Traits::space_used(c.slot_array() + i); - } + for (auto it = c.begin(); it != c.end(); ++it) { + m += Traits::space_used(it.slot()); } } return m; -- cgit v1.2.3