16 #include "absl/flags/internal/flag.h"
30 #include "absl/base/call_once.h"
31 #include "absl/base/casts.h"
32 #include "absl/base/config.h"
33 #include "absl/base/optimization.h"
34 #include "absl/flags/config.h"
35 #include "absl/flags/internal/commandlineflag.h"
36 #include "absl/flags/usage_config.h"
37 #include "absl/memory/memory.h"
38 #include "absl/strings/str_cat.h"
39 #include "absl/strings/string_view.h"
40 #include "absl/synchronization/mutex.h"
44 namespace flags_internal {
56 #define DONT_VALIDATE(T, _) \
57 if (flag_type_id == base_internal::FastTypeId<T>()) return false;
73 MutexRelock(
const MutexRelock&) =
delete;
74 MutexRelock& operator=(
const MutexRelock&) =
delete;
87 class FlagState :
public flags_internal::FlagStateInterface {
137 if (
op ==
nullptr)
return;
147 switch (ValueStorageKind()) {
152 (*default_value_.gen_func)(AlignedBufferValue());
157 (*default_value_.gen_func)(
buf.data());
162 OneWordValue().store(absl::bit_cast<int64_t>(
buf),
163 std::memory_order_release);
170 (*default_value_.gen_func)(AtomicBufferValue());
174 seq_lock_.MarkInitialized();
182 return reinterpret_cast<absl::Mutex*
>(&data_guard_);
186 const std::type_info* (*gen_rtti)())
const {
195 const std::type_info* lhs_runtime_type_id =
197 const std::type_info* rhs_runtime_type_id = (*gen_rtti)();
199 if (lhs_runtime_type_id == rhs_runtime_type_id)
return;
201 #if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
202 if (*lhs_runtime_type_id == *rhs_runtime_type_id)
return;
207 "' is defined as one type and declared as another"));
212 switch (DefaultKind()) {
218 (*default_value_.gen_func)(res);
224 return {res, DynValueDeleter{
op_}};
228 switch (ValueStorageKind()) {
230 Copy(
op_, src, AlignedBufferValue());
231 seq_lock_.IncrementModificationCount();
236 OneWordValue().store(one_word_val, std::memory_order_release);
237 seq_lock_.IncrementModificationCount();
241 seq_lock_.Write(AtomicBufferValue(), src,
Sizeof(
op_));
265 return seq_lock_.ModificationCount();
276 auto obj = MakeInitValue();
281 auto* guard = DataGuard();
282 switch (ValueStorageKind()) {
288 const auto one_word_val =
290 OneWordValue().load(std::memory_order_acquire));
295 DynValueDeleter{
op_});
296 ReadSequenceLockedData(cloned.get());
307 if (callback_ ==
nullptr) {
308 callback_ =
new FlagCallback;
310 callback_->func = mutation_callback;
316 if (!callback_)
return;
333 MutexRelock relock(*DataGuard());
343 switch (ValueStorageKind()) {
345 return absl::make_unique<FlagState>(
347 on_command_line, ModificationCount());
350 return absl::make_unique<FlagState>(
351 *
this, OneWordValue().
load(std::memory_order_acquire), modified,
352 on_command_line, ModificationCount());
358 seq_lock_.TryRead(cloned, AtomicBufferValue(),
Sizeof(
op_));
360 static_cast<void>(success);
361 return absl::make_unique<FlagState>(*
this, cloned, modified,
362 on_command_line, ModificationCount());
370 if (flag_state.counter_ == ModificationCount()) {
374 switch (ValueStorageKind()) {
377 StoreValue(flag_state.value_.heap_allocated);
380 StoreValue(&flag_state.value_.one_word);
390 template <
typename StorageT>
392 char*
p =
reinterpret_cast<char*
>(
const_cast<FlagImpl*
>(
this));
396 return reinterpret_cast<StorageT*
>(
p +
offset);
401 return OffsetValue<void>();
406 return OffsetValue<std::atomic<uint64_t>>();
411 return OffsetValue<FlagOneWordValue>()->value;
420 std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue();
426 Name(),
"'", err_sep, parse_err);
430 return tentative_value;
434 auto* guard = DataGuard();
435 switch (ValueStorageKind()) {
443 OneWordValue().load(std::memory_order_acquire);
448 ReadSequenceLockedData(
dst);
463 bool success = seq_lock_.TryRead(
dst, AtomicBufferValue(),
size);
465 static_cast<void>(success);
473 DynValueDeleter{
op_}};
478 "' to invalid value ", src_as_str));
500 auto tentative_value = TryParse(
value,
err);
501 if (!tentative_value)
return false;
503 StoreValue(tentative_value.get());
521 auto tentative_value = TryParse(
value,
err);
522 if (!tentative_value)
return false;
524 StoreValue(tentative_value.get());
528 auto tentative_value = TryParse(
value,
err);
529 if (!tentative_value)
return false;
532 void*
old_value = default_value_.dynamic_value;
533 default_value_.dynamic_value = tentative_value.release();
536 default_value_.dynamic_value = tentative_value.release();
542 StoreValue(default_value_.dynamic_value);
557 auto dst = MakeInitValue();
563 "): string form of default value '",
v,
564 "' could not be parsed; error=",
error));
574 auto obj = MakeInitValue();