From 249b5674a9fbdb23a34dc4487b80243f8af7e045 Mon Sep 17 00:00:00 2001 From: Grey Golla Date: Thu, 11 Apr 2024 17:36:42 -0700 Subject: [PATCH] Implement efficient clearing of the Hashtable Instead of iterating over the linked list (also requires hash lookups) and erasing one by one, just reset the backing linked list and value storage, then 0 out the bucket array. --- .../fixed_doubly_linked_list.hpp | 27 +++++++++++++++---- .../fixed_robinhood_hashtable.hpp | 9 ++++++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/include/fixed_containers/fixed_doubly_linked_list.hpp b/include/fixed_containers/fixed_doubly_linked_list.hpp index 11b6fa2b..2ab09253 100644 --- a/include/fixed_containers/fixed_doubly_linked_list.hpp +++ b/include/fixed_containers/fixed_doubly_linked_list.hpp @@ -18,6 +18,7 @@ struct LinkedListIndices template class FixedDoublyLinkedListBase { +protected: static_assert(MAXIMUM_SIZE + 1 <= std::numeric_limits::max(), "must be able to index MAXIMUM_SIZE+1 elements with IndexType"); using StorageType = FixedIndexBasedPoolStorage; @@ -52,11 +53,6 @@ class FixedDoublyLinkedListBase } [[nodiscard]] constexpr bool full() const noexcept { return storage().full(); } - constexpr void clear() noexcept - { - delete_range_and_return_next_index(front_index(), MAXIMUM_SIZE); - } - constexpr const T& at(const IndexType i) const { return storage().at(i); } constexpr T& at(const IndexType i) { return storage().at(i); } @@ -227,6 +223,11 @@ class FixedDoublyLinkedList : public FixedDoublyLinkedListBasedelete_range_and_return_next_index(this->front_index(), MAXIMUM_SIZE); + } + constexpr ~FixedDoublyLinkedList() noexcept { this->clear(); } }; @@ -240,6 +241,22 @@ class FixedDoublyLinkedList // clang-format off constexpr FixedDoublyLinkedList() noexcept : Base() { } // clang-format on + + constexpr void clear() noexcept + { + // Instead of iterating over the elements of the linked list (slow), just reset the backing + // storage + this->IMPLEMENTATION_DETAIL_DO_NOT_USE_storage_ = std::move(typename Base::StorageType{}); + + // And reset the start/end sentinel to point at itself. + // The remaining links of the linked list will be overwritten as elements are allocated, so + // we don't have to reset the entire chain + this->next_of(MAXIMUM_SIZE) = MAXIMUM_SIZE; + this->prev_of(MAXIMUM_SIZE) = MAXIMUM_SIZE; + + // Finally, set the size back to 0 + this->IMPLEMENTATION_DETAIL_DO_NOT_USE_size_ = 0; + } }; } // namespace fixed_containers::fixed_doubly_linked_list_detail::specializations diff --git a/include/fixed_containers/fixed_robinhood_hashtable.hpp b/include/fixed_containers/fixed_robinhood_hashtable.hpp index 10d96348..2ce583ef 100644 --- a/include/fixed_containers/fixed_robinhood_hashtable.hpp +++ b/include/fixed_containers/fixed_robinhood_hashtable.hpp @@ -386,7 +386,14 @@ class FixedRobinhoodHashtable return end_value_index; } - constexpr void clear() { erase_range(begin_index(), end_index()); } + constexpr void clear() + { + // reset the backing linked list + IMPLEMENTATION_DETAIL_DO_NOT_USE_value_storage_.clear(); + + // reset the bucket array + IMPLEMENTATION_DETAIL_DO_NOT_USE_bucket_array_.fill({}); + } public: constexpr FixedRobinhoodHashtable() = default;