abseil-cpp/absl/flags/reflection.cc
Go to the documentation of this file.
1 //
2 // Copyright 2020 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/reflection.h"
17 
18 #include <assert.h>
19 
20 #include <atomic>
21 #include <string>
22 
23 #include "absl/base/config.h"
24 #include "absl/base/thread_annotations.h"
25 #include "absl/container/flat_hash_map.h"
26 #include "absl/flags/commandlineflag.h"
27 #include "absl/flags/internal/private_handle_accessor.h"
28 #include "absl/flags/internal/registry.h"
29 #include "absl/flags/usage_config.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/string_view.h"
32 #include "absl/synchronization/mutex.h"
33 
34 namespace absl {
36 namespace flags_internal {
37 
38 // --------------------------------------------------------------------
39 // FlagRegistry
40 // A FlagRegistry singleton object holds all flag objects indexed by their
41 // names so that if you know a flag's name, you can access or set it. If the
42 // function is named FooLocked(), you must own the registry lock before
43 // calling the function; otherwise, you should *not* hold the lock, and the
44 // function will acquire it itself if needed.
45 // --------------------------------------------------------------------
46 
47 class FlagRegistry {
48  public:
49  FlagRegistry() = default;
50  ~FlagRegistry() = default;
51 
52  // Store a flag in this registry. Takes ownership of *flag.
53  void RegisterFlag(CommandLineFlag& flag, const char* filename);
54 
57 
58  // Returns the flag object for the specified name, or nullptr if not found.
59  // Will emit a warning if a 'retired' flag is specified.
61 
62  static FlagRegistry& GlobalRegistry(); // returns a singleton registry
63 
64  private:
65  friend class flags_internal::FlagSaverImpl; // reads all the flags in order
66  // to copy them
67  friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
68  friend void FinalizeRegistry();
69 
70  // The map from name to flag, for FindFlag().
73  using FlagConstIterator = FlagMap::const_iterator;
75  std::vector<CommandLineFlag*> flat_flags_;
76  std::atomic<bool> finalized_flags_{false};
77 
79 
80  // Disallow
81  FlagRegistry(const FlagRegistry&);
83 };
84 
85 namespace {
86 
87 class FlagRegistryLock {
88  public:
89  explicit FlagRegistryLock(FlagRegistry& fr) : fr_(fr) { fr_.Lock(); }
90  ~FlagRegistryLock() { fr_.Unlock(); }
91 
92  private:
93  FlagRegistry& fr_;
94 };
95 
96 } // namespace
97 
99  if (finalized_flags_.load(std::memory_order_acquire)) {
100  // We could save some gcus here if we make `Name()` be non-virtual.
101  // We could move the `const char*` name to the base class.
102  auto it = std::partition_point(
103  flat_flags_.begin(), flat_flags_.end(),
104  [=](CommandLineFlag* f) { return f->Name() < name; });
105  if (it != flat_flags_.end() && (*it)->Name() == name) return *it;
106  }
107 
108  FlagRegistryLock frl(*this);
109  auto it = flags_.find(name);
110  return it != flags_.end() ? it->second : nullptr;
111 }
112 
114  if (filename != nullptr &&
115  flag.Filename() != GetUsageConfig().normalize_filename(filename)) {
117  absl::StrCat(
118  "Inconsistency between flag object and registration for flag '",
119  flag.Name(),
120  "', likely due to duplicate flags or an ODR violation. Relevant "
121  "files: ",
122  flag.Filename(), " and ", filename),
123  true);
124  std::exit(1);
125  }
126 
127  FlagRegistryLock registry_lock(*this);
128 
129  std::pair<FlagIterator, bool> ins =
130  flags_.insert(FlagMap::value_type(flag.Name(), &flag));
131  if (ins.second == false) { // means the name was already in the map
132  CommandLineFlag& old_flag = *ins.first->second;
133  if (flag.IsRetired() != old_flag.IsRetired()) {
134  // All registrations must agree on the 'retired' flag.
136  absl::StrCat(
137  "Retired flag '", flag.Name(), "' was defined normally in file '",
138  (flag.IsRetired() ? old_flag.Filename() : flag.Filename()), "'."),
139  true);
143  absl::StrCat("Flag '", flag.Name(),
144  "' was defined more than once but with "
145  "differing types. Defined in files '",
146  old_flag.Filename(), "' and '", flag.Filename(), "'."),
147  true);
148  } else if (old_flag.IsRetired()) {
149  return;
150  } else if (old_flag.Filename() != flag.Filename()) {
152  absl::StrCat("Flag '", flag.Name(),
153  "' was defined more than once (in files '",
154  old_flag.Filename(), "' and '", flag.Filename(), "')."),
155  true);
156  } else {
158  absl::StrCat(
159  "Something is wrong with flag '", flag.Name(), "' in file '",
160  flag.Filename(), "'. One possibility: file '", flag.Filename(),
161  "' is being linked both statically and dynamically into this "
162  "executable. e.g. some files listed as srcs to a test and also "
163  "listed as srcs of some shared lib deps of the same test."),
164  true);
165  }
166  // All cases above are fatal, except for the retired flags.
167  std::exit(1);
168  }
169 }
170 
172  static FlagRegistry* global_registry = new FlagRegistry;
173  return *global_registry;
174 }
175 
176 // --------------------------------------------------------------------
177 
180 
181  if (registry.finalized_flags_.load(std::memory_order_acquire)) {
182  for (const auto& i : registry.flat_flags_) visitor(*i);
183  }
184 
185  FlagRegistryLock frl(registry);
186  for (const auto& i : registry.flags_) visitor(*i.second);
187 }
188 
189 // --------------------------------------------------------------------
190 
193  return true;
194 }
195 
197  auto& registry = FlagRegistry::GlobalRegistry();
198  FlagRegistryLock frl(registry);
199  if (registry.finalized_flags_.load(std::memory_order_relaxed)) {
200  // Was already finalized. Ignore the second time.
201  return;
202  }
203  registry.flat_flags_.reserve(registry.flags_.size());
204  for (const auto& f : registry.flags_) {
205  registry.flat_flags_.push_back(f.second);
206  }
207  std::sort(std::begin(registry.flat_flags_), std::end(registry.flat_flags_),
208  [](const CommandLineFlag* lhs, const CommandLineFlag* rhs) {
209  return lhs->Name() < rhs->Name();
210  });
211  registry.flags_.clear();
212  registry.finalized_flags_.store(true, std::memory_order_release);
213 }
214 
215 // --------------------------------------------------------------------
216 
217 namespace {
218 
219 class RetiredFlagObj final : public CommandLineFlag {
220  public:
221  constexpr RetiredFlagObj(const char* name, FlagFastTypeId type_id)
222  : name_(name), type_id_(type_id) {}
223 
224  private:
225  absl::string_view Name() const override { return name_; }
226  std::string Filename() const override {
227  OnAccess();
228  return "RETIRED";
229  }
230  FlagFastTypeId TypeId() const override { return type_id_; }
231  std::string Help() const override {
232  OnAccess();
233  return "";
234  }
235  bool IsRetired() const override { return true; }
236  bool IsSpecifiedOnCommandLine() const override {
237  OnAccess();
238  return false;
239  }
240  std::string DefaultValue() const override {
241  OnAccess();
242  return "";
243  }
244  std::string CurrentValue() const override {
245  OnAccess();
246  return "";
247  }
248 
249  // Any input is valid
250  bool ValidateInputValue(absl::string_view) const override {
251  OnAccess();
252  return true;
253  }
254 
255  std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override {
256  return nullptr;
257  }
258 
261  OnAccess();
262  return false;
263  }
264 
265  void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); }
266 
267  void Read(void*) const override { OnAccess(); }
268 
269  void OnAccess() const {
271  absl::StrCat("Accessing retired flag '", name_, "'"), false);
272  }
273 
274  // Data members
275  const char* const name_;
277 };
278 
279 } // namespace
280 
281 void Retire(const char* name, FlagFastTypeId type_id, char* buf) {
282  static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, "");
283  static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, "");
284  auto* flag = ::new (static_cast<void*>(buf))
285  flags_internal::RetiredFlagObj(name, type_id);
287 }
288 
289 // --------------------------------------------------------------------
290 
292  public:
293  FlagSaverImpl() = default;
294  FlagSaverImpl(const FlagSaverImpl&) = delete;
295  void operator=(const FlagSaverImpl&) = delete;
296 
297  // Saves the flag states from the flag registry into this object.
298  // It's an error to call this more than once.
300  assert(backup_registry_.empty()); // call only once!
302  if (auto flag_state =
304  backup_registry_.emplace_back(std::move(flag_state));
305  }
306  });
307  }
308 
309  // Restores the saved flag states into the flag registry.
311  for (const auto& flag_state : backup_registry_) {
312  flag_state->Restore();
313  }
314  }
315 
316  private:
317  std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>
319 };
320 
321 } // namespace flags_internal
322 
323 FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) {
325 }
326 
328  if (!impl_) return;
329 
331  delete impl_;
332 }
333 
334 // --------------------------------------------------------------------
335 
337  if (name.empty()) return nullptr;
338  flags_internal::FlagRegistry& registry =
340  return registry.FindFlag(name);
341 }
342 
343 // --------------------------------------------------------------------
344 
348  if (!flag.IsRetired()) res.insert({flag.Name(), &flag});
349  });
350  return res;
351 }
352 
354 } // namespace absl
absl::flags_internal::FlagSettingMode
FlagSettingMode
Definition: abseil-cpp/absl/flags/internal/commandlineflag.h:34
flag
uint32_t flag
Definition: ssl_versions.cc:162
absl::flags_internal::kRetiredFlagObjSize
constexpr size_t kRetiredFlagObjSize
Definition: abseil-cpp/absl/flags/internal/registry.h:78
filename
const char * filename
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
absl::flags_internal::FlagRegistry::RegisterFlag
void RegisterFlag(CommandLineFlag &flag, const char *filename)
Definition: abseil-cpp/absl/flags/reflection.cc:113
regen-readme.it
it
Definition: regen-readme.py:15
absl::flags_internal::RegisterCommandLineFlag
bool RegisterCommandLineFlag(CommandLineFlag &, const char *filename)
Definition: abseil-cpp/absl/flags/reflection.cc:191
absl::flags_internal::FlagRegistry::operator=
FlagRegistry & operator=(const FlagRegistry &)
Filename
static std::string Filename(const protobuf::FileDescriptor *file)
Definition: upbc.cc:53
absl::flags_internal::PrivateHandleAccessor::SaveState
static std::unique_ptr< FlagStateInterface > SaveState(CommandLineFlag &flag)
Definition: abseil-cpp/absl/flags/internal/private_handle_accessor.cc:34
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
begin
char * begin
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1007
absl::flags_internal::FlagRegistry::lock_
absl::Mutex lock_
Definition: abseil-cpp/absl/flags/reflection.cc:78
absl::flags_internal::FlagSaverImpl::operator=
void operator=(const FlagSaverImpl &)=delete
absl::Mutex
Definition: abseil-cpp/absl/synchronization/mutex.h:131
absl::flags_internal::FlagFastTypeId
absl::base_internal::FastTypeIdType FlagFastTypeId
Definition: abseil-cpp/absl/flags/internal/commandlineflag.h:31
absl::CommandLineFlag::IsRetired
virtual bool IsRetired() const
Definition: abseil-cpp/absl/flags/commandlineflag.cc:27
absl::flags_internal::FlagRegistry::FlagIterator
FlagMap::iterator FlagIterator
Definition: abseil-cpp/absl/flags/reflection.cc:72
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::flags_internal::FlagRegistry::FindFlag
CommandLineFlag * FindFlag(absl::string_view name)
Definition: abseil-cpp/absl/flags/reflection.cc:98
absl::flags_internal::FlagRegistry::GlobalRegistry
static FlagRegistry & GlobalRegistry()
Definition: abseil-cpp/absl/flags/reflection.cc:171
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
testing::internal::TypeId
const typedef void * TypeId
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h:405
absl::Mutex::Unlock
void Unlock() ABSL_UNLOCK_FUNCTION()
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
absl::flags_internal::FlagRegistry::flat_flags_
std::vector< CommandLineFlag * > flat_flags_
Definition: abseil-cpp/absl/flags/reflection.cc:75
absl::FindCommandLineFlag
CommandLineFlag * FindCommandLineFlag(absl::string_view name)
Definition: abseil-cpp/absl/flags/reflection.cc:336
setup.name
name
Definition: setup.py:542
env.new
def new
Definition: env.py:51
absl::CommandLineFlag
Definition: abseil-cpp/absl/flags/commandlineflag.h:62
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
iterator
const typedef MCPhysReg * iterator
Definition: MCRegisterInfo.h:27
absl::flags_internal::FlagRegistry::finalized_flags_
std::atomic< bool > finalized_flags_
Definition: abseil-cpp/absl/flags/reflection.cc:76
absl::flags_internal::FlagSaverImpl::backup_registry_
std::vector< std::unique_ptr< flags_internal::FlagStateInterface > > backup_registry_
Definition: abseil-cpp/absl/flags/reflection.cc:318
absl::flags_internal::FinalizeRegistry
void FinalizeRegistry()
Definition: abseil-cpp/absl/flags/reflection.cc:196
absl::flags_internal::FlagSaverImpl::FlagSaverImpl
FlagSaverImpl()=default
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::flags_internal::FlagRegistry::FinalizeRegistry
friend void FinalizeRegistry()
Definition: abseil-cpp/absl/flags/reflection.cc:196
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
testing::internal::posix::Read
int Read(int fd, void *buf, unsigned int count)
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2044
impl_
std::shared_ptr< ExternalConnectionAcceptorImpl > impl_
Definition: external_connection_acceptor_impl.cc:43
absl::flags_internal::FlagRegistry
Definition: abseil-cpp/absl/flags/reflection.cc:47
absl::flags_internal::FlagRegistry::FlagRegistry
FlagRegistry()=default
absl::flags_internal::ReportUsageError
void ReportUsageError(absl::string_view msg, bool is_fatal)
Definition: abseil-cpp/absl/flags/usage_config.cc:128
absl::Mutex::Lock
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION()
absl::flags_internal::FlagRegistry::ForEachFlag
friend void ForEachFlag(std::function< void(CommandLineFlag &)> visitor)
Definition: abseil-cpp/absl/flags/reflection.cc:178
absl::FlagSaver::impl_
flags_internal::FlagSaverImpl * impl_
Definition: abseil-cpp/absl/flags/reflection.h:82
absl::flags_internal::ForEachFlag
void ForEachFlag(std::function< void(CommandLineFlag &)> visitor)
Definition: abseil-cpp/absl/flags/reflection.cc:178
absl::compare_internal::value_type
int8_t value_type
Definition: abseil-cpp/absl/types/compare.h:45
absl::FlagSaver::FlagSaver
FlagSaver()
Definition: abseil-cpp/absl/flags/reflection.cc:323
google::protobuf::compiler::cpp::DefaultValue
std::string DefaultValue(const FieldDescriptor *field)
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc:622
absl::flags_internal::FlagSaverImpl::RestoreToRegistry
void RestoreToRegistry()
Definition: abseil-cpp/absl/flags/reflection.cc:310
absl::flags_internal::PrivateHandleAccessor::TypeId
static FlagFastTypeId TypeId(const CommandLineFlag &flag)
Definition: abseil-cpp/absl/flags/internal/private_handle_accessor.cc:30
absl::flags_internal::FlagRegistry::Lock
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_)
Definition: abseil-cpp/absl/flags/reflection.cc:55
absl::CommandLineFlag::Filename
virtual std::string Filename() const =0
absl::flags_internal::ValueSource
ValueSource
Definition: abseil-cpp/absl/flags/internal/commandlineflag.h:47
ABSL_EXCLUSIVE_LOCK_FUNCTION
#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...)
Definition: abseil-cpp/absl/base/thread_annotations.h:207
absl::flags_internal::FlagSaverImpl
Definition: abseil-cpp/absl/flags/reflection.cc:291
absl::flags_internal::FlagSaverImpl::SaveFromRegistry
void SaveFromRegistry()
Definition: abseil-cpp/absl/flags/reflection.cc:299
absl::flags_internal::GetUsageConfig
FlagsUsageConfig GetUsageConfig()
Definition: abseil-cpp/absl/flags/usage_config.cc:113
absl::flat_hash_map< absl::string_view, CommandLineFlag * >
absl::FlagSaver::~FlagSaver
~FlagSaver()
Definition: abseil-cpp/absl/flags/reflection.cc:327
absl::flags_internal::FlagRegistry::FlagConstIterator
FlagMap::const_iterator FlagConstIterator
Definition: abseil-cpp/absl/flags/reflection.cc:73
fr_
FlagRegistry & fr_
Definition: abseil-cpp/absl/flags/reflection.cc:93
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::flags_internal::kRetiredFlagObjAlignment
constexpr size_t kRetiredFlagObjAlignment
Definition: abseil-cpp/absl/flags/internal/registry.h:79
type_id_
const FlagFastTypeId type_id_
Definition: abseil-cpp/absl/flags/reflection.cc:276
absl::flags_internal::FlagRegistry::~FlagRegistry
~FlagRegistry()=default
function
std::function< bool(GrpcTool *, int, const char **, const CliCredentials &, GrpcToolOutputCallback)> function
Definition: grpc_tool.cc:250
absl::flags_internal::FlagRegistry::flags_
FlagMap flags_
Definition: abseil-cpp/absl/flags/reflection.cc:74
absl::flags_internal::Retire
void Retire(const char *name, FlagFastTypeId type_id, char *buf)
Definition: abseil-cpp/absl/flags/reflection.cc:281
ABSL_UNLOCK_FUNCTION
#define ABSL_UNLOCK_FUNCTION(...)
Definition: abseil-cpp/absl/base/thread_annotations.h:228
name_
const char *const name_
Definition: abseil-cpp/absl/flags/reflection.cc:275
absl::GetAllFlags
absl::flat_hash_map< absl::string_view, absl::CommandLineFlag * > GetAllFlags()
Definition: abseil-cpp/absl/flags/reflection.cc:345
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
absl::flags_internal::FlagRegistry::Unlock
void Unlock() ABSL_UNLOCK_FUNCTION(lock_)
Definition: abseil-cpp/absl/flags/reflection.cc:56


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:00