00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
00017 #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
00018
00019 #include <atomic>
00020
00021 #include "absl/base/macros.h"
00022 #include "absl/flags/marshalling.h"
00023 #include "absl/synchronization/mutex.h"
00024 #include "absl/types/optional.h"
00025
00026 namespace absl {
00027 namespace flags_internal {
00028
00029
00030
00031 enum FlagOp {
00032 kDelete,
00033 kClone,
00034 kCopy,
00035 kCopyConstruct,
00036 kSizeof,
00037 kParse,
00038 kUnparse
00039 };
00040 using FlagOpFn = void* (*)(FlagOp, const void*, void*);
00041 using FlagMarshallingOpFn = void* (*)(FlagOp, const void*, void*, void*);
00042
00043
00044 enum FlagSettingMode {
00045
00046 SET_FLAGS_VALUE,
00047
00048
00049 SET_FLAG_IF_DEFAULT,
00050
00051
00052
00053 SET_FLAGS_DEFAULT
00054 };
00055
00056
00057 enum ValueSource {
00058
00059 kCommandLine,
00060
00061 kProgrammaticChange,
00062 };
00063
00064
00065
00066 using HelpGenFunc = std::string (*)();
00067
00068
00069
00070 using InitialValGenFunc = void* (*)();
00071
00072
00073
00074
00075 using FlagCallback = void (*)();
00076
00077 extern const char kStrippedFlagHelp[];
00078
00079
00080 template <typename T>
00081 void* FlagOps(FlagOp op, const void* v1, void* v2) {
00082 switch (op) {
00083 case kDelete:
00084 delete static_cast<const T*>(v1);
00085 return nullptr;
00086 case kClone:
00087 return new T(*static_cast<const T*>(v1));
00088 case kCopy:
00089 *static_cast<T*>(v2) = *static_cast<const T*>(v1);
00090 return nullptr;
00091 case kCopyConstruct:
00092 new (v2) T(*static_cast<const T*>(v1));
00093 return nullptr;
00094 case kSizeof:
00095 return reinterpret_cast<void*>(sizeof(T));
00096 default:
00097 return nullptr;
00098 }
00099 }
00100
00101 template <typename T>
00102 void* FlagMarshallingOps(FlagOp op, const void* v1, void* v2, void* v3) {
00103 switch (op) {
00104 case kParse: {
00105
00106
00107 T temp(*static_cast<T*>(v2));
00108 if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,
00109 static_cast<std::string*>(v3))) {
00110 return nullptr;
00111 }
00112 *static_cast<T*>(v2) = std::move(temp);
00113 return v2;
00114 }
00115 case kUnparse:
00116 *static_cast<std::string*>(v2) =
00117 absl::UnparseFlag<T>(*static_cast<const T*>(v1));
00118 return nullptr;
00119 default:
00120 return nullptr;
00121 }
00122 }
00123
00124
00125 inline void Delete(FlagOpFn op, const void* obj) {
00126 op(flags_internal::kDelete, obj, nullptr);
00127 }
00128
00129 inline void* Clone(FlagOpFn op, const void* obj) {
00130 return op(flags_internal::kClone, obj, nullptr);
00131 }
00132
00133 inline void Copy(FlagOpFn op, const void* src, void* dst) {
00134 op(flags_internal::kCopy, src, dst);
00135 }
00136
00137 inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
00138 op(flags_internal::kCopyConstruct, src, dst);
00139 }
00140
00141 inline bool Parse(FlagMarshallingOpFn op, absl::string_view text, void* dst,
00142 std::string* error) {
00143 return op(flags_internal::kParse, &text, dst, error) != nullptr;
00144 }
00145
00146 inline std::string Unparse(FlagMarshallingOpFn op, const void* val) {
00147 std::string result;
00148 op(flags_internal::kUnparse, val, &result, nullptr);
00149 return result;
00150 }
00151
00152 inline size_t Sizeof(FlagOpFn op) {
00153
00154 return static_cast<size_t>(reinterpret_cast<intptr_t>(
00155 op(flags_internal::kSizeof, nullptr, nullptr)));
00156 }
00157
00158
00159
00160
00161 struct CommandLineFlagLocks {
00162 absl::Mutex primary_mu;
00163 absl::Mutex callback_mu;
00164 };
00165
00166
00167
00168
00169
00170
00171 class HelpText {
00172 public:
00173 static constexpr HelpText FromFunctionPointer(const HelpGenFunc fn) {
00174 return HelpText(fn, nullptr);
00175 }
00176 static constexpr HelpText FromStaticCString(const char* msg) {
00177 return HelpText(nullptr, msg);
00178 }
00179
00180 std::string GetHelpText() const;
00181
00182 HelpText() = delete;
00183 HelpText(const HelpText&) = default;
00184 HelpText(HelpText&&) = default;
00185
00186 private:
00187 explicit constexpr HelpText(const HelpGenFunc fn, const char* msg)
00188 : help_function_(fn), help_message_(msg) {}
00189
00190 HelpGenFunc help_function_;
00191 const char* help_message_;
00192 };
00193
00194
00195 struct CommandLineFlag {
00196 constexpr CommandLineFlag(
00197 const char* name_arg, HelpText help_text, const char* filename_arg,
00198 const flags_internal::FlagOpFn op_arg,
00199 const flags_internal::FlagMarshallingOpFn marshalling_op_arg,
00200 const flags_internal::InitialValGenFunc initial_value_gen,
00201 const bool retired_arg, void* def_arg, void* cur_arg)
00202 : name(name_arg),
00203 help(help_text),
00204 filename(filename_arg),
00205 op(op_arg),
00206 marshalling_op(marshalling_op_arg),
00207 make_init_value(initial_value_gen),
00208 retired(retired_arg),
00209 inited(false),
00210 modified(false),
00211 on_command_line(false),
00212 validator(nullptr),
00213 callback(nullptr),
00214 def(def_arg),
00215 cur(cur_arg),
00216 counter(0),
00217 atomic(kAtomicInit),
00218 locks(nullptr) {}
00219
00220
00221 CommandLineFlag(const CommandLineFlag&) = delete;
00222 CommandLineFlag& operator=(const CommandLineFlag&) = delete;
00223
00224 absl::string_view Name() const { return name; }
00225 std::string Help() const { return help.GetHelpText(); }
00226 bool IsRetired() const { return this->retired; }
00227 bool IsSpecifiedOnCommandLine() const { return on_command_line; }
00228
00229 bool IsAbseilFlag() const {
00230
00231 return this->make_init_value != nullptr;
00232 }
00233
00234 absl::string_view Typename() const;
00235 std::string Filename() const;
00236 std::string DefaultValue() const;
00237 std::string CurrentValue() const;
00238
00239
00240 template <typename T>
00241 inline bool IsOfType() const {
00242 return this->op == &flags_internal::FlagOps<T>;
00243 }
00244
00245
00246
00247 template <typename T>
00248 absl::optional<T> Get() {
00249 if (IsRetired() || flags_internal::FlagOps<T> != this->op)
00250 return absl::nullopt;
00251
00252 T res;
00253 Read(&res, flags_internal::FlagOps<T>);
00254
00255 return res;
00256 }
00257
00258 void SetCallback(const flags_internal::FlagCallback mutation_callback);
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 bool SetFromString(absl::string_view value,
00269 flags_internal::FlagSettingMode set_mode,
00270 flags_internal::ValueSource source, std::string* error);
00271
00272
00273 private:
00274 const char* const name;
00275 const HelpText help;
00276 const char* const filename;
00277
00278 public:
00279 const FlagOpFn op;
00280 const FlagMarshallingOpFn marshalling_op;
00281 const InitialValGenFunc make_init_value;
00282 const bool retired;
00283 std::atomic<bool> inited;
00284
00285
00286 bool modified;
00287 bool on_command_line;
00288 bool (*validator)();
00289 FlagCallback callback;
00290 void* def;
00291 void* cur;
00292 int64_t counter;
00293
00294
00295
00296 static const int64_t kAtomicInit = 0xababababababababll;
00297 std::atomic<int64_t> atomic;
00298
00299
00300
00301
00302
00303 struct CommandLineFlagLocks* locks;
00304
00305
00306
00307 void Read(void* dst, const flags_internal::FlagOpFn dst_op) const;
00308
00309 void Write(const void* src, const flags_internal::FlagOpFn src_op);
00310
00311 ABSL_DEPRECATED(
00312 "temporary until FlagName call sites are migrated and validator API is "
00313 "changed")
00314 const char* NameAsCString() const { return name; }
00315
00316 private:
00317 friend class FlagRegistry;
00318 };
00319
00320
00321
00322 absl::Mutex* InitFlagIfNecessary(CommandLineFlag* flag);
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 void UpdateCopy(CommandLineFlag* flag, absl::Mutex* primary_lock);
00336
00337 bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b);
00338
00339
00340 void UpdateModifiedBit(CommandLineFlag* flag);
00341
00342
00343 bool Validate(CommandLineFlag* flag, const void* value);
00344
00345
00346
00347
00348
00349 #define ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(A) \
00350 A(bool) \
00351 A(short) \
00352 A(unsigned short) \
00353 A(int) \
00354 A(unsigned int) \
00355 A(long) \
00356 A(unsigned long) \
00357 A(long long) \
00358 A(unsigned long long) \
00359 A(double) \
00360 A(float)
00361
00362 }
00363 }
00364
00365 #endif // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_