about summary refs log tree commit diff
path: root/absl/flags
diff options
context:
space:
mode:
Diffstat (limited to 'absl/flags')
-rw-r--r--absl/flags/BUILD.bazel1
-rw-r--r--absl/flags/CMakeLists.txt1
-rw-r--r--absl/flags/internal/flag.cc29
-rw-r--r--absl/flags/internal/flag.h19
4 files changed, 20 insertions, 30 deletions
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index d2ca5c6f8317..cdb4e7e8fe78 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -41,6 +41,7 @@ cc_library(
         ":config",
         ":handle",
         ":registry",
+        "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/memory",
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index 20e66825a0aa..1d25f0ded8b1 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -27,6 +27,7 @@ absl_cc_library(
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::base
     absl::config
     absl::flags_config
     absl::flags_handle
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc
index ba70da91af3b..721e411e0875 100644
--- a/absl/flags/internal/flag.cc
+++ b/absl/flags/internal/flag.cc
@@ -80,41 +80,22 @@ class MutexRelock {
   absl::Mutex* mu_;
 };
 
-// This global lock guards the initialization and destruction of data_guard_,
-// which is used to guard the other Flag data.
-ABSL_CONST_INIT static absl::Mutex flag_mutex_lifetime_guard(absl::kConstInit);
-
 }  // namespace
 
 void FlagImpl::Init() {
-  {
-    absl::MutexLock lock(&flag_mutex_lifetime_guard);
-
-    // Must initialize data guard for this flag.
-    if (!is_data_guard_inited_) {
-      new (&data_guard_) absl::Mutex;
-      is_data_guard_inited_ = true;
-    }
-  }
+  new (&data_guard_) absl::Mutex;
 
   absl::MutexLock lock(reinterpret_cast<absl::Mutex*>(&data_guard_));
 
-  if (value_.dynamic != nullptr) {
-    inited_.store(true, std::memory_order_release);
-  } else {
-    // Need to initialize cur field.
-    value_.dynamic = MakeInitValue().release();
-    StoreAtomic();
-    inited_.store(true, std::memory_order_release);
-  }
+  value_.dynamic = MakeInitValue().release();
+  StoreAtomic();
 }
 
 // Ensures that the lazily initialized data is initialized,
 // and returns pointer to the mutex guarding flags data.
 absl::Mutex* FlagImpl::DataGuard() const {
-  if (ABSL_PREDICT_FALSE(!inited_.load(std::memory_order_acquire))) {
-    const_cast<FlagImpl*>(this)->Init();
-  }
+  absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init,
+                  const_cast<FlagImpl*>(this));
 
   // data_guard_ is initialized.
   return reinterpret_cast<absl::Mutex*>(&data_guard_);
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index ef30a22f53b8..b426ccb571a6 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -24,6 +24,7 @@
 #include <string>
 #include <type_traits>
 
+#include "absl/base/call_once.h"
 #include "absl/base/config.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/flags/config.h"
@@ -281,10 +282,8 @@ class FlagImpl {
         help_(help.source),
         help_source_kind_(static_cast<uint8_t>(help.kind)),
         def_kind_(static_cast<uint8_t>(FlagDefaultKind::kGenFunc)),
-        is_data_guard_inited_(false),
         modified_(false),
         on_command_line_(false),
-        inited_(false),
         counter_(0),
         callback_(nullptr),
         default_src_(default_value_gen),
@@ -406,20 +405,28 @@ class FlagImpl {
   // Indicates if help message was supplied as literal or generator func.
   const uint8_t help_source_kind_ : 1;
 
+  // ------------------------------------------------------------------------
+  // The bytes containing the const bitfields must not be shared with bytes
+  // containing the mutable bitfields.
+  // ------------------------------------------------------------------------
+
+  // Unique tag for absl::call_once call to initialize this flag.
+  //
+  // The placement of this variable between the immutable and mutable bitfields
+  // is important as prevents them from occupying the same byte. If you remove
+  // this variable, make sure to maintain this property.
+  absl::once_flag init_control_;
+
   // Mutable flag's state (guarded by `data_guard_`).
 
   // If def_kind_ == kDynamicValue, default_src_ holds a dynamically allocated
   // value.
   uint8_t def_kind_ : 1 ABSL_GUARDED_BY(*DataGuard());
-  // Protects against multiple concurrent constructions of `data_guard_`.
-  bool is_data_guard_inited_ : 1;
   // Has this flag's value been modified?
   bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard());
   // Has this flag been specified on command line.
   bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard());
 
-  // Indicates that the flag state is initialized.
-  std::atomic<bool> inited_;
   // Mutation counter
   int64_t counter_ ABSL_GUARDED_BY(*DataGuard());
   // Optional flag's callback and absl::Mutex to guard the invocations.