diff options
Diffstat (limited to 'absl/flags/internal')
-rw-r--r-- | absl/flags/internal/flag.cc | 29 | ||||
-rw-r--r-- | absl/flags/internal/flag.h | 19 |
2 files changed, 18 insertions, 30 deletions
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index ba70da91..721e411e 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 ef30a22f..b426ccb5 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. |