diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 923d8c1..b291a4e 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -26,6 +26,7 @@ #include "absl/base/attributes.h" #include "absl/base/optimization.h" +#include "absl/container/btree_map.h" #include "absl/container/flat_hash_set.h" #include "absl/functional/overload.h" #include "absl/hash/hash.h" @@ -49,6 +50,10 @@ namespace google { namespace protobuf { namespace internal { + +struct ExtensionSet::LargeMap : public absl::btree_map { + using btree_map::btree_map; +}; namespace { inline WireFormatLite::FieldType real_type(FieldType type) { @@ -1565,6 +1570,39 @@ std::pair ExtensionSet::InternalInsertIntoLargeMap(int key) { ABSL_DCHECK(is_large()); auto maybe = map_.large->insert({key, Extension()}); return {&maybe.first->second, maybe.second}; } +size_t ExtensionSet::LargeMapSize() const { + return map_.large->size(); +} + +void ExtensionSet::ForEachLargeMap( + absl::FunctionRef func, + absl::FunctionRef prefetch_func) { + ForEachPrefetchImpl(map_.large->begin(), map_.large->end(), func, + prefetch_func); +} + +void ExtensionSet::ForEachLargeMap( + absl::FunctionRef func, + absl::FunctionRef prefetch_func) const { + ForEachPrefetchImpl(map_.large->begin(), map_.large->end(), func, + prefetch_func); +} + +void ExtensionSet::ForEachNoPrefetchLargeMap( + absl::FunctionRef func) { + ForEachNoPrefetch(map_.large->begin(), map_.large->end(), func); +} + +void ExtensionSet::ForEachNoPrefetchLargeMap( + absl::FunctionRef func) const { + ForEachNoPrefetch(map_.large->begin(), map_.large->end(), func); +} + +bool ExtensionSet::AnyOfNoPrefetchLargeMap( + absl::FunctionRef predicate) const { + return AnyOfNoPrefetch(map_.large->begin(), map_.large->end(), predicate); +} + std::pair ExtensionSet::Insert(Arena* arena, int key) { diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index 923d8c1..b291a4e 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -34,7 +34,7 @@ #include "google/protobuf/stubs/common.h" #include "absl/base/casts.h" #include "absl/base/prefetch.h" -#include "absl/container/btree_map.h" +#include "absl/functional/function_ref.h" #include "absl/log/absl_check.h" #include "absl/strings/string_view.h" #include "google/protobuf/generated_enum_util.h" @@ -893,7 +893,7 @@ class PROTOBUF_EXPORT ExtensionSet { Extension second; }; - using LargeMap = absl::btree_map; + struct LargeMap; // Wrapper API that switches between flat-map and LargeMap. @@ -911,6 +911,15 @@ class PROTOBUF_EXPORT ExtensionSet { // Same as insert for the large map. std::pair InternalInsertIntoLargeMap(int key); + size_t LargeMapSize() const; + void ForEachLargeMap(absl::FunctionRef func, + absl::FunctionRef prefetch_func); + void ForEachLargeMap(absl::FunctionRef func, + absl::FunctionRef prefetch_func) const; + void ForEachNoPrefetchLargeMap(absl::FunctionRef func); + void ForEachNoPrefetchLargeMap(absl::FunctionRef func) const; + bool AnyOfNoPrefetchLargeMap(absl::FunctionRef predicate) const; + // Grows the flat_capacity_. // If flat_capacity_ > kMaximumFlatCapacity, converts to LargeMap. void GrowCapacity(Arena* arena, size_t minimum_new_capacity); @@ -932,7 +941,7 @@ class PROTOBUF_EXPORT ExtensionSet { // Returns the number of elements in the ExtensionSet, including cleared // extensions. size_t Size() const { - return ABSL_PREDICT_FALSE(is_large()) ? map_.large->size() : flat_size_; + return ABSL_PREDICT_FALSE(is_large()) ? LargeMapSize() : flat_size_; } // For use as `PrefetchFunctor`s in `ForEach`. @@ -975,8 +984,9 @@ class PROTOBUF_EXPORT ExtensionSet { template void ForEach(KeyValueFunctor func, PrefetchFunctor prefetch_func) { if (ABSL_PREDICT_FALSE(is_large())) { - ForEachPrefetchImpl(map_.large->begin(), map_.large->end(), - std::move(func), std::move(prefetch_func)); + ForEachLargeMap( + [&](int k, Extension& ext) { func(k, ext); }, + [&](const void* p) { prefetch_func(p); }); return; } ForEachPrefetchImpl(flat_begin(), flat_end(), std::move(func), @@ -986,8 +996,9 @@ class PROTOBUF_EXPORT ExtensionSet { template void ForEach(KeyValueFunctor func, PrefetchFunctor prefetch_func) const { if (ABSL_PREDICT_FALSE(is_large())) { - ForEachPrefetchImpl(map_.large->begin(), map_.large->end(), - std::move(func), std::move(prefetch_func)); + ForEachLargeMap( + [&](int k, const Extension& ext) { func(k, ext); }, + [&](const void* p) { prefetch_func(p); }); return; } ForEachPrefetchImpl(flat_begin(), flat_end(), std::move(func), @@ -1019,8 +1030,7 @@ class PROTOBUF_EXPORT ExtensionSet { template void ForEachNoPrefetch(KeyValueFunctor func) { if (ABSL_PREDICT_FALSE(is_large())) { - ForEachNoPrefetch(map_.large->begin(), map_.large->end(), - std::move(func)); + ForEachNoPrefetchLargeMap([&](int k, Extension& ext) { func(k, ext); }); return; } ForEachNoPrefetch(flat_begin(), flat_end(), std::move(func)); @@ -1030,8 +1040,8 @@ class PROTOBUF_EXPORT ExtensionSet { template void ForEachNoPrefetch(KeyValueFunctor func) const { if (ABSL_PREDICT_FALSE(is_large())) { - ForEachNoPrefetch(map_.large->begin(), map_.large->end(), - std::move(func)); + ForEachNoPrefetchLargeMap( + [&](int k, const Extension& ext) { func(k, ext); }); return; } ForEachNoPrefetch(flat_begin(), flat_end(), std::move(func)); @@ -1043,8 +1053,8 @@ class PROTOBUF_EXPORT ExtensionSet { template bool AnyOfNoPrefetch(KeyValueFunctor predicate) const { if (ABSL_PREDICT_FALSE(is_large())) { - return AnyOfNoPrefetch(map_.large->begin(), map_.large->end(), - std::move(predicate)); + return AnyOfNoPrefetchLargeMap( + [&](int k, const Extension& ext) { return predicate(k, ext); }); } return AnyOfNoPrefetch(flat_begin(), flat_end(), std::move(predicate)); } diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 923d8c1..b291a4e 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -365,7 +365,7 @@ int ExtensionSet::SpaceUsedExcludingSelf() const { size_t ExtensionSet::SpaceUsedExcludingSelfLong() const { size_t total_size = - (is_large() ? map_.large->size() : flat_capacity_) * sizeof(KeyValue); + (is_large() ? Size() : flat_capacity_) * sizeof(KeyValue); ForEach( [&total_size](int /* number */, const Extension& ext) { total_size += ext.SpaceUsedExcludingSelfLong(); diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 923d8c1..b291a4e 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -31,7 +31,6 @@ #include "absl/base/attributes.h" #include "absl/base/optimization.h" #include "absl/base/prefetch.h" -#include "absl/container/btree_map.h" #include "absl/hash/hash.h" #include "absl/log/absl_check.h" #include "absl/numeric/bits.h"