tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

flag.cc (25022B)


      1 //
      2 // Copyright 2019 The Abseil Authors.
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      https://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 
     16 #include "absl/flags/internal/flag.h"
     17 
     18 #include <assert.h>
     19 #include <stddef.h>
     20 #include <stdint.h>
     21 #include <string.h>
     22 
     23 #include <array>
     24 #include <atomic>
     25 #include <cstring>
     26 #include <memory>
     27 #include <string>
     28 #include <typeinfo>
     29 #include <vector>
     30 
     31 #include "absl/base/attributes.h"
     32 #include "absl/base/call_once.h"
     33 #include "absl/base/casts.h"
     34 #include "absl/base/config.h"
     35 #include "absl/base/const_init.h"
     36 #include "absl/base/dynamic_annotations.h"
     37 #include "absl/base/no_destructor.h"
     38 #include "absl/base/optimization.h"
     39 #include "absl/base/thread_annotations.h"
     40 #include "absl/flags/config.h"
     41 #include "absl/flags/internal/commandlineflag.h"
     42 #include "absl/flags/usage_config.h"
     43 #include "absl/memory/memory.h"
     44 #include "absl/strings/str_cat.h"
     45 #include "absl/strings/string_view.h"
     46 #include "absl/synchronization/mutex.h"
     47 
     48 namespace absl {
     49 ABSL_NAMESPACE_BEGIN
     50 namespace flags_internal {
     51 
     52 // The help message indicating that the commandline flag has been stripped. It
     53 // will not show up when doing "-help" and its variants. The flag is stripped
     54 // if ABSL_FLAGS_STRIP_HELP is set to 1 before including absl/flags/flag.h
     55 const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
     56 
     57 namespace {
     58 
     59 // Currently we only validate flag values for user-defined flag types.
     60 bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
     61 #define DONT_VALIDATE(T, _) \
     62  if (flag_type_id == base_internal::FastTypeId<T>()) return false;
     63  ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE)
     64 #undef DONT_VALIDATE
     65 
     66  return true;
     67 }
     68 
     69 // RAII helper used to temporarily unlock and relock `absl::Mutex`.
     70 // This is used when we need to ensure that locks are released while
     71 // invoking user supplied callbacks and then reacquired, since callbacks may
     72 // need to acquire these locks themselves.
     73 class MutexRelock {
     74 public:
     75  explicit MutexRelock(absl::Mutex& mu) : mu_(mu) { mu_.Unlock(); }
     76  ~MutexRelock() { mu_.Lock(); }
     77 
     78  MutexRelock(const MutexRelock&) = delete;
     79  MutexRelock& operator=(const MutexRelock&) = delete;
     80 
     81 private:
     82  absl::Mutex& mu_;
     83 };
     84 
     85 // This is a freelist of leaked flag values and guard for its access.
     86 // When we can't guarantee it is safe to reuse the memory for flag values,
     87 // we move the memory to the freelist where it lives indefinitely, so it can
     88 // still be safely accessed. This also prevents leak checkers from complaining
     89 // about the leaked memory that can no longer be accessed through any pointer.
     90 absl::Mutex* FreelistMutex() {
     91  static absl::NoDestructor<absl::Mutex> mutex;
     92  return mutex.get();
     93 }
     94 ABSL_CONST_INIT std::vector<void*>* s_freelist ABSL_GUARDED_BY(FreelistMutex())
     95    ABSL_PT_GUARDED_BY(FreelistMutex()) = nullptr;
     96 
     97 void AddToFreelist(void* p) {
     98  absl::MutexLock l(FreelistMutex());
     99  if (!s_freelist) {
    100    s_freelist = new std::vector<void*>;
    101  }
    102  s_freelist->push_back(p);
    103 }
    104 
    105 }  // namespace
    106 
    107 ///////////////////////////////////////////////////////////////////////////////
    108 
    109 uint64_t NumLeakedFlagValues() {
    110  absl::MutexLock l(FreelistMutex());
    111  return s_freelist == nullptr ? 0u : s_freelist->size();
    112 }
    113 
    114 ///////////////////////////////////////////////////////////////////////////////
    115 // Persistent state of the flag data.
    116 
    117 class FlagImpl;
    118 
    119 class FlagState : public flags_internal::FlagStateInterface {
    120 public:
    121  template <typename V>
    122  FlagState(FlagImpl& flag_impl, const V& v, bool modified,
    123            bool on_command_line, int64_t counter)
    124      : flag_impl_(flag_impl),
    125        value_(v),
    126        modified_(modified),
    127        on_command_line_(on_command_line),
    128        counter_(counter) {}
    129 
    130  ~FlagState() override {
    131    if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kHeapAllocated &&
    132        flag_impl_.ValueStorageKind() != FlagValueStorageKind::kSequenceLocked)
    133      return;
    134    flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);
    135  }
    136 
    137 private:
    138  friend class FlagImpl;
    139 
    140  // Restores the flag to the saved state.
    141  void Restore() const override {
    142    if (!flag_impl_.RestoreState(*this)) return;
    143 
    144    ABSL_INTERNAL_LOG(INFO,
    145                      absl::StrCat("Restore saved value of ", flag_impl_.Name(),
    146                                   " to: ", flag_impl_.CurrentValue()));
    147  }
    148 
    149  // Flag and saved flag data.
    150  FlagImpl& flag_impl_;
    151  union SavedValue {
    152    explicit SavedValue(void* v) : heap_allocated(v) {}
    153    explicit SavedValue(int64_t v) : one_word(v) {}
    154 
    155    void* heap_allocated;
    156    int64_t one_word;
    157  } value_;
    158  bool modified_;
    159  bool on_command_line_;
    160  int64_t counter_;
    161 };
    162 
    163 ///////////////////////////////////////////////////////////////////////////////
    164 // Flag implementation, which does not depend on flag value type.
    165 
    166 DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {}
    167 
    168 void DynValueDeleter::operator()(void* ptr) const {
    169  if (op == nullptr) return;
    170 
    171  Delete(op, ptr);
    172 }
    173 
    174 MaskedPointer::MaskedPointer(ptr_t rhs, bool is_candidate) : ptr_(rhs) {
    175  if (is_candidate) {
    176    ApplyMask(kUnprotectedReadCandidate);
    177  }
    178 }
    179 
    180 bool MaskedPointer::IsUnprotectedReadCandidate() const {
    181  return CheckMask(kUnprotectedReadCandidate);
    182 }
    183 
    184 bool MaskedPointer::HasBeenRead() const { return CheckMask(kHasBeenRead); }
    185 
    186 void MaskedPointer::Set(FlagOpFn op, const void* src, bool is_candidate) {
    187  flags_internal::Copy(op, src, Ptr());
    188  if (is_candidate) {
    189    ApplyMask(kUnprotectedReadCandidate);
    190  }
    191 }
    192 void MaskedPointer::MarkAsRead() { ApplyMask(kHasBeenRead); }
    193 
    194 void MaskedPointer::ApplyMask(mask_t mask) {
    195  ptr_ = reinterpret_cast<ptr_t>(reinterpret_cast<mask_t>(ptr_) | mask);
    196 }
    197 bool MaskedPointer::CheckMask(mask_t mask) const {
    198  return (reinterpret_cast<mask_t>(ptr_) & mask) != 0;
    199 }
    200 
    201 void FlagImpl::Init() {
    202  new (&data_guard_) absl::Mutex;
    203 
    204  auto def_kind = static_cast<FlagDefaultKind>(def_kind_);
    205 
    206  switch (ValueStorageKind()) {
    207    case FlagValueStorageKind::kValueAndInitBit:
    208    case FlagValueStorageKind::kOneWordAtomic: {
    209      alignas(int64_t) std::array<char, sizeof(int64_t)> buf{};
    210      if (def_kind == FlagDefaultKind::kGenFunc) {
    211        (*default_value_.gen_func)(buf.data());
    212      } else {
    213        assert(def_kind != FlagDefaultKind::kDynamicValue);
    214        std::memcpy(buf.data(), &default_value_, Sizeof(op_));
    215      }
    216      if (ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit) {
    217        // We presume here the memory layout of FlagValueAndInitBit struct.
    218        uint8_t initialized = 1;
    219        std::memcpy(buf.data() + Sizeof(op_), &initialized,
    220                    sizeof(initialized));
    221      }
    222      // Type can contain valid uninitialized bits, e.g. padding.
    223      ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(buf.data(), buf.size());
    224      OneWordValue().store(absl::bit_cast<int64_t>(buf),
    225                           std::memory_order_release);
    226      break;
    227    }
    228    case FlagValueStorageKind::kSequenceLocked: {
    229      // For this storage kind the default_value_ always points to gen_func
    230      // during initialization.
    231      assert(def_kind == FlagDefaultKind::kGenFunc);
    232      (*default_value_.gen_func)(AtomicBufferValue());
    233      break;
    234    }
    235    case FlagValueStorageKind::kHeapAllocated:
    236      // For this storage kind the default_value_ always points to gen_func
    237      // during initialization.
    238      assert(def_kind == FlagDefaultKind::kGenFunc);
    239      // Flag value initially points to the internal buffer.
    240      MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire);
    241      (*default_value_.gen_func)(ptr_value.Ptr());
    242      // Default value is a candidate for an unprotected read.
    243      PtrStorage().store(MaskedPointer(ptr_value.Ptr(), true),
    244                         std::memory_order_release);
    245      break;
    246  }
    247  seq_lock_.MarkInitialized();
    248 }
    249 
    250 absl::Mutex* FlagImpl::DataGuard() const {
    251  absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init,
    252                  const_cast<FlagImpl*>(this));
    253 
    254  // data_guard_ is initialized inside Init.
    255  return reinterpret_cast<absl::Mutex*>(&data_guard_);
    256 }
    257 
    258 void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id,
    259                               const std::type_info* (*gen_rtti)()) const {
    260  FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_);
    261 
    262  // `rhs_type_id` is the fast type id corresponding to the declaration
    263  // visible at the call site. `lhs_type_id` is the fast type id
    264  // corresponding to the type specified in flag definition. They must match
    265  //  for this operation to be well-defined.
    266  if (ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return;
    267 
    268  const std::type_info* lhs_runtime_type_id =
    269      flags_internal::RuntimeTypeId(op_);
    270  const std::type_info* rhs_runtime_type_id = (*gen_rtti)();
    271 
    272  if (lhs_runtime_type_id == rhs_runtime_type_id) return;
    273 
    274 #ifdef ABSL_INTERNAL_HAS_RTTI
    275  if (*lhs_runtime_type_id == *rhs_runtime_type_id) return;
    276 #endif
    277 
    278  ABSL_INTERNAL_LOG(
    279      FATAL, absl::StrCat("Flag '", Name(),
    280                          "' is defined as one type and declared as another"));
    281 }
    282 
    283 std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {
    284  void* res = nullptr;
    285  switch (DefaultKind()) {
    286    case FlagDefaultKind::kDynamicValue:
    287      res = flags_internal::Clone(op_, default_value_.dynamic_value);
    288      break;
    289    case FlagDefaultKind::kGenFunc:
    290      res = flags_internal::Alloc(op_);
    291      (*default_value_.gen_func)(res);
    292      break;
    293    default:
    294      res = flags_internal::Clone(op_, &default_value_);
    295      break;
    296  }
    297  return {res, DynValueDeleter{op_}};
    298 }
    299 
    300 void FlagImpl::StoreValue(const void* src, ValueSource source) {
    301  switch (ValueStorageKind()) {
    302    case FlagValueStorageKind::kValueAndInitBit:
    303    case FlagValueStorageKind::kOneWordAtomic: {
    304      // Load the current value to avoid setting 'init' bit manually.
    305      int64_t one_word_val = OneWordValue().load(std::memory_order_acquire);
    306      std::memcpy(&one_word_val, src, Sizeof(op_));
    307      OneWordValue().store(one_word_val, std::memory_order_release);
    308      seq_lock_.IncrementModificationCount();
    309      break;
    310    }
    311    case FlagValueStorageKind::kSequenceLocked: {
    312      seq_lock_.Write(AtomicBufferValue(), src, Sizeof(op_));
    313      break;
    314    }
    315    case FlagValueStorageKind::kHeapAllocated:
    316      MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire);
    317 
    318      if (ptr_value.IsUnprotectedReadCandidate() && ptr_value.HasBeenRead()) {
    319        // If current value is a candidate for an unprotected read and if it was
    320        // already read at least once, follow up reads (if any) are done without
    321        // mutex protection. We can't guarantee it is safe to reuse this memory
    322        // since it may have been accessed by another thread concurrently, so
    323        // instead we move the memory to a freelist so it can still be safely
    324        // accessed, and allocate a new one for the new value.
    325        AddToFreelist(ptr_value.Ptr());
    326        ptr_value = MaskedPointer(Clone(op_, src), source == kCommandLine);
    327      } else {
    328        // Current value either was set programmatically or was never read.
    329        // We can reuse the memory since all accesses to this value (if any)
    330        // were protected by mutex. That said, if a new value comes from command
    331        // line it now becomes a candidate for an unprotected read.
    332        ptr_value.Set(op_, src, source == kCommandLine);
    333      }
    334 
    335      PtrStorage().store(ptr_value, std::memory_order_release);
    336      seq_lock_.IncrementModificationCount();
    337      break;
    338  }
    339  modified_ = true;
    340  InvokeCallback();
    341 }
    342 
    343 absl::string_view FlagImpl::Name() const { return name_; }
    344 
    345 absl::string_view FlagImpl::TypeName() const { return type_name_; }
    346 
    347 std::string FlagImpl::Filename() const {
    348  return flags_internal::GetUsageConfig().normalize_filename(filename_);
    349 }
    350 
    351 std::string FlagImpl::Help() const {
    352  return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal
    353                                                    : help_.gen_func();
    354 }
    355 
    356 FlagFastTypeId FlagImpl::TypeId() const {
    357  return flags_internal::FastTypeId(op_);
    358 }
    359 
    360 int64_t FlagImpl::ModificationCount() const {
    361  return seq_lock_.ModificationCount();
    362 }
    363 
    364 bool FlagImpl::IsSpecifiedOnCommandLine() const {
    365  absl::MutexLock l(DataGuard());
    366  return on_command_line_;
    367 }
    368 
    369 std::string FlagImpl::DefaultValue() const {
    370  absl::MutexLock l(DataGuard());
    371 
    372  auto obj = MakeInitValue();
    373  return flags_internal::Unparse(op_, obj.get());
    374 }
    375 
    376 std::string FlagImpl::CurrentValue() const {
    377  auto* guard = DataGuard();  // Make sure flag initialized
    378  switch (ValueStorageKind()) {
    379    case FlagValueStorageKind::kValueAndInitBit:
    380    case FlagValueStorageKind::kOneWordAtomic: {
    381      const auto one_word_val =
    382          absl::bit_cast<std::array<char, sizeof(int64_t)>>(
    383              OneWordValue().load(std::memory_order_acquire));
    384      return flags_internal::Unparse(op_, one_word_val.data());
    385    }
    386    case FlagValueStorageKind::kSequenceLocked: {
    387      std::unique_ptr<void, DynValueDeleter> cloned(flags_internal::Alloc(op_),
    388                                                    DynValueDeleter{op_});
    389      ReadSequenceLockedData(cloned.get());
    390      return flags_internal::Unparse(op_, cloned.get());
    391    }
    392    case FlagValueStorageKind::kHeapAllocated: {
    393      absl::MutexLock l(guard);
    394      return flags_internal::Unparse(
    395          op_, PtrStorage().load(std::memory_order_acquire).Ptr());
    396    }
    397  }
    398 
    399  return "";
    400 }
    401 
    402 void FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) {
    403  absl::MutexLock l(DataGuard());
    404 
    405  if (callback_ == nullptr) {
    406    callback_ = new FlagCallback;
    407  }
    408  callback_->func = mutation_callback;
    409 
    410  InvokeCallback();
    411 }
    412 
    413 void FlagImpl::InvokeCallback() const {
    414  if (!callback_) return;
    415 
    416  // Make a copy of the C-style function pointer that we are about to invoke
    417  // before we release the lock guarding it.
    418  FlagCallbackFunc cb = callback_->func;
    419 
    420  // If the flag has a mutation callback this function invokes it. While the
    421  // callback is being invoked the primary flag's mutex is unlocked and it is
    422  // re-locked back after call to callback is completed. Callback invocation is
    423  // guarded by flag's secondary mutex instead which prevents concurrent
    424  // callback invocation. Note that it is possible for other thread to grab the
    425  // primary lock and update flag's value at any time during the callback
    426  // invocation. This is by design. Callback can get a value of the flag if
    427  // necessary, but it might be different from the value initiated the callback
    428  // and it also can be different by the time the callback invocation is
    429  // completed. Requires that *primary_lock be held in exclusive mode; it may be
    430  // released and reacquired by the implementation.
    431  MutexRelock relock(*DataGuard());
    432  absl::MutexLock lock(&callback_->guard);
    433  cb();
    434 }
    435 
    436 std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
    437  absl::MutexLock l(DataGuard());
    438 
    439  bool modified = modified_;
    440  bool on_command_line = on_command_line_;
    441  switch (ValueStorageKind()) {
    442    case FlagValueStorageKind::kValueAndInitBit:
    443    case FlagValueStorageKind::kOneWordAtomic: {
    444      return absl::make_unique<FlagState>(
    445          *this, OneWordValue().load(std::memory_order_acquire), modified,
    446          on_command_line, ModificationCount());
    447    }
    448    case FlagValueStorageKind::kSequenceLocked: {
    449      void* cloned = flags_internal::Alloc(op_);
    450      // Read is guaranteed to be successful because we hold the lock.
    451      bool success =
    452          seq_lock_.TryRead(cloned, AtomicBufferValue(), Sizeof(op_));
    453      assert(success);
    454      static_cast<void>(success);
    455      return absl::make_unique<FlagState>(*this, cloned, modified,
    456                                          on_command_line, ModificationCount());
    457    }
    458    case FlagValueStorageKind::kHeapAllocated: {
    459      return absl::make_unique<FlagState>(
    460          *this,
    461          flags_internal::Clone(
    462              op_, PtrStorage().load(std::memory_order_acquire).Ptr()),
    463          modified, on_command_line, ModificationCount());
    464    }
    465  }
    466  return nullptr;
    467 }
    468 
    469 bool FlagImpl::RestoreState(const FlagState& flag_state) {
    470  absl::MutexLock l(DataGuard());
    471  if (flag_state.counter_ == ModificationCount()) {
    472    return false;
    473  }
    474 
    475  switch (ValueStorageKind()) {
    476    case FlagValueStorageKind::kValueAndInitBit:
    477    case FlagValueStorageKind::kOneWordAtomic:
    478      StoreValue(&flag_state.value_.one_word, kProgrammaticChange);
    479      break;
    480    case FlagValueStorageKind::kSequenceLocked:
    481    case FlagValueStorageKind::kHeapAllocated:
    482      StoreValue(flag_state.value_.heap_allocated, kProgrammaticChange);
    483      break;
    484  }
    485 
    486  modified_ = flag_state.modified_;
    487  on_command_line_ = flag_state.on_command_line_;
    488 
    489  return true;
    490 }
    491 
    492 template <typename StorageT>
    493 StorageT* FlagImpl::OffsetValue() const {
    494  char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this));
    495  // The offset is deduced via Flag value type specific op_.
    496  ptrdiff_t offset = flags_internal::ValueOffset(op_);
    497 
    498  return reinterpret_cast<StorageT*>(p + offset);
    499 }
    500 
    501 std::atomic<uint64_t>* FlagImpl::AtomicBufferValue() const {
    502  assert(ValueStorageKind() == FlagValueStorageKind::kSequenceLocked);
    503  return OffsetValue<std::atomic<uint64_t>>();
    504 }
    505 
    506 std::atomic<int64_t>& FlagImpl::OneWordValue() const {
    507  assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic ||
    508         ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
    509  return OffsetValue<FlagOneWordValue>()->value;
    510 }
    511 
    512 std::atomic<MaskedPointer>& FlagImpl::PtrStorage() const {
    513  assert(ValueStorageKind() == FlagValueStorageKind::kHeapAllocated);
    514  return OffsetValue<FlagMaskedPointerValue>()->value;
    515 }
    516 
    517 // Attempts to parse supplied `value` string using parsing routine in the `flag`
    518 // argument. If parsing successful, this function replaces the dst with newly
    519 // parsed value. In case if any error is encountered in either step, the error
    520 // message is stored in 'err'
    521 std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(
    522    absl::string_view value, std::string& err) const {
    523  std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue();
    524 
    525  std::string parse_err;
    526  if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) {
    527    absl::string_view err_sep = parse_err.empty() ? "" : "; ";
    528    err = absl::StrCat("Illegal value '", value, "' specified for flag '",
    529                       Name(), "'", err_sep, parse_err);
    530    return nullptr;
    531  }
    532 
    533  return tentative_value;
    534 }
    535 
    536 void FlagImpl::Read(void* dst) const {
    537  auto* guard = DataGuard();  // Make sure flag initialized
    538  switch (ValueStorageKind()) {
    539    case FlagValueStorageKind::kValueAndInitBit:
    540    case FlagValueStorageKind::kOneWordAtomic: {
    541      const int64_t one_word_val =
    542          OneWordValue().load(std::memory_order_acquire);
    543      std::memcpy(dst, &one_word_val, Sizeof(op_));
    544      break;
    545    }
    546    case FlagValueStorageKind::kSequenceLocked: {
    547      ReadSequenceLockedData(dst);
    548      break;
    549    }
    550    case FlagValueStorageKind::kHeapAllocated: {
    551      absl::MutexLock l(guard);
    552      MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire);
    553 
    554      flags_internal::CopyConstruct(op_, ptr_value.Ptr(), dst);
    555 
    556      // For unprotected read candidates, mark that the value as has been read.
    557      if (ptr_value.IsUnprotectedReadCandidate() && !ptr_value.HasBeenRead()) {
    558        ptr_value.MarkAsRead();
    559        PtrStorage().store(ptr_value, std::memory_order_release);
    560      }
    561      break;
    562    }
    563  }
    564 }
    565 
    566 int64_t FlagImpl::ReadOneWord() const {
    567  assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic ||
    568         ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
    569  auto* guard = DataGuard();  // Make sure flag initialized
    570  (void)guard;
    571  return OneWordValue().load(std::memory_order_acquire);
    572 }
    573 
    574 bool FlagImpl::ReadOneBool() const {
    575  assert(ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
    576  auto* guard = DataGuard();  // Make sure flag initialized
    577  (void)guard;
    578  return absl::bit_cast<FlagValueAndInitBit<bool>>(
    579             OneWordValue().load(std::memory_order_acquire))
    580      .value;
    581 }
    582 
    583 void FlagImpl::ReadSequenceLockedData(void* dst) const {
    584  size_t size = Sizeof(op_);
    585  // Attempt to read using the sequence lock.
    586  if (ABSL_PREDICT_TRUE(seq_lock_.TryRead(dst, AtomicBufferValue(), size))) {
    587    return;
    588  }
    589  // We failed due to contention. Acquire the lock to prevent contention
    590  // and try again.
    591  absl::ReaderMutexLock l(DataGuard());
    592  bool success = seq_lock_.TryRead(dst, AtomicBufferValue(), size);
    593  assert(success);
    594  static_cast<void>(success);
    595 }
    596 
    597 void FlagImpl::Write(const void* src) {
    598  absl::MutexLock l(DataGuard());
    599 
    600  if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) {
    601    std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src),
    602                                               DynValueDeleter{op_}};
    603    std::string ignored_error;
    604    std::string src_as_str = flags_internal::Unparse(op_, src);
    605    if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) {
    606      ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(),
    607                                            "' to invalid value ", src_as_str));
    608    }
    609  }
    610 
    611  StoreValue(src, kProgrammaticChange);
    612 }
    613 
    614 // Sets the value of the flag based on specified string `value`. If the flag
    615 // was successfully set to new value, it returns true. Otherwise, sets `err`
    616 // to indicate the error, leaves the flag unchanged, and returns false. There
    617 // are three ways to set the flag's value:
    618 //  * Update the current flag value
    619 //  * Update the flag's default value
    620 //  * Update the current flag value if it was never set before
    621 // The mode is selected based on 'set_mode' parameter.
    622 bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode,
    623                         ValueSource source, std::string& err) {
    624  absl::MutexLock l(DataGuard());
    625 
    626  switch (set_mode) {
    627    case SET_FLAGS_VALUE: {
    628      // set or modify the flag's value
    629      auto tentative_value = TryParse(value, err);
    630      if (!tentative_value) return false;
    631 
    632      StoreValue(tentative_value.get(), source);
    633 
    634      if (source == kCommandLine) {
    635        on_command_line_ = true;
    636      }
    637      break;
    638    }
    639    case SET_FLAG_IF_DEFAULT: {
    640      // set the flag's value, but only if it hasn't been set by someone else
    641      if (modified_) {
    642        // TODO(rogeeff): review and fix this semantic. Currently we do not fail
    643        // in this case if flag is modified. This is misleading since the flag's
    644        // value is not updated even though we return true.
    645        // *err = absl::StrCat(Name(), " is already set to ",
    646        //                     CurrentValue(), "\n");
    647        // return false;
    648        return true;
    649      }
    650      auto tentative_value = TryParse(value, err);
    651      if (!tentative_value) return false;
    652 
    653      StoreValue(tentative_value.get(), source);
    654      break;
    655    }
    656    case SET_FLAGS_DEFAULT: {
    657      auto tentative_value = TryParse(value, err);
    658      if (!tentative_value) return false;
    659 
    660      if (DefaultKind() == FlagDefaultKind::kDynamicValue) {
    661        void* old_value = default_value_.dynamic_value;
    662        default_value_.dynamic_value = tentative_value.release();
    663        tentative_value.reset(old_value);
    664      } else {
    665        default_value_.dynamic_value = tentative_value.release();
    666        def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue);
    667      }
    668 
    669      if (!modified_) {
    670        // Need to set both default value *and* current, in this case.
    671        StoreValue(default_value_.dynamic_value, source);
    672        modified_ = false;
    673      }
    674      break;
    675    }
    676  }
    677 
    678  return true;
    679 }
    680 
    681 void FlagImpl::CheckDefaultValueParsingRoundtrip() const {
    682  std::string v = DefaultValue();
    683 
    684  absl::MutexLock lock(DataGuard());
    685 
    686  auto dst = MakeInitValue();
    687  std::string error;
    688  if (!flags_internal::Parse(op_, v, dst.get(), &error)) {
    689    ABSL_INTERNAL_LOG(
    690        FATAL,
    691        absl::StrCat("Flag ", Name(), " (from ", Filename(),
    692                     "): string form of default value '", v,
    693                     "' could not be parsed; error=", error));
    694  }
    695 
    696  // We do not compare dst to def since parsing/unparsing may make
    697  // small changes, e.g., precision loss for floating point types.
    698 }
    699 
    700 bool FlagImpl::ValidateInputValue(absl::string_view value) const {
    701  absl::MutexLock l(DataGuard());
    702 
    703  auto obj = MakeInitValue();
    704  std::string ignored_error;
    705  return flags_internal::Parse(op_, value, obj.get(), &ignored_error);
    706 }
    707 
    708 }  // namespace flags_internal
    709 ABSL_NAMESPACE_END
    710 }  // namespace absl