about summary refs log tree commit diff
path: root/absl/flags/internal/flag.h
diff options
context:
space:
mode:
Diffstat (limited to 'absl/flags/internal/flag.h')
-rw-r--r--absl/flags/internal/flag.h91
1 files changed, 57 insertions, 34 deletions
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index d79902543a22..947a8cadaf2d 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -119,47 +119,61 @@ constexpr flags_internal::HelpInitArg HelpArg(char) {
           flags_internal::FlagHelpSrcKind::kGenFunc};
 }
 
-// Signature for the function generating the initial flag value based (usually
+// Signature for the function generating the initial flag value (usually
 // based on default value supplied in flag's definition)
-using InitialValGenFunc = void* (*)();
+using FlagDfltGenFunc = void* (*)();
+
+union FlagDefaultSrc {
+  constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg)
+      : gen_func(gen_func_arg) {}
+
+  void* dynamic_value;
+  FlagDfltGenFunc gen_func;
+};
+
+enum class FlagDefaultSrcKind : int8_t { kDynamicValue, kGenFunc };
 
 // Signature for the mutation callback used by watched Flags
 // The callback is noexcept.
 // TODO(rogeeff): add noexcept after C++17 support is added.
 using FlagCallback = void (*)();
 
-void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
-                    FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu);
+struct DynValueDeleter {
+  void operator()(void* ptr) const { Delete(op, ptr); }
+
+  const FlagOpFn op;
+};
 
 // The class encapsulates the Flag's data and safe access to it.
 class FlagImpl {
  public:
   constexpr FlagImpl(const flags_internal::FlagOpFn op,
                      const flags_internal::FlagMarshallingOpFn marshalling_op,
-                     const flags_internal::InitialValGenFunc initial_value_gen,
+                     const flags_internal::FlagDfltGenFunc default_value_gen,
                      const HelpInitArg help)
       : op_(op),
         marshalling_op_(marshalling_op),
-        initial_value_gen_(initial_value_gen),
         help_(help.source),
-        help_source_kind_(help.kind) {}
+        help_source_kind_(help.kind),
+        def_kind_(flags_internal::FlagDefaultSrcKind::kGenFunc),
+        default_src_(default_value_gen) {}
 
   // Forces destruction of the Flag's data.
   void Destroy() const;
 
   // Constant access methods
   std::string Help() const;
-  bool IsModified() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
-  bool IsSpecifiedOnCommandLine() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
-  std::string DefaultValue() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
-  std::string CurrentValue() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
+  bool IsModified() const ABSL_LOCKS_EXCLUDED(*DataGuard());
+  bool IsSpecifiedOnCommandLine() const ABSL_LOCKS_EXCLUDED(*DataGuard());
+  std::string DefaultValue() const ABSL_LOCKS_EXCLUDED(*DataGuard());
+  std::string CurrentValue() const ABSL_LOCKS_EXCLUDED(*DataGuard());
   void Read(const CommandLineFlag& flag, void* dst,
             const flags_internal::FlagOpFn dst_op) const
-      ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
   // Attempts to parse supplied `value` std::string.
   bool TryParse(const CommandLineFlag& flag, void* dst, absl::string_view value,
                 std::string* err) const
-      ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu);
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
   template <typename T>
   bool AtomicGet(T* v) const {
     const int64_t r = atomic_.load(std::memory_order_acquire);
@@ -174,23 +188,23 @@ class FlagImpl {
   // Mutating access methods
   void Write(const CommandLineFlag& flag, const void* src,
              const flags_internal::FlagOpFn src_op)
-      ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
   bool SetFromString(const CommandLineFlag& flag, absl::string_view value,
                      FlagSettingMode set_mode, ValueSource source,
-                     std::string* err) ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
+                     std::string* err) ABSL_LOCKS_EXCLUDED(*DataGuard());
   // If possible, updates copy of the Flag's value that is stored in an
   // atomic word.
-  void StoreAtomic() ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu);
+  void StoreAtomic() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
 
   // Interfaces to operate on callbacks.
   void SetCallback(const flags_internal::FlagCallback mutation_callback)
-      ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
-  void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu);
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+  void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
 
   // Interfaces to save/restore mutable flag data
   template <typename T>
   std::unique_ptr<flags_internal::FlagStateInterface> SaveState(
-      Flag<T>* flag) const ABSL_LOCKS_EXCLUDED(locks_->primary_mu) {
+      Flag<T>* flag) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
     T&& cur_value = flag->Get();
     absl::MutexLock l(DataGuard());
 
@@ -199,13 +213,13 @@ class FlagImpl {
   }
   bool RestoreState(const CommandLineFlag& flag, const void* value,
                     bool modified, bool on_command_line, int64_t counter)
-      ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
 
   // Value validation interfaces.
   void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag) const
-      ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
   bool ValidateInputValue(absl::string_view value) const
-      ABSL_LOCKS_EXCLUDED(locks_->primary_mu);
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
 
  private:
   // Lazy initialization of the Flag's data.
@@ -214,27 +228,36 @@ class FlagImpl {
   // and returns pointer to the mutex guarding flags data.
   absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED(locks_->primary_mu);
 
+  // Returns heap allocated value of type T initialized with default value.
+  std::unique_ptr<void, DynValueDeleter> MakeInitValue() const
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
   // Immutable Flag's data.
-  const FlagOpFn op_;                          // Type-specific handler.
-  const FlagMarshallingOpFn marshalling_op_;   // Marshalling ops handler.
-  const InitialValGenFunc initial_value_gen_;  // Makes flag's initial value.
+  const FlagOpFn op_;                         // Type-specific handler.
+  const FlagMarshallingOpFn marshalling_op_;  // Marshalling ops handler.
   const FlagHelpSrc help_;  // Help message literal or function to generate it.
   // Indicates if help message was supplied as literal or generator func.
   const FlagHelpSrcKind help_source_kind_;
 
-  // Mutable Flag's data. (guarded by locks_->primary_mu).
-  // Indicates that locks_, cur_ and def_ fields have been lazily initialized.
+  // Mutable Flag's data. (guarded by DataGuard()).
+  // Indicates that locks_ and cur_ fields have been lazily initialized.
   std::atomic<bool> inited_{false};
   // Has flag value been modified?
-  bool modified_ ABSL_GUARDED_BY(locks_->primary_mu) = false;
+  bool modified_ ABSL_GUARDED_BY(*DataGuard()) = false;
   // Specified on command line.
-  bool on_command_line_ ABSL_GUARDED_BY(locks_->primary_mu) = false;
-  // Lazily initialized pointer to default value
-  void* def_ ABSL_GUARDED_BY(locks_->primary_mu) = nullptr;
+  bool on_command_line_ ABSL_GUARDED_BY(*DataGuard()) = false;
+  // If def_kind_ == kDynamicValue, default_src_ holds a dynamically allocated
+  // value.
+  FlagDefaultSrcKind def_kind_ ABSL_GUARDED_BY(*DataGuard());
+  // Either a pointer to the function generating the default value based on the
+  // value specified in ABSL_FLAG or pointer to the dynamically set default
+  // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
+  // these two cases.
+  FlagDefaultSrc default_src_ ABSL_GUARDED_BY(*DataGuard());
   // Lazily initialized pointer to current value
-  void* cur_ ABSL_GUARDED_BY(locks_->primary_mu) = nullptr;
+  void* cur_ ABSL_GUARDED_BY(*DataGuard()) = nullptr;
   // Mutation counter
-  int64_t counter_ ABSL_GUARDED_BY(locks_->primary_mu) = 0;
+  int64_t counter_ ABSL_GUARDED_BY(*DataGuard()) = 0;
   // For some types, a copy of the current value is kept in an atomically
   // accessible field.
   std::atomic<int64_t> atomic_{flags_internal::AtomicInit()};
@@ -263,7 +286,7 @@ class Flag final : public flags_internal::CommandLineFlag {
   constexpr Flag(const char* name, const flags_internal::HelpInitArg help,
                  const char* filename,
                  const flags_internal::FlagMarshallingOpFn marshalling_op,
-                 const flags_internal::InitialValGenFunc initial_value_gen)
+                 const flags_internal::FlagDfltGenFunc initial_value_gen)
       : flags_internal::CommandLineFlag(name, filename),
         impl_(&flags_internal::FlagOps<T>, marshalling_op, initial_value_gen,
               help) {}