31
31
#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__
32
32
#define GOOGLE_PROTOBUF_DESCRIPTOR_H__
33
33
34
- #include < any>
35
34
#include < atomic>
36
35
#include < cstdint>
37
36
#include < iterator>
@@ -2455,11 +2454,20 @@ class PROTOBUF_EXPORT DescriptorPool {
2455
2454
friend class google ::protobuf::descriptor_unittest::ValidationErrorTest;
2456
2455
friend class ::google::protobuf::compiler::CommandLineInterface;
2457
2456
friend class TextFormat ;
2457
+
2458
+ struct MemoBase {
2459
+ virtual ~MemoBase () = default ;
2460
+ };
2461
+ template <typename T>
2462
+ struct MemoData : MemoBase {
2463
+ T value;
2464
+ };
2465
+
2458
2466
// Memoize a projection of a field. This is used to cache the results of
2459
2467
// calling a function on a field, used for expensive descriptor calculations.
2460
2468
template <typename Func>
2461
- auto MemoizeProjection (const FieldDescriptor* field, Func func) const {
2462
- using ResultT = decltype (func (field));
2469
+ const auto & MemoizeProjection (const FieldDescriptor* field, Func func) const {
2470
+ using ResultT = std:: decay_t < decltype (func (field))> ;
2463
2471
ABSL_DCHECK (field->file ()->pool () == this );
2464
2472
static_assert (std::is_empty_v<Func>);
2465
2473
// This static bool is unique per-Func, so its address can be used as a key.
@@ -2469,15 +2477,21 @@ class PROTOBUF_EXPORT DescriptorPool {
2469
2477
absl::ReaderMutexLock lock (&field_memo_table_mutex_);
2470
2478
auto it = field_memo_table_.find (key);
2471
2479
if (it != field_memo_table_.end ()) {
2472
- return std::any_cast< ResultT>( it->second );
2480
+ return internal::DownCast< const MemoData< ResultT>&>(* it->second ). value ;
2473
2481
}
2474
2482
}
2475
- ResultT result = func (field);
2483
+ auto result = std::make_unique<MemoData<ResultT>>();
2484
+ result->value = func (field);
2476
2485
{
2477
2486
absl::MutexLock lock (&field_memo_table_mutex_);
2478
- field_memo_table_[key] = result;
2487
+ auto & res = field_memo_table_[key];
2488
+ // Only initialize the first time. We don't want to invalidate old
2489
+ // references.
2490
+ if (res == nullptr ) {
2491
+ res = std::move (result);
2492
+ }
2493
+ return internal::DownCast<const MemoData<ResultT>&>(*res).value ;
2479
2494
}
2480
- return result;
2481
2495
}
2482
2496
// Return true if the given name is a sub-symbol of any non-package
2483
2497
// descriptor that already exists in the descriptor pool. (The full
@@ -2537,9 +2551,12 @@ class PROTOBUF_EXPORT DescriptorPool {
2537
2551
Symbol NewPlaceholderWithMutexHeld (absl::string_view name,
2538
2552
PlaceholderType placeholder_type) const ;
2539
2553
2554
+ #ifndef SWIG
2540
2555
mutable absl::Mutex field_memo_table_mutex_;
2541
- mutable absl::flat_hash_map<std::pair<const void *, const void *>, std::any>
2556
+ mutable absl::flat_hash_map<std::pair<const void *, const void *>,
2557
+ std::unique_ptr<MemoBase>>
2542
2558
field_memo_table_ ABSL_GUARDED_BY (field_memo_table_mutex_);
2559
+ #endif // SWIG
2543
2560
2544
2561
// If fallback_database_ is nullptr, this is nullptr. Otherwise, this is a
2545
2562
// mutex which must be locked while accessing tables_.
0 commit comments