00001 // 00002 // Copyright 2019 The Abseil Authors. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // https://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 00016 #ifndef ABSL_FLAGS_INTERNAL_REGISTRY_H_ 00017 #define ABSL_FLAGS_INTERNAL_REGISTRY_H_ 00018 00019 #include <functional> 00020 #include <map> 00021 #include <string> 00022 00023 #include "absl/base/macros.h" 00024 #include "absl/flags/internal/commandlineflag.h" 00025 00026 // -------------------------------------------------------------------- 00027 // Global flags registry API. 00028 00029 namespace absl { 00030 namespace flags_internal { 00031 00032 // CommandLineFlagInfo holds all information for a flag. 00033 struct CommandLineFlagInfo { 00034 std::string name; // the name of the flag 00035 std::string type; // DO NOT use. Use flag->IsOfType<T>() instead. 00036 std::string description; // the "help text" associated with the flag 00037 std::string current_value; // the current value, as a std::string 00038 std::string default_value; // the default value, as a std::string 00039 std::string filename; // 'cleaned' version of filename holding the flag 00040 bool has_validator_fn; // true if RegisterFlagValidator called on this flag 00041 00042 bool is_default; // true if the flag has the default value and 00043 // has not been set explicitly from the cmdline 00044 // or via SetCommandLineOption. 00045 00046 // nullptr for ABSL_FLAG. A pointer to the flag's current value 00047 // otherwise. E.g., for DEFINE_int32(foo, ...), flag_ptr will be 00048 // &FLAGS_foo. 00049 const void* flag_ptr; 00050 }; 00051 00052 //----------------------------------------------------------------------------- 00053 00054 void FillCommandLineFlagInfo(CommandLineFlag* flag, 00055 CommandLineFlagInfo* result); 00056 00057 //----------------------------------------------------------------------------- 00058 00059 CommandLineFlag* FindCommandLineFlag(absl::string_view name); 00060 CommandLineFlag* FindCommandLineV1Flag(const void* flag_ptr); 00061 CommandLineFlag* FindRetiredFlag(absl::string_view name); 00062 00063 // Executes specified visitor for each non-retired flag in the registry. 00064 // Requires the caller hold the registry lock. 00065 void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor); 00066 // Executes specified visitor for each non-retired flag in the registry. While 00067 // callback are executed, the registry is locked and can't be changed. 00068 void ForEachFlag(std::function<void(CommandLineFlag*)> visitor); 00069 00070 //----------------------------------------------------------------------------- 00071 00072 // Store the list of all flags in *OUTPUT, sorted by file. 00073 void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT); 00074 00075 //----------------------------------------------------------------------------- 00076 00077 bool RegisterCommandLineFlag(CommandLineFlag*, const void* ptr = nullptr); 00078 00079 //----------------------------------------------------------------------------- 00080 // Retired registrations: 00081 // 00082 // Retired flag registrations are treated specially. A 'retired' flag is 00083 // provided only for compatibility with automated invocations that still 00084 // name it. A 'retired' flag: 00085 // - is not bound to a C++ FLAGS_ reference. 00086 // - has a type and a value, but that value is intentionally inaccessible. 00087 // - does not appear in --help messages. 00088 // - is fully supported by _all_ flag parsing routines. 00089 // - consumes args normally, and complains about type mismatches in its 00090 // argument. 00091 // - emits a complaint but does not die (e.g. LOG(ERROR)) if it is 00092 // accessed by name through the flags API for parsing or otherwise. 00093 // 00094 // The registrations for a flag happen in an unspecified order as the 00095 // initializers for the namespace-scope objects of a program are run. 00096 // Any number of weak registrations for a flag can weakly define the flag. 00097 // One non-weak registration will upgrade the flag from weak to non-weak. 00098 // Further weak registrations of a non-weak flag are ignored. 00099 // 00100 // This mechanism is designed to support moving dead flags into a 00101 // 'graveyard' library. An example migration: 00102 // 00103 // 0: Remove references to this FLAGS_flagname in the C++ codebase. 00104 // 1: Register as 'retired' in old_lib. 00105 // 2: Make old_lib depend on graveyard. 00106 // 3: Add a redundant 'retired' registration to graveyard. 00107 // 4: Remove the old_lib 'retired' registration. 00108 // 5: Eventually delete the graveyard registration entirely. 00109 // 00110 // Returns bool to enable use in namespace-scope initializers. 00111 // For example: 00112 // 00113 // static const bool dummy = base::RetiredFlag<int32_t>("myflag"); 00114 // 00115 // Or to declare several at once: 00116 // 00117 // static bool dummies[] = { 00118 // base::RetiredFlag<std::string>("some_string_flag"), 00119 // base::RetiredFlag<double>("some_double_flag"), 00120 // base::RetiredFlag<int32_t>("some_int32_flag") 00121 // }; 00122 00123 // Retire flag with name "name" and type indicated by ops. 00124 bool Retire(FlagOpFn ops, FlagMarshallingOpFn marshalling_ops, 00125 const char* name); 00126 00127 // Registered a retired flag with name 'flag_name' and type 'T'. 00128 template <typename T> 00129 inline bool RetiredFlag(const char* flag_name) { 00130 return flags_internal::Retire(flags_internal::FlagOps<T>, 00131 flags_internal::FlagMarshallingOps<T>, 00132 flag_name); 00133 } 00134 00135 // If the flag is retired, returns true and indicates in |*type_is_bool| 00136 // whether the type of the retired flag is a bool. 00137 // Only to be called by code that needs to explicitly ignore retired flags. 00138 bool IsRetiredFlag(absl::string_view name, bool* type_is_bool); 00139 00140 //----------------------------------------------------------------------------- 00141 // Saves the states (value, default value, whether the user has set 00142 // the flag, registered validators, etc) of all flags, and restores 00143 // them when the FlagSaver is destroyed. 00144 // 00145 // This class is thread-safe. However, its destructor writes to 00146 // exactly the set of flags that have changed value during its 00147 // lifetime, so concurrent _direct_ access to those flags 00148 // (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe. 00149 00150 class FlagSaver { 00151 public: 00152 FlagSaver(); 00153 ~FlagSaver(); 00154 00155 FlagSaver(const FlagSaver&) = delete; 00156 void operator=(const FlagSaver&) = delete; 00157 00158 // Prevents saver from restoring the saved state of flags. 00159 void Ignore(); 00160 00161 private: 00162 class FlagSaverImpl* impl_; // we use pimpl here to keep API steady 00163 }; 00164 00165 } // namespace flags_internal 00166 } // namespace absl 00167 00168 #endif // ABSL_FLAGS_INTERNAL_REGISTRY_H_