33 namespace flags_internal {
38 if (flag->IsRetired() || flag->IsAbseilFlag()) {
39 if (flag->cur)
Delete(flag->op, flag->cur);
40 if (flag->def)
Delete(flag->op, flag->def);
46 if (!flag->IsAbseilFlag()) {
65 void Register(CommandLineFlag* flag) {
66 auto& vec =
buckets_[BucketForFlag(flag->cur)];
67 if (vec.size() == vec.capacity()) {
70 vec.reserve(vec.size() * 1.25 + 0.5);
75 CommandLineFlag* FindByPtr(
const void* flag_ptr) {
76 const auto& flag_vector =
buckets_[BucketForFlag(flag_ptr)];
77 for (CommandLineFlag* entry : flag_vector) {
78 if (entry->cur == flag_ptr) {
100 static int BucketForFlag(
const void*
ptr) {
103 return reinterpret_cast<uintptr_t
>(
ptr) % kNumBuckets;
114 for (
auto& p : flags_) {
115 DestroyFlag(p.second);
146 using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
162 return global_registry;
167 class FlagRegistryLock {
170 ~FlagRegistryLock() {
fr_->Unlock(); }
179 FlagRegistryLock registry_lock(
this);
180 std::pair<FlagIterator, bool> ins =
182 if (ins.second ==
false) {
188 "Retired flag '", flag->
Name(),
189 "' was defined normally in file '",
193 }
else if (flag->
op != old_flag->
op) {
196 "' was defined more than once but with " 197 "differing types. Defined in files '",
199 "' with types '", old_flag->
Typename(),
"' and '",
200 flag->
Typename(),
"', respectively."),
209 "' was defined more than once (in files '",
216 "Something wrong with flag '", flag->
Name(),
"' in file '",
218 "' is being linked both statically and dynamically into this " 219 "executable. e.g. some files listed as srcs to a test and also " 220 "listed as srcs of some shared lib deps of the same test."),
227 if (ptr !=
nullptr) {
229 flag_ptr_map_.Register(flag);
235 if (i == flags_.end()) {
239 if (i->second->IsRetired()) {
241 absl::StrCat(
"Accessing retired flag '", name,
"'"),
false);
249 if (i == flags_.end() || !i->second->IsRetired()) {
257 return flag_ptr_map_.FindByPtr(flag_ptr);
276 for (
const SavedFlag& src : backup_registry_) {
277 Delete(src.op, src.current);
278 Delete(src.op, src.default_value);
286 assert(backup_registry_.empty());
291 saved.name = flag->
Name();
299 saved.current =
Clone(saved.op, flag->
cur);
300 saved.default_value =
Clone(saved.op, flag->
def);
303 backup_registry_.push_back(saved);
313 FlagRegistryLock frl(global_registry);
314 for (
const SavedFlag& src : backup_registry_) {
319 bool restored =
false;
326 if (flag->
counter != src.counter ||
329 Copy(src.op, src.default_value, flag->
def);
331 if (flag->
counter != src.counter ||
335 Copy(src.op, src.current, flag->
cur);
351 Unparse(src.marshalling_op, src.current)));
403 if (cmp != 0)
return cmp < 0;
410 result->
name = std::string(flag->
Name());
428 if (name.
empty())
return nullptr;
430 FlagRegistryLock frl(registry);
437 FlagRegistryLock frl(registry);
444 FlagRegistryLock frl(registry);
461 FlagRegistryLock frl(registry);
473 OUTPUT->push_back(fi);
494 "RETIRED", ops, marshalling_ops,
496 true,
nullptr,
nullptr);
504 assert(!name.
empty());
506 if (flag ==
nullptr) {
509 assert(type_is_bool);
510 *type_is_bool = flag->IsOfType<
bool>();
void Delete(FlagOpFn op, const void *obj)
std::string default_value
static constexpr HelpText FromStaticCString(const char *msg)
bool IsAbseilFlag() const
#define EXCLUSIVE_LOCK_FUNCTION(...)
void UpdateModifiedBit(CommandLineFlag *flag)
static FlagRegistry * GlobalRegistry()
void ForEachFlagUnlocked(std::function< void(CommandLineFlag *)> visitor)
std::map< absl::string_view, CommandLineFlag * > FlagMap
bool Validate(CommandLineFlag *, const void *)
static constexpr size_t kNumBuckets
class FlagSaverImpl * impl_
void * Clone(FlagOpFn op, const void *obj)
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
bool IsSpecifiedOnCommandLine() const
void GetAllFlags(std::vector< CommandLineFlagInfo > *OUTPUT)
void Unlock() UNLOCK_FUNCTION(lock_)
FlagMap::iterator FlagIterator
FlagMap::const_iterator FlagConstIterator
void *(*)(FlagOp, const void *, void *) FlagOpFn
const void * default_value
void RegisterFlag(CommandLineFlag *flag, const void *ptr)
void *(*)(FlagOp, const void *, void *, void *) FlagMarshallingOpFn
void Lock() EXCLUSIVE_LOCK_FUNCTION(lock_)
#define ABSL_INTERNAL_LOG(severity, message)
std::vector< SavedFlag > backup_registry_
std::vector< CommandLineFlag * > buckets_[kNumBuckets]
CommandLineFlag * FindCommandLineFlag(absl::string_view name)
void Copy(FlagOpFn op, const void *src, void *dst)
std::string Filename() const
std::string Unparse(FlagMarshallingOpFn op, const void *val)
#define UNLOCK_FUNCTION(...)
CommandLineFlag * FindFlagViaPtrLocked(const void *flag_ptr)
#define NO_THREAD_SAFETY_ANALYSIS
constexpr bool empty() const noexcept
bool operator()(const CommandLineFlagInfo &a, const CommandLineFlagInfo &b) const
void FillCommandLineFlagInfo(CommandLineFlag *flag, CommandLineFlagInfo *result)
void ReportUsageError(absl::string_view msg, bool is_fatal)
CommandLineFlag * FindRetiredFlagLocked(absl::string_view name)
absl::string_view Typename() const
CommandLineFlag * FindFlagLocked(absl::string_view name)
std::string current_value
CommandLineFlag * FindCommandLineV1Flag(const void *flag_ptr)
absl::string_view Name() const
bool Retire(FlagOpFn ops, FlagMarshallingOpFn marshalling_ops, const char *name)
CommandLineFlag * FindRetiredFlag(absl::string_view name)
bool IsRetiredFlag(absl::string_view name, bool *type_is_bool)
void UpdateCopy(CommandLineFlag *flag, absl::Mutex *primary_lock) EXCLUSIVE_LOCKS_REQUIRED(primary_lock)
const FlagMarshallingOpFn marshalling_op
absl::Mutex * InitFlagIfNecessary(CommandLineFlag *flag) LOCK_RETURNED(flag -> locks->primary_mu)
int compare(string_view x) const noexcept
FlagMarshallingOpFn marshalling_op
bool ChangedDirectly(CommandLineFlag *flag, const void *a, const void *b)
bool RegisterCommandLineFlag(CommandLineFlag *flag, const void *ptr)
std::string CurrentValue() const
void ForEachFlag(std::function< void(CommandLineFlag *)> visitor)
std::string DefaultValue() const