From 2796d500aea5a31d26b8b24a33fab7a1c8fa2f32 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 21 Oct 2019 10:21:03 -0700 Subject: Export of internal Abseil changes -- b770d03c2f1042d399c3f9576e881691cbe962c4 by Abseil Team : Avoid applying the workaround for MSVC's static initialization problems when using clang-cl. PiperOrigin-RevId: 275870089 -- 2b8fc02ec49aeb5ad56cef20259cdd7f6ee0c917 by Abseil Team : Document return values. PiperOrigin-RevId: 275839042 -- baa99064f9a28b188661df7fba989fcd558818af by Abseil Team : Support "auto" and other uncommon builtin types in absl::debugging_internal::Demangle. PiperOrigin-RevId: 275556195 -- f9d5c6a3a0d374dbf105d6e2e9e0c8fa949ed187 by Gennadiy Rozental : Internal rework. PiperOrigin-RevId: 275550005 -- 2679a77db5b26349e8c8b2059621af55d2fca139 by Mark Barolak : Remove a comment reference to the no longer extant ::string implementation. PiperOrigin-RevId: 275531987 -- 7b427a7613c44a98c6f13da43b2bff2837ca6b19 by Derek Mauro : Upgrade to Bazel 1.0.0 and CMake 3.15.4 PiperOrigin-RevId: 275500823 -- 81f7d20905debf9d1e300bd2e9899f88d27f632a by Derek Mauro : Fix -Wimplicit-int-float-conversion warning in latest clang PiperOrigin-RevId: 275492439 GitOrigin-RevId: b770d03c2f1042d399c3f9576e881691cbe962c4 Change-Id: I9b39dad524489f0d62c912d02e8ac43761c81e55 --- absl/flags/internal/commandlineflag.h | 187 ++++++++++++---------------------- 1 file changed, 64 insertions(+), 123 deletions(-) (limited to 'absl/flags/internal/commandlineflag.h') diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h index 528d310..13a3352 100644 --- a/absl/flags/internal/commandlineflag.h +++ b/absl/flags/internal/commandlineflag.h @@ -16,12 +16,10 @@ #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ -#include #include #include "absl/base/macros.h" #include "absl/flags/marshalling.h" -#include "absl/synchronization/mutex.h" #include "absl/types/optional.h" namespace absl { @@ -151,14 +149,6 @@ inline size_t Sizeof(FlagOpFn op) { op(flags_internal::kSizeof, nullptr, nullptr))); } -// The following struct contains the locks in a CommandLineFlag struct. -// They are in a separate struct that is lazily allocated to avoid problems -// with static initialization and to avoid multiple allocations. -struct CommandLineFlagLocks { - absl::Mutex primary_mu; // protects several fields in CommandLineFlag - absl::Mutex callback_mu; // used to serialize callbacks -}; - // Holds either a pointer to help text or a function which produces it. This is // needed for supporting both static initialization of Flags while supporting // the legacy registration framework. We can't use absl::variant inline bool IsOfType() const { - return op_ == &flags_internal::FlagOps; + return TypeId() == &flags_internal::FlagOps; } // Attempts to retrieve the flag value. Returns value on success, // absl::nullopt otherwise. template absl::optional Get() const { - if (IsRetired() || flags_internal::FlagOps != op_) return absl::nullopt; - - T res; - Read(&res, flags_internal::FlagOps); + if (IsRetired() || !IsOfType()) { + return absl::nullopt; + } - return res; + // Implementation notes: + // + // We are wrapping a union around the value of `T` to serve three purposes: + // + // 1. `U.value` has correct size and alignment for a value of type `T` + // 2. The `U.value` constructor is not invoked since U's constructor does + // not + // do it explicitly. + // 3. The `U.value` destructor is invoked since U's destructor does it + // explicitly. This makes `U` a kind of RAII wrapper around non default + // constructible value of T, which is destructed when we leave the + // scope. We do need to destroy U.value, which is constructed by + // CommandLineFlag::Read even though we left it in a moved-from state + // after std::move. + // + // All of this serves to avoid requiring `T` being default constructible. + union U { + T value; + U() {} + ~U() { value.~T(); } + }; + U u; + + Read(&u.value); + return std::move(u.value); } + // Polymorphic access methods + + // Returns true iff this object corresponds to retired flag + virtual bool IsRetired() const { return false; } + // Returns true iff this is a handle to an Abseil Flag. + virtual bool IsAbseilFlag() const { return true; } + // Returns id of the flag's value type. + virtual flags_internal::FlagOpFn TypeId() const = 0; + virtual bool IsModified() const = 0; + virtual bool IsSpecifiedOnCommandLine() const = 0; + virtual std::string DefaultValue() const = 0; + virtual std::string CurrentValue() const = 0; + + // Interfaces to operate on validators. + virtual bool ValidateInputValue(absl::string_view value) const = 0; + // Interface to save flag to some persistent state. Returns current flag state // or nullptr if flag does not support saving and restoring a state. virtual std::unique_ptr SaveState() = 0; - // Interfaces to overate on callbacks. - virtual void InvokeCallback() {} - // Sets the value of the flag based on specified std::string `value`. If the flag // was successfully set to new value, it returns true. Otherwise, sets `error` // to indicate the error, leaves the flag unchanged, and returns false. There @@ -289,74 +276,28 @@ class CommandLineFlag { // * Update the flag's default value // * Update the current flag value if it was never set before // The mode is selected based on `set_mode` parameter. - bool SetFromString(absl::string_view value, - flags_internal::FlagSettingMode set_mode, - flags_internal::ValueSource source, std::string* error); + virtual bool SetFromString(absl::string_view value, + flags_internal::FlagSettingMode set_mode, + flags_internal::ValueSource source, + std::string* error) = 0; - void CheckDefaultValueParsingRoundtrip() const; + // Checks that flags default value can be converted to std::string and back to the + // flag's value type. + virtual void CheckDefaultValueParsingRoundtrip() const = 0; // Constant configuration for a particular flag. protected: ~CommandLineFlag() = default; - // Thread safe access to mutation counter. - int64_t MutationCounter() const; - - const char* const name_; - const HelpText help_; - const char* const filename_; - - const FlagOpFn op_; // Type-specific handler - const FlagMarshallingOpFn marshalling_op_; // Marshalling ops handler - const InitialValGenFunc make_init_value_; // Makes initial value for the flag - std::atomic inited_; // fields have been lazily initialized - - // Mutable state (guarded by locks_->primary_mu). - bool modified_; // Has flag value been modified? - bool on_command_line_; // Specified on command line. - void* def_; // Lazily initialized pointer to default value - void* cur_; // Lazily initialized pointer to current value - int64_t counter_; // Mutation counter - - // Lazily initialized mutexes for this flag value. We cannot inline a - // SpinLock or Mutex here because those have non-constexpr constructors and - // so would prevent constant initialization of this type. - // TODO(rogeeff): fix it once Mutex has constexpr constructor - struct CommandLineFlagLocks* locks_; // locks, laziliy allocated. - - // Ensure that the lazily initialized fields of *flag have been initialized, - // and return the lock which should be locked when flag's state is mutated. - absl::Mutex* InitFlagIfNecessary() const ABSL_LOCK_RETURNED(locks_->primary_mu); - - // copy construct new value of flag's type in a memory referenced by dst - // based on current flag's value - void Read(void* dst, const flags_internal::FlagOpFn dst_op) const; - // updates flag's value to *src (locked) - void Write(const void* src, const flags_internal::FlagOpFn src_op); - - friend class FlagRegistry; - friend class FlagPtrMap; - friend class FlagSaverImpl; - friend bool TryParseLocked(CommandLineFlag* flag, void* dst, - absl::string_view value, std::string* err); - friend absl::Mutex* InitFlag(CommandLineFlag* flag); -}; + const char* const name_; // Flags name passed to ABSL_FLAG as second arg. + const HelpText help_; // The function generating help message. + const char* const filename_; // The file name where ABSL_FLAG resides. -// Update any copy of the flag value that is stored in an atomic word. -// In addition if flag has a mutation callback this function invokes it. While -// callback is being invoked the primary flag's mutex is unlocked and it is -// re-locked back after call to callback is completed. Callback invocation is -// guarded by flag's secondary mutex instead which prevents concurrent callback -// invocation. Note that it is possible for other thread to grab the primary -// lock and update flag's value at any time during the callback invocation. -// This is by design. Callback can get a value of the flag if necessary, but it -// might be different from the value initiated the callback and it also can be -// different by the time the callback invocation is completed. -// Requires that *primary_lock be held in exclusive mode; it may be released -// and reacquired by the implementation. -void UpdateCopy(CommandLineFlag* flag); -// Return true iff flag value was changed via direct-access. -bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b); + private: + // Copy-construct a new value of the flag's type in a memory referenced by + // the dst based on the current flag's value. + virtual void Read(void* dst) const = 0; +}; // This macro is the "source of truth" for the list of supported flag types we // expect to perform lock free operations on. Specifically it generates code, -- cgit v1.2.3