aboutsummaryrefslogtreecommitdiffhomepage
path: root/absl/flags/internal/flag.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/flags/internal/flag.cc')
-rw-r--r--absl/flags/internal/flag.cc71
1 files changed, 42 insertions, 29 deletions
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc
index d087f79..435cc36 100644
--- a/absl/flags/internal/flag.cc
+++ b/absl/flags/internal/flag.cc
@@ -49,12 +49,11 @@ void FlagImpl::Init() {
absl::MutexLock lock(&locks_->primary_mu);
- if (def_ != nullptr) {
+ if (cur_ != nullptr) {
inited_.store(true, std::memory_order_release);
} else {
- // Need to initialize def and cur fields.
- def_ = (*initial_value_gen_)();
- cur_ = Clone(op_, def_);
+ // Need to initialize cur field.
+ cur_ = MakeInitValue().release();
StoreAtomic();
inited_.store(true, std::memory_order_release);
InvokeCallback();
@@ -63,8 +62,7 @@ void FlagImpl::Init() {
// Ensures that the lazily initialized data is initialized,
// and returns pointer to the mutex guarding flags data.
-absl::Mutex* FlagImpl::DataGuard() const
- ABSL_LOCK_RETURNED(locks_->primary_mu) {
+absl::Mutex* FlagImpl::DataGuard() const {
if (ABSL_PREDICT_FALSE(!inited_.load(std::memory_order_acquire))) {
const_cast<FlagImpl*>(this)->Init();
}
@@ -79,12 +77,23 @@ void FlagImpl::Destroy() const {
// Values are heap allocated for Abseil Flags.
if (cur_) Delete(op_, cur_);
- if (def_) Delete(op_, def_);
+ if (def_kind_ == FlagDefaultSrcKind::kDynamicValue)
+ Delete(op_, default_src_.dynamic_value);
}
delete locks_;
}
+std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {
+ void* res = nullptr;
+ if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) {
+ res = Clone(op_, default_src_.dynamic_value);
+ } else {
+ res = (*default_src_.gen_func)();
+ }
+ return {res, DynValueDeleter{op_}};
+}
+
std::string FlagImpl::Help() const {
return help_source_kind_ == FlagHelpSrcKind::kLiteral ? help_.literal
: help_.gen_func();
@@ -103,7 +112,8 @@ bool FlagImpl::IsSpecifiedOnCommandLine() const {
std::string FlagImpl::DefaultValue() const {
absl::MutexLock l(DataGuard());
- return Unparse(marshalling_op_, def_);
+ auto obj = MakeInitValue();
+ return Unparse(marshalling_op_, obj.get());
}
std::string FlagImpl::CurrentValue() const {
@@ -121,8 +131,7 @@ void FlagImpl::SetCallback(
InvokeCallback();
}
-void FlagImpl::InvokeCallback() const
- ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) {
+void FlagImpl::InvokeCallback() const {
if (!callback_) return;
// If the flag has a mutation callback this function invokes it. While the
@@ -172,23 +181,20 @@ bool FlagImpl::RestoreState(const CommandLineFlag& flag, const void* value,
// 'dst' assuming it is a pointer to the flag's value type. In case if any error
// is encountered in either step, the error message is stored in 'err'
bool FlagImpl::TryParse(const CommandLineFlag& flag, void* dst,
- absl::string_view value, std::string* err) const
- ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) {
- void* tentative_value = Clone(op_, def_);
+ absl::string_view value, std::string* err) const {
+ auto tentative_value = MakeInitValue();
std::string parse_err;
- if (!Parse(marshalling_op_, value, tentative_value, &parse_err)) {
+ if (!Parse(marshalling_op_, value, tentative_value.get(), &parse_err)) {
auto type_name = flag.Typename();
absl::string_view err_sep = parse_err.empty() ? "" : "; ";
absl::string_view typename_sep = type_name.empty() ? "" : " ";
*err = absl::StrCat("Illegal value '", value, "' specified for",
typename_sep, type_name, " flag '", flag.Name(), "'",
err_sep, parse_err);
- Delete(op_, tentative_value);
return false;
}
- Copy(op_, tentative_value, dst);
- Delete(op_, tentative_value);
+ Copy(op_, tentative_value.get(), dst);
return true;
}
@@ -208,7 +214,7 @@ void FlagImpl::Read(const CommandLineFlag& flag, void* dst,
CopyConstruct(op_, cur_, dst);
}
-void FlagImpl::StoreAtomic() ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) {
+void FlagImpl::StoreAtomic() {
size_t data_size = Sizeof(op_);
if (data_size <= sizeof(int64_t)) {
@@ -299,12 +305,22 @@ bool FlagImpl::SetFromString(const CommandLineFlag& flag,
break;
}
case SET_FLAGS_DEFAULT: {
- // modify the flag's default-value
- if (!TryParse(flag, def_, value, err)) return false;
+ // Flag's new default-value.
+ auto new_default_value = MakeInitValue();
+
+ if (!TryParse(flag, new_default_value.get(), value, err)) return false;
+
+ if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) {
+ // Release old default value.
+ Delete(op_, default_src_.dynamic_value);
+ }
+
+ default_src_.dynamic_value = new_default_value.release();
+ def_kind_ = FlagDefaultSrcKind::kDynamicValue;
if (!modified_) {
// Need to set both default value *and* current, in this case
- Copy(op_, def_, cur_);
+ Copy(op_, default_src_.dynamic_value, cur_);
StoreAtomic();
InvokeCallback();
}
@@ -321,9 +337,9 @@ void FlagImpl::CheckDefaultValueParsingRoundtrip(
absl::MutexLock lock(DataGuard());
- void* dst = Clone(op_, def_);
+ auto dst = MakeInitValue();
std::string error;
- if (!flags_internal::Parse(marshalling_op_, v, dst, &error)) {
+ if (!flags_internal::Parse(marshalling_op_, v, dst.get(), &error)) {
ABSL_INTERNAL_LOG(
FATAL,
absl::StrCat("Flag ", flag.Name(), " (from ", flag.Filename(),
@@ -333,18 +349,15 @@ void FlagImpl::CheckDefaultValueParsingRoundtrip(
// We do not compare dst to def since parsing/unparsing may make
// small changes, e.g., precision loss for floating point types.
- Delete(op_, dst);
}
bool FlagImpl::ValidateInputValue(absl::string_view value) const {
absl::MutexLock l(DataGuard());
- void* obj = Clone(op_, def_);
+ auto obj = MakeInitValue();
std::string ignored_error;
- const bool result =
- flags_internal::Parse(marshalling_op_, value, obj, &ignored_error);
- Delete(op_, obj);
- return result;
+ return flags_internal::Parse(marshalling_op_, value, obj.get(),
+ &ignored_error);
}
} // namespace flags_internal