flag.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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. // -----------------------------------------------------------------------------
  17. // File: flag.h
  18. // -----------------------------------------------------------------------------
  19. //
  20. // This header file defines the `absl::Flag<T>` type for holding command-line
  21. // flag data, and abstractions to create, get and set such flag data.
  22. //
  23. // It is important to note that this type is **unspecified** (an implementation
  24. // detail) and you do not construct or manipulate actual `absl::Flag<T>`
  25. // instances. Instead, you define and declare flags using the
  26. // `ABSL_FLAG()` and `ABSL_DECLARE_FLAG()` macros, and get and set flag values
  27. // using the `absl::GetFlag()` and `absl::SetFlag()` functions.
  28. #ifndef ABSL_FLAGS_FLAG_H_
  29. #define ABSL_FLAGS_FLAG_H_
  30. #include <string>
  31. #include <type_traits>
  32. #include "absl/base/attributes.h"
  33. #include "absl/base/config.h"
  34. #include "absl/base/optimization.h"
  35. #include "absl/flags/config.h"
  36. #include "absl/flags/internal/flag.h"
  37. #include "absl/flags/internal/registry.h"
  38. #include "absl/strings/string_view.h"
  39. namespace absl {
  40. ABSL_NAMESPACE_BEGIN
  41. // Flag
  42. //
  43. // An `absl::Flag` holds a command-line flag value, providing a runtime
  44. // parameter to a binary. Such flags should be defined in the global namespace
  45. // and (preferably) in the module containing the binary's `main()` function.
  46. //
  47. // You should not construct and cannot use the `absl::Flag` type directly;
  48. // instead, you should declare flags using the `ABSL_DECLARE_FLAG()` macro
  49. // within a header file, and define your flag using `ABSL_FLAG()` within your
  50. // header's associated `.cc` file. Such flags will be named `FLAGS_name`.
  51. //
  52. // Example:
  53. //
  54. // .h file
  55. //
  56. // // Declares usage of a flag named "FLAGS_count"
  57. // ABSL_DECLARE_FLAG(int, count);
  58. //
  59. // .cc file
  60. //
  61. // // Defines a flag named "FLAGS_count" with a default `int` value of 0.
  62. // ABSL_FLAG(int, count, 0, "Count of items to process");
  63. //
  64. // No public methods of `absl::Flag<T>` are part of the Abseil Flags API.
  65. #if !defined(_MSC_VER) || defined(__clang__)
  66. template <typename T>
  67. using Flag = flags_internal::Flag<T>;
  68. #else
  69. // MSVC debug builds do not implement initialization with constexpr constructors
  70. // correctly. To work around this we add a level of indirection, so that the
  71. // class `absl::Flag` contains an `internal::Flag*` (instead of being an alias
  72. // to that class) and dynamically allocates an instance when necessary. We also
  73. // forward all calls to internal::Flag methods via trampoline methods. In this
  74. // setup the `absl::Flag` class does not have constructor and virtual methods,
  75. // all the data members are public and thus MSVC is able to initialize it at
  76. // link time. To deal with multiple threads accessing the flag for the first
  77. // time concurrently we use an atomic boolean indicating if flag object is
  78. // initialized. We also employ the double-checked locking pattern where the
  79. // second level of protection is a global Mutex, so if two threads attempt to
  80. // construct the flag concurrently only one wins.
  81. // This solution is based on a recomendation here:
  82. // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html?childToView=648454#comment-648454
  83. namespace flags_internal {
  84. absl::Mutex* GetGlobalConstructionGuard();
  85. } // namespace flags_internal
  86. template <typename T>
  87. class Flag {
  88. public:
  89. // No constructor and destructor to ensure this is an aggregate type.
  90. // Visual Studio 2015 still requires the constructor for class to be
  91. // constexpr initializable.
  92. #if _MSC_VER <= 1900
  93. constexpr Flag(const char* name, const char* filename,
  94. const flags_internal::HelpGenFunc help_gen,
  95. const flags_internal::FlagDfltGenFunc default_value_gen)
  96. : name_(name),
  97. filename_(filename),
  98. help_gen_(help_gen),
  99. default_value_gen_(default_value_gen),
  100. inited_(false),
  101. impl_(nullptr) {}
  102. #endif
  103. flags_internal::Flag<T>& GetImpl() const {
  104. if (!inited_.load(std::memory_order_acquire)) {
  105. absl::MutexLock l(flags_internal::GetGlobalConstructionGuard());
  106. if (inited_.load(std::memory_order_acquire)) {
  107. return *impl_;
  108. }
  109. impl_ = new flags_internal::Flag<T>(
  110. name_, filename_,
  111. {flags_internal::FlagHelpMsg(help_gen_),
  112. flags_internal::FlagHelpKind::kGenFunc},
  113. {flags_internal::FlagDefaultSrc(default_value_gen_),
  114. flags_internal::FlagDefaultKind::kGenFunc});
  115. inited_.store(true, std::memory_order_release);
  116. }
  117. return *impl_;
  118. }
  119. // Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API.
  120. // See https://abseil.io/docs/cpp/guides/flags
  121. bool IsRetired() const { return GetImpl().IsRetired(); }
  122. absl::string_view Name() const { return GetImpl().Name(); }
  123. std::string Help() const { return GetImpl().Help(); }
  124. bool IsModified() const { return GetImpl().IsModified(); }
  125. bool IsSpecifiedOnCommandLine() const {
  126. return GetImpl().IsSpecifiedOnCommandLine();
  127. }
  128. std::string Filename() const { return GetImpl().Filename(); }
  129. std::string DefaultValue() const { return GetImpl().DefaultValue(); }
  130. std::string CurrentValue() const { return GetImpl().CurrentValue(); }
  131. template <typename U>
  132. inline bool IsOfType() const {
  133. return GetImpl().template IsOfType<U>();
  134. }
  135. T Get() const {
  136. return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl());
  137. }
  138. void Set(const T& v) {
  139. flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v);
  140. }
  141. void InvokeCallback() { GetImpl().InvokeCallback(); }
  142. const CommandLineFlag& Reflect() const {
  143. return flags_internal::FlagImplPeer::InvokeReflect(GetImpl());
  144. }
  145. // The data members are logically private, but they need to be public for
  146. // this to be an aggregate type.
  147. const char* name_;
  148. const char* filename_;
  149. const flags_internal::HelpGenFunc help_gen_;
  150. const flags_internal::FlagDfltGenFunc default_value_gen_;
  151. mutable std::atomic<bool> inited_;
  152. mutable flags_internal::Flag<T>* impl_;
  153. };
  154. #endif
  155. // GetFlag()
  156. //
  157. // Returns the value (of type `T`) of an `absl::Flag<T>` instance, by value. Do
  158. // not construct an `absl::Flag<T>` directly and call `absl::GetFlag()`;
  159. // instead, refer to flag's constructed variable name (e.g. `FLAGS_name`).
  160. // Because this function returns by value and not by reference, it is
  161. // thread-safe, but note that the operation may be expensive; as a result, avoid
  162. // `absl::GetFlag()` within any tight loops.
  163. //
  164. // Example:
  165. //
  166. // // FLAGS_count is a Flag of type `int`
  167. // int my_count = absl::GetFlag(FLAGS_count);
  168. //
  169. // // FLAGS_firstname is a Flag of type `std::string`
  170. // std::string first_name = absl::GetFlag(FLAGS_firstname);
  171. template <typename T>
  172. ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
  173. return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
  174. }
  175. // SetFlag()
  176. //
  177. // Sets the value of an `absl::Flag` to the value `v`. Do not construct an
  178. // `absl::Flag<T>` directly and call `absl::SetFlag()`; instead, use the
  179. // flag's variable name (e.g. `FLAGS_name`). This function is
  180. // thread-safe, but is potentially expensive. Avoid setting flags in general,
  181. // but especially within performance-critical code.
  182. template <typename T>
  183. void SetFlag(absl::Flag<T>* flag, const T& v) {
  184. flags_internal::FlagImplPeer::InvokeSet(*flag, v);
  185. }
  186. // Overload of `SetFlag()` to allow callers to pass in a value that is
  187. // convertible to `T`. E.g., use this overload to pass a "const char*" when `T`
  188. // is `std::string`.
  189. template <typename T, typename V>
  190. void SetFlag(absl::Flag<T>* flag, const V& v) {
  191. T value(v);
  192. flags_internal::FlagImplPeer::InvokeSet(*flag, value);
  193. }
  194. // GetFlagReflectionHandle()
  195. //
  196. // Returns the reflection handle corresponding to specified Abseil Flag
  197. // instance. Use this handle to access flag's reflection information, like name,
  198. // location, default value etc.
  199. //
  200. // Example:
  201. //
  202. // std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();
  203. template <typename T>
  204. const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
  205. return flags_internal::FlagImplPeer::InvokeReflect(f);
  206. }
  207. ABSL_NAMESPACE_END
  208. } // namespace absl
  209. // ABSL_FLAG()
  210. //
  211. // This macro defines an `absl::Flag<T>` instance of a specified type `T`:
  212. //
  213. // ABSL_FLAG(T, name, default_value, help);
  214. //
  215. // where:
  216. //
  217. // * `T` is a supported flag type (see the list of types in `marshalling.h`),
  218. // * `name` designates the name of the flag (as a global variable
  219. // `FLAGS_name`),
  220. // * `default_value` is an expression holding the default value for this flag
  221. // (which must be implicitly convertible to `T`),
  222. // * `help` is the help text, which can also be an expression.
  223. //
  224. // This macro expands to a flag named 'FLAGS_name' of type 'T':
  225. //
  226. // absl::Flag<T> FLAGS_name = ...;
  227. //
  228. // Note that all such instances are created as global variables.
  229. //
  230. // For `ABSL_FLAG()` values that you wish to expose to other translation units,
  231. // it is recommended to define those flags within the `.cc` file associated with
  232. // the header where the flag is declared.
  233. //
  234. // Note: do not construct objects of type `absl::Flag<T>` directly. Only use the
  235. // `ABSL_FLAG()` macro for such construction.
  236. #define ABSL_FLAG(Type, name, default_value, help) \
  237. ABSL_FLAG_IMPL(Type, name, default_value, help)
  238. // ABSL_FLAG().OnUpdate()
  239. //
  240. // Defines a flag of type `T` with a callback attached:
  241. //
  242. // ABSL_FLAG(T, name, default_value, help).OnUpdate(callback);
  243. //
  244. // After any setting of the flag value, the callback will be called at least
  245. // once. A rapid sequence of changes may be merged together into the same
  246. // callback. No concurrent calls to the callback will be made for the same
  247. // flag. Callbacks are allowed to read the current value of the flag but must
  248. // not mutate that flag.
  249. //
  250. // The update mechanism guarantees "eventual consistency"; if the callback
  251. // derives an auxiliary data structure from the flag value, it is guaranteed
  252. // that eventually the flag value and the derived data structure will be
  253. // consistent.
  254. //
  255. // Note: ABSL_FLAG.OnUpdate() does not have a public definition. Hence, this
  256. // comment serves as its API documentation.
  257. // -----------------------------------------------------------------------------
  258. // Implementation details below this section
  259. // -----------------------------------------------------------------------------
  260. // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
  261. #if !defined(_MSC_VER) || defined(__clang__)
  262. #define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag
  263. #define ABSL_FLAG_IMPL_HELP_ARG(name) \
  264. absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \
  265. FLAGS_help_storage_##name)
  266. #define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \
  267. absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)
  268. #else
  269. #define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag.GetImpl()
  270. #define ABSL_FLAG_IMPL_HELP_ARG(name) &AbslFlagHelpGenFor##name::NonConst
  271. #define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) &AbslFlagDefaultGenFor##name::Gen
  272. #endif
  273. #if ABSL_FLAGS_STRIP_NAMES
  274. #define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
  275. #define ABSL_FLAG_IMPL_FILENAME() ""
  276. #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
  277. absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
  278. #else
  279. #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
  280. #define ABSL_FLAG_IMPL_FILENAME() __FILE__
  281. #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
  282. absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
  283. #endif
  284. // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
  285. #if ABSL_FLAGS_STRIP_HELP
  286. #define ABSL_FLAG_IMPL_FLAGHELP(txt) absl::flags_internal::kStrippedFlagHelp
  287. #else
  288. #define ABSL_FLAG_IMPL_FLAGHELP(txt) txt
  289. #endif
  290. // AbslFlagHelpGenFor##name is used to encapsulate both immediate (method Const)
  291. // and lazy (method NonConst) evaluation of help message expression. We choose
  292. // between the two via the call to HelpArg in absl::Flag instantiation below.
  293. // If help message expression is constexpr evaluable compiler will optimize
  294. // away this whole struct.
  295. // TODO(rogeeff): place these generated structs into local namespace and apply
  296. // ABSL_INTERNAL_UNIQUE_SHORT_NAME.
  297. // TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name
  298. #define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \
  299. struct AbslFlagHelpGenFor##name { \
  300. /* The expression is run in the caller as part of the */ \
  301. /* default value argument. That keeps temporaries alive */ \
  302. /* long enough for NonConst to work correctly. */ \
  303. static constexpr absl::string_view Value( \
  304. absl::string_view v = ABSL_FLAG_IMPL_FLAGHELP(txt)) { \
  305. return v; \
  306. } \
  307. static std::string NonConst() { return std::string(Value()); } \
  308. }; \
  309. constexpr auto FLAGS_help_storage_##name ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
  310. ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) = \
  311. absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \
  312. 0);
  313. #define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
  314. struct AbslFlagDefaultGenFor##name { \
  315. Type value = absl::flags_internal::InitDefaultValue<Type>(default_value); \
  316. static void Gen(void* p) { \
  317. new (p) Type(AbslFlagDefaultGenFor##name{}.value); \
  318. } \
  319. };
  320. // ABSL_FLAG_IMPL
  321. //
  322. // Note: Name of registrar object is not arbitrary. It is used to "grab"
  323. // global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
  324. // of defining two flags with names foo and nofoo.
  325. #define ABSL_FLAG_IMPL(Type, name, default_value, help) \
  326. namespace absl /* block flags in namespaces */ {} \
  327. ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
  328. ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help) \
  329. ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{ \
  330. ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(), \
  331. ABSL_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \
  332. extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name; \
  333. absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name = \
  334. ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
  335. // ABSL_RETIRED_FLAG
  336. //
  337. // Designates the flag (which is usually pre-existing) as "retired." A retired
  338. // flag is a flag that is now unused by the program, but may still be passed on
  339. // the command line, usually by production scripts. A retired flag is ignored
  340. // and code can't access it at runtime.
  341. //
  342. // This macro registers a retired flag with given name and type, with a name
  343. // identical to the name of the original flag you are retiring. The retired
  344. // flag's type can change over time, so that you can retire code to support a
  345. // custom flag type.
  346. //
  347. // This macro has the same signature as `ABSL_FLAG`. To retire a flag, simply
  348. // replace an `ABSL_FLAG` definition with `ABSL_RETIRED_FLAG`, leaving the
  349. // arguments unchanged (unless of course you actually want to retire the flag
  350. // type at this time as well).
  351. //
  352. // `default_value` is only used as a double check on the type. `explanation` is
  353. // unused.
  354. // TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of
  355. // retired flags are cleaned up.
  356. #define ABSL_RETIRED_FLAG(type, name, default_value, explanation) \
  357. static absl::flags_internal::RetiredFlag<type> RETIRED_FLAGS_##name; \
  358. ABSL_ATTRIBUTE_UNUSED static const auto RETIRED_FLAGS_REG_##name = \
  359. (RETIRED_FLAGS_##name.Retire(#name), \
  360. ::absl::flags_internal::FlagRegistrarEmpty{})
  361. #endif // ABSL_FLAGS_FLAG_H_