(&empty_node);
-#endif
}
enum : uint32_t {
@@ -2420,7 +2410,7 @@ auto btree::operator=(btree &&other) noexcept -> btree & {
using std::swap;
if (absl::allocator_traits<
- allocator_type>::propagate_on_container_copy_assignment::value) {
+ allocator_type>::propagate_on_container_move_assignment::value) {
swap(root_, other.root_);
// Note: `rightmost_` also contains the allocator and the key comparator.
swap(rightmost_, other.rightmost_);
@@ -2534,6 +2524,10 @@ auto btree
::rebalance_after_delete(iterator iter) -> iterator {
return res;
}
+// Note: we tried implementing this more efficiently by erasing all of the
+// elements in [begin, end) at once and then doing rebalancing once at the end
+// (rather than interleaving deletion and rebalancing), but that adds a lot of
+// complexity, which seems to outweigh the performance win.
template
auto btree::erase_range(iterator begin, iterator end)
-> std::pair {
@@ -2863,7 +2857,8 @@ inline auto btree::internal_emplace(iterator iter, Args &&...args)
}
}
(void)replaced_node;
-#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
+ defined(ABSL_HAVE_HWADDRESS_SANITIZER)
if (!replaced_node) {
assert(iter.node_->is_leaf());
if (iter.node_->is_root()) {
diff --git a/absl/container/internal/common_policy_traits.h b/absl/container/internal/common_policy_traits.h
index 3558a54..57eac67 100644
--- a/absl/container/internal/common_policy_traits.h
+++ b/absl/container/internal/common_policy_traits.h
@@ -93,11 +93,13 @@ struct common_policy_traits {
struct Rank0 : Rank1 {};
// Use auto -> decltype as an enabler.
+ // P::transfer returns std::true_type if transfer uses memcpy (e.g. in
+ // node_slot_policy).
template
static auto transfer_impl(Alloc* alloc, slot_type* new_slot,
slot_type* old_slot, Rank0)
- -> decltype((void)P::transfer(alloc, new_slot, old_slot)) {
- P::transfer(alloc, new_slot, old_slot);
+ -> decltype(P::transfer(alloc, new_slot, old_slot)) {
+ return P::transfer(alloc, new_slot, old_slot);
}
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
// This overload returns true_type for the trait below.
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h
index f59ca4e..3262d4e 100644
--- a/absl/container/internal/container_memory.h
+++ b/absl/container/internal/container_memory.h
@@ -122,10 +122,10 @@ auto TupleRefImpl(T&& t, absl::index_sequence)
// Returns a tuple of references to the elements of the input tuple. T must be a
// tuple.
template
-auto TupleRef(T&& t) -> decltype(
- TupleRefImpl(std::forward(t),
- absl::make_index_sequence<
- std::tuple_size::type>::value>())) {
+auto TupleRef(T&& t) -> decltype(TupleRefImpl(
+ std::forward(t),
+ absl::make_index_sequence<
+ std::tuple_size::type>::value>())) {
return TupleRefImpl(
std::forward(t),
absl::make_index_sequence<
@@ -156,8 +156,8 @@ void ConstructFromTuple(Alloc* alloc, T* ptr, Tuple&& t) {
// Constructs T using the args specified in the tuple and calls F with the
// constructed value.
template
-decltype(std::declval()(std::declval())) WithConstructed(
- Tuple&& t, F&& f) {
+decltype(std::declval()(std::declval())) WithConstructed(Tuple&& t,
+ F&& f) {
return memory_internal::WithConstructedImpl(
std::forward(t),
absl::make_index_sequence<
@@ -423,16 +423,19 @@ struct map_slot_policy {
}
template
- static void transfer(Allocator* alloc, slot_type* new_slot,
+ static auto transfer(Allocator* alloc, slot_type* new_slot,
slot_type* old_slot) {
+ auto is_relocatable =
+ typename absl::is_trivially_relocatable::type();
+
emplace(new_slot);
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
- if (absl::is_trivially_relocatable()) {
+ if (is_relocatable) {
// TODO(b/247130232,b/251814870): remove casts after fixing warnings.
std::memcpy(static_cast(std::launder(&new_slot->value)),
static_cast(&old_slot->value),
sizeof(value_type));
- return;
+ return is_relocatable;
}
#endif
@@ -444,6 +447,7 @@ struct map_slot_policy {
std::move(old_slot->value));
}
destroy(alloc, old_slot);
+ return is_relocatable;
}
};
diff --git a/absl/container/internal/counting_allocator.h b/absl/container/internal/counting_allocator.h
deleted file mode 100644
index 66068a5..0000000
--- a/absl/container/internal/counting_allocator.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
-#define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
-
-#include
-#include
-
-#include "absl/base/config.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace container_internal {
-
-// This is a stateful allocator, but the state lives outside of the
-// allocator (in whatever test is using the allocator). This is odd
-// but helps in tests where the allocator is propagated into nested
-// containers - that chain of allocators uses the same state and is
-// thus easier to query for aggregate allocation information.
-template
-class CountingAllocator {
- public:
- using Allocator = std::allocator;
- using AllocatorTraits = std::allocator_traits;
- using value_type = typename AllocatorTraits::value_type;
- using pointer = typename AllocatorTraits::pointer;
- using const_pointer = typename AllocatorTraits::const_pointer;
- using size_type = typename AllocatorTraits::size_type;
- using difference_type = typename AllocatorTraits::difference_type;
-
- CountingAllocator() = default;
- explicit CountingAllocator(int64_t* bytes_used) : bytes_used_(bytes_used) {}
- CountingAllocator(int64_t* bytes_used, int64_t* instance_count)
- : bytes_used_(bytes_used), instance_count_(instance_count) {}
-
- template
- CountingAllocator(const CountingAllocator& x)
- : bytes_used_(x.bytes_used_), instance_count_(x.instance_count_) {}
-
- pointer allocate(
- size_type n,
- typename AllocatorTraits::const_void_pointer hint = nullptr) {
- Allocator allocator;
- pointer ptr = AllocatorTraits::allocate(allocator, n, hint);
- if (bytes_used_ != nullptr) {
- *bytes_used_ += n * sizeof(T);
- }
- return ptr;
- }
-
- void deallocate(pointer p, size_type n) {
- Allocator allocator;
- AllocatorTraits::deallocate(allocator, p, n);
- if (bytes_used_ != nullptr) {
- *bytes_used_ -= n * sizeof(T);
- }
- }
-
- template
- void construct(U* p, Args&&... args) {
- Allocator allocator;
- AllocatorTraits::construct(allocator, p, std::forward(args)...);
- if (instance_count_ != nullptr) {
- *instance_count_ += 1;
- }
- }
-
- template
- void destroy(U* p) {
- Allocator allocator;
- // Ignore GCC warning bug.
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wuse-after-free"
-#endif
- AllocatorTraits::destroy(allocator, p);
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
-#pragma GCC diagnostic pop
-#endif
- if (instance_count_ != nullptr) {
- *instance_count_ -= 1;
- }
- }
-
- template
- class rebind {
- public:
- using other = CountingAllocator;
- };
-
- friend bool operator==(const CountingAllocator& a,
- const CountingAllocator& b) {
- return a.bytes_used_ == b.bytes_used_ &&
- a.instance_count_ == b.instance_count_;
- }
-
- friend bool operator!=(const CountingAllocator& a,
- const CountingAllocator& b) {
- return !(a == b);
- }
-
- int64_t* bytes_used_ = nullptr;
- int64_t* instance_count_ = nullptr;
-};
-
-} // namespace container_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc
index 59cc5aa..e89dfdb 100644
--- a/absl/container/internal/hash_generator_testing.cc
+++ b/absl/container/internal/hash_generator_testing.cc
@@ -16,6 +16,8 @@
#include
+#include "absl/base/no_destructor.h"
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
@@ -41,11 +43,11 @@ class RandomDeviceSeedSeq {
} // namespace
std::mt19937_64* GetSharedRng() {
- static auto* rng = [] {
+ static absl::NoDestructor rng([] {
RandomDeviceSeedSeq seed_seq;
- return new std::mt19937_64(seed_seq);
- }();
- return rng;
+ return std::mt19937_64(seed_seq);
+ }());
+ return rng.get();
}
std::string Generator::operator()() const {
@@ -59,7 +61,7 @@ std::string Generator::operator()() const {
}
absl::string_view Generator::operator()() const {
- static auto* arena = new std::deque();
+ static absl::NoDestructor> arena;
// NOLINTNEXTLINE(runtime/int)
std::uniform_int_distribution chars(0x20, 0x7E);
arena->emplace_back();
diff --git a/absl/container/internal/hashtable_debug.h b/absl/container/internal/hashtable_debug.h
index 19d5212..c79c1a9 100644
--- a/absl/container/internal/hashtable_debug.h
+++ b/absl/container/internal/hashtable_debug.h
@@ -95,14 +95,6 @@ size_t AllocatedByteSize(const C& c) {
HashtableDebugAccess::AllocatedByteSize(c);
}
-// Returns a tight lower bound for AllocatedByteSize(c) where `c` is of type `C`
-// and `c.size()` is equal to `num_elements`.
-template
-size_t LowerBoundAllocatedByteSize(size_t num_elements) {
- return absl::container_internal::hashtable_debug_internal::
- HashtableDebugAccess::LowerBoundAllocatedByteSize(num_elements);
-}
-
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index d8fd8f3..e41ee2d 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -137,18 +137,7 @@ class HashtablezInfoHandle {
UnsampleSlow(info_);
}
- HashtablezInfoHandle(const HashtablezInfoHandle&) = delete;
- HashtablezInfoHandle& operator=(const HashtablezInfoHandle&) = delete;
-
- HashtablezInfoHandle(HashtablezInfoHandle&& o) noexcept
- : info_(absl::exchange(o.info_, nullptr)) {}
- HashtablezInfoHandle& operator=(HashtablezInfoHandle&& o) noexcept {
- if (ABSL_PREDICT_FALSE(info_ != nullptr)) {
- UnsampleSlow(info_);
- }
- info_ = absl::exchange(o.info_, nullptr);
- return *this;
- }
+ inline bool IsSampled() const { return ABSL_PREDICT_FALSE(info_ != nullptr); }
inline void RecordStorageChanged(size_t size, size_t capacity) {
if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
@@ -198,6 +187,7 @@ class HashtablezInfoHandle {
explicit HashtablezInfoHandle(std::nullptr_t) {}
inline void Unregister() {}
+ inline bool IsSampled() const { return false; }
inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {}
inline void RecordRehash(size_t /*total_probe_length*/) {}
inline void RecordReservation(size_t /*target_capacity*/) {}
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
index b2a602d..0eb9c34 100644
--- a/absl/container/internal/inlined_vector.h
+++ b/absl/container/internal/inlined_vector.h
@@ -26,6 +26,7 @@
#include
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/container/internal/compressed_tuple.h"
#include "absl/memory/memory.h"
@@ -384,7 +385,17 @@ class Storage {
bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; }
- Pointer GetAllocatedData() { return data_.allocated.allocated_data; }
+ Pointer GetAllocatedData() {
+ // GCC 12 has a false-positive -Wmaybe-uninitialized warning here.
+#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+ return data_.allocated.allocated_data;
+#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
+#pragma GCC diagnostic pop
+#endif
+ }
ConstPointer GetAllocatedData() const {
return data_.allocated.allocated_data;
diff --git a/absl/container/internal/layout.h b/absl/container/internal/layout.h
index a59a243..a4ba610 100644
--- a/absl/container/internal/layout.h
+++ b/absl/container/internal/layout.h
@@ -55,7 +55,7 @@
// `Partial()` comes in handy when the array sizes are embedded into the
// allocation.
//
-// // size_t[1] containing N, size_t[1] containing M, double[N], int[M].
+// // size_t[0] containing N, size_t[1] containing M, double[N], int[M].
// using L = Layout;
//
// unsigned char* Allocate(size_t n, size_t m) {
@@ -172,6 +172,7 @@
#include
#include "absl/base/config.h"
+#include "absl/debugging/internal/demangle.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/str_cat.h"
#include "absl/types/span.h"
@@ -181,14 +182,6 @@
#include
#endif
-#if defined(__GXX_RTTI)
-#define ABSL_INTERNAL_HAS_CXA_DEMANGLE
-#endif
-
-#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
-#include
-#endif
-
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
@@ -294,19 +287,11 @@ constexpr size_t Max(size_t a, size_t b, Ts... rest) {
template
std::string TypeName() {
std::string out;
- int status = 0;
- char* demangled = nullptr;
-#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
- demangled = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
-#endif
- if (status == 0 && demangled != nullptr) { // Demangling succeeded.
- absl::StrAppend(&out, "<", demangled, ">");
- free(demangled);
- } else {
-#if defined(__GXX_RTTI) || defined(_CPPRTTI)
- absl::StrAppend(&out, "<", typeid(T).name(), ">");
+#if ABSL_INTERNAL_HAS_RTTI
+ absl::StrAppend(&out, "<",
+ absl::debugging_internal::DemangleString(typeid(T).name()),
+ ">");
#endif
- }
return out;
}
diff --git a/absl/container/internal/node_slot_policy.h b/absl/container/internal/node_slot_policy.h
index baba574..3f1874d 100644
--- a/absl/container/internal/node_slot_policy.h
+++ b/absl/container/internal/node_slot_policy.h
@@ -62,9 +62,12 @@ struct node_slot_policy {
Policy::delete_element(alloc, *slot);
}
+ // Returns true_type to indicate that transfer can use memcpy.
template
- static void transfer(Alloc*, slot_type* new_slot, slot_type* old_slot) {
+ static std::true_type transfer(Alloc*, slot_type* new_slot,
+ slot_type* old_slot) {
*new_slot = *old_slot;
+ return {};
}
static size_t space_used(const slot_type* slot) {
diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h
index 2d5a871..97182bc 100644
--- a/absl/container/internal/raw_hash_map.h
+++ b/absl/container/internal/raw_hash_map.h
@@ -19,6 +19,8 @@
#include
#include
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export
@@ -175,13 +177,20 @@ class raw_hash_map : public raw_hash_set {
template
MappedReference operator[](key_arg&& key)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
- return Policy::value(&*try_emplace(std::forward(key)).first);
+ // It is safe to use unchecked_deref here because try_emplace
+ // will always return an iterator pointing to a valid item in the table,
+ // since it inserts if nothing is found for the given key.
+ return Policy::value(
+ &this->unchecked_deref(try_emplace(std::forward(key)).first));
}
template
MappedReference operator[](const key_arg& key)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
- return Policy::value(&*try_emplace(key).first);
+ // It is safe to use unchecked_deref here because try_emplace
+ // will always return an iterator pointing to a valid item in the table,
+ // since it inserts if nothing is found for the given key.
+ return Policy::value(&this->unchecked_deref(try_emplace(key).first));
}
private:
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index 2ff95b6..9f8ea51 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -17,11 +17,13 @@
#include
#include
#include
+#include
#include