diff options
Diffstat (limited to 'third_party/abseil_cpp/absl/flags/reflection.cc')
-rw-r--r-- | third_party/abseil_cpp/absl/flags/reflection.cc | 153 |
1 files changed, 91 insertions, 62 deletions
diff --git a/third_party/abseil_cpp/absl/flags/reflection.cc b/third_party/abseil_cpp/absl/flags/reflection.cc index 5fc945f23767..c976d4679601 100644 --- a/third_party/abseil_cpp/absl/flags/reflection.cc +++ b/third_party/abseil_cpp/absl/flags/reflection.cc @@ -17,6 +17,7 @@ #include <assert.h> +#include <atomic> #include <map> #include <string> @@ -56,25 +57,23 @@ class FlagRegistry { // Returns the flag object for the specified name, or nullptr if not found. // Will emit a warning if a 'retired' flag is specified. - CommandLineFlag* FindFlagLocked(absl::string_view name); - - // Returns the retired flag object for the specified name, or nullptr if not - // found or not retired. Does not emit a warning. - CommandLineFlag* FindRetiredFlagLocked(absl::string_view name); + CommandLineFlag* FindFlag(absl::string_view name); static FlagRegistry& GlobalRegistry(); // returns a singleton registry private: friend class flags_internal::FlagSaverImpl; // reads all the flags in order // to copy them - friend void ForEachFlagUnlocked( - std::function<void(CommandLineFlag&)> visitor); + friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor); + friend void FinalizeRegistry(); - // The map from name to flag, for FindFlagLocked(). + // The map from name to flag, for FindFlag(). using FlagMap = std::map<absl::string_view, CommandLineFlag*>; using FlagIterator = FlagMap::iterator; using FlagConstIterator = FlagMap::const_iterator; FlagMap flags_; + std::vector<CommandLineFlag*> flat_flags_; + std::atomic<bool> finalized_flags_{false}; absl::Mutex lock_; @@ -83,29 +82,6 @@ class FlagRegistry { FlagRegistry& operator=(const FlagRegistry&); }; -CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) { - FlagConstIterator i = flags_.find(name); - if (i == flags_.end()) { - return nullptr; - } - - if (i->second->IsRetired()) { - flags_internal::ReportUsageError( - absl::StrCat("Accessing retired flag '", name, "'"), false); - } - - return i->second; -} - -CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) { - FlagConstIterator i = flags_.find(name); - if (i == flags_.end() || !i->second->IsRetired()) { - return nullptr; - } - - return i->second; -} - namespace { class FlagRegistryLock { @@ -117,12 +93,26 @@ class FlagRegistryLock { FlagRegistry& fr_; }; -void DestroyRetiredFlag(CommandLineFlag& flag); - } // namespace +CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) { + if (finalized_flags_.load(std::memory_order_acquire)) { + // We could save some gcus here if we make `Name()` be non-virtual. + // We could move the `const char*` name to the base class. + auto it = std::partition_point( + flat_flags_.begin(), flat_flags_.end(), + [=](CommandLineFlag* f) { return f->Name() < name; }); + if (it != flat_flags_.end() && (*it)->Name() == name) return *it; + } + + FlagRegistryLock frl(*this); + auto it = flags_.find(name); + return it != flags_.end() ? it->second : nullptr; +} + void FlagRegistry::RegisterFlag(CommandLineFlag& flag) { FlagRegistryLock registry_lock(*this); + std::pair<FlagIterator, bool> ins = flags_.insert(FlagMap::value_type(flag.Name(), &flag)); if (ins.second == false) { // means the name was already in the map @@ -143,8 +133,6 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag) { old_flag.Filename(), "' and '", flag.Filename(), "'."), true); } else if (old_flag.IsRetired()) { - // Retired flag can just be deleted. - DestroyRetiredFlag(flag); return; } else if (old_flag.Filename() != flag.Filename()) { flags_internal::ReportUsageError( @@ -155,7 +143,7 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag) { } else { flags_internal::ReportUsageError( absl::StrCat( - "Something wrong with flag '", flag.Name(), "' in file '", + "Something is wrong with flag '", flag.Name(), "' in file '", flag.Filename(), "'. One possibility: file '", flag.Filename(), "' is being linked both statically and dynamically into this " "executable. e.g. some files listed as srcs to a test and also " @@ -174,18 +162,15 @@ FlagRegistry& FlagRegistry::GlobalRegistry() { // -------------------------------------------------------------------- -void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor) { +void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) { FlagRegistry& registry = FlagRegistry::GlobalRegistry(); - for (FlagRegistry::FlagConstIterator i = registry.flags_.begin(); - i != registry.flags_.end(); ++i) { - visitor(*i->second); + + if (registry.finalized_flags_.load(std::memory_order_acquire)) { + for (const auto& i : registry.flat_flags_) visitor(*i); } -} -void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) { - FlagRegistry& registry = FlagRegistry::GlobalRegistry(); FlagRegistryLock frl(registry); - ForEachFlagUnlocked(visitor); + for (const auto& i : registry.flags_) visitor(*i.second); } // -------------------------------------------------------------------- @@ -195,6 +180,21 @@ bool RegisterCommandLineFlag(CommandLineFlag& flag) { return true; } +void FinalizeRegistry() { + auto& registry = FlagRegistry::GlobalRegistry(); + FlagRegistryLock frl(registry); + if (registry.finalized_flags_.load(std::memory_order_relaxed)) { + // Was already finalized. Ignore the second time. + return; + } + registry.flat_flags_.reserve(registry.flags_.size()); + for (const auto& f : registry.flags_) { + registry.flat_flags_.push_back(f.second); + } + registry.flags_.clear(); + registry.finalized_flags_.store(true, std::memory_order_release); +} + // -------------------------------------------------------------------- namespace { @@ -206,16 +206,34 @@ class RetiredFlagObj final : public CommandLineFlag { private: absl::string_view Name() const override { return name_; } - std::string Filename() const override { return "RETIRED"; } + std::string Filename() const override { + OnAccess(); + return "RETIRED"; + } FlagFastTypeId TypeId() const override { return type_id_; } - std::string Help() const override { return ""; } + std::string Help() const override { + OnAccess(); + return ""; + } bool IsRetired() const override { return true; } - bool IsSpecifiedOnCommandLine() const override { return false; } - std::string DefaultValue() const override { return ""; } - std::string CurrentValue() const override { return ""; } + bool IsSpecifiedOnCommandLine() const override { + OnAccess(); + return false; + } + std::string DefaultValue() const override { + OnAccess(); + return ""; + } + std::string CurrentValue() const override { + OnAccess(); + return ""; + } // Any input is valid - bool ValidateInputValue(absl::string_view) const override { return true; } + bool ValidateInputValue(absl::string_view) const override { + OnAccess(); + return true; + } std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override { return nullptr; @@ -223,29 +241,32 @@ class RetiredFlagObj final : public CommandLineFlag { bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode, flags_internal::ValueSource, std::string&) override { + OnAccess(); return false; } - void CheckDefaultValueParsingRoundtrip() const override {} + void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); } + + void Read(void*) const override { OnAccess(); } - void Read(void*) const override {} + void OnAccess() const { + flags_internal::ReportUsageError( + absl::StrCat("Accessing retired flag '", name_, "'"), false); + } // Data members const char* const name_; const FlagFastTypeId type_id_; }; -void DestroyRetiredFlag(CommandLineFlag& flag) { - assert(flag.IsRetired()); - delete static_cast<RetiredFlagObj*>(&flag); -} - } // namespace -bool Retire(const char* name, FlagFastTypeId type_id) { - auto* flag = new flags_internal::RetiredFlagObj(name, type_id); +void Retire(const char* name, FlagFastTypeId type_id, char* buf) { + static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, ""); + static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, ""); + auto* flag = ::new (static_cast<void*>(buf)) + flags_internal::RetiredFlagObj(name, type_id); FlagRegistry::GlobalRegistry().RegisterFlag(*flag); - return true; } // -------------------------------------------------------------------- @@ -299,9 +320,17 @@ CommandLineFlag* FindCommandLineFlag(absl::string_view name) { if (name.empty()) return nullptr; flags_internal::FlagRegistry& registry = flags_internal::FlagRegistry::GlobalRegistry(); - flags_internal::FlagRegistryLock frl(registry); + return registry.FindFlag(name); +} + +// -------------------------------------------------------------------- - return registry.FindFlagLocked(name); +absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags() { + absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> res; + flags_internal::ForEachFlag([&](CommandLineFlag& flag) { + if (!flag.IsRetired()) res.insert({flag.Name(), &flag}); + }); + return res; } ABSL_NAMESPACE_END |