Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:31:43

0001 //
0002 // Copyright 2019 The Abseil Authors.
0003 //
0004 // Licensed under the Apache License, Version 2.0 (the "License");
0005 // you may not use this file except in compliance with the License.
0006 // You may obtain a copy of the License at
0007 //
0008 //      https://www.apache.org/licenses/LICENSE-2.0
0009 //
0010 // Unless required by applicable law or agreed to in writing, software
0011 // distributed under the License is distributed on an "AS IS" BASIS,
0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013 // See the License for the specific language governing permissions and
0014 // limitations under the License.
0015 
0016 #ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
0017 #define ABSL_FLAGS_INTERNAL_FLAG_H_
0018 
0019 #include <stddef.h>
0020 #include <stdint.h>
0021 
0022 #include <atomic>
0023 #include <cstring>
0024 #include <memory>
0025 #include <string>
0026 #include <type_traits>
0027 #include <typeinfo>
0028 
0029 #include "absl/base/attributes.h"
0030 #include "absl/base/call_once.h"
0031 #include "absl/base/casts.h"
0032 #include "absl/base/config.h"
0033 #include "absl/base/optimization.h"
0034 #include "absl/base/thread_annotations.h"
0035 #include "absl/flags/commandlineflag.h"
0036 #include "absl/flags/config.h"
0037 #include "absl/flags/internal/commandlineflag.h"
0038 #include "absl/flags/internal/registry.h"
0039 #include "absl/flags/internal/sequence_lock.h"
0040 #include "absl/flags/marshalling.h"
0041 #include "absl/meta/type_traits.h"
0042 #include "absl/strings/string_view.h"
0043 #include "absl/synchronization/mutex.h"
0044 #include "absl/utility/utility.h"
0045 
0046 namespace absl {
0047 ABSL_NAMESPACE_BEGIN
0048 
0049 ///////////////////////////////////////////////////////////////////////////////
0050 // Forward declaration of absl::Flag<T> public API.
0051 namespace flags_internal {
0052 template <typename T>
0053 class Flag;
0054 }  // namespace flags_internal
0055 
0056 template <typename T>
0057 using Flag = flags_internal::Flag<T>;
0058 
0059 template <typename T>
0060 ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
0061 
0062 template <typename T>
0063 void SetFlag(absl::Flag<T>* flag, const T& v);
0064 
0065 template <typename T, typename V>
0066 void SetFlag(absl::Flag<T>* flag, const V& v);
0067 
0068 template <typename U>
0069 const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f);
0070 
0071 ///////////////////////////////////////////////////////////////////////////////
0072 // Flag value type operations, eg., parsing, copying, etc. are provided
0073 // by function specific to that type with a signature matching FlagOpFn.
0074 
0075 namespace flags_internal {
0076 
0077 enum class FlagOp {
0078   kAlloc,
0079   kDelete,
0080   kCopy,
0081   kCopyConstruct,
0082   kSizeof,
0083   kFastTypeId,
0084   kRuntimeTypeId,
0085   kParse,
0086   kUnparse,
0087   kValueOffset,
0088 };
0089 using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
0090 
0091 // Forward declaration for Flag value specific operations.
0092 template <typename T>
0093 void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3);
0094 
0095 // Allocate aligned memory for a flag value.
0096 inline void* Alloc(FlagOpFn op) {
0097   return op(FlagOp::kAlloc, nullptr, nullptr, nullptr);
0098 }
0099 // Deletes memory interpreting obj as flag value type pointer.
0100 inline void Delete(FlagOpFn op, void* obj) {
0101   op(FlagOp::kDelete, nullptr, obj, nullptr);
0102 }
0103 // Copies src to dst interpreting as flag value type pointers.
0104 inline void Copy(FlagOpFn op, const void* src, void* dst) {
0105   op(FlagOp::kCopy, src, dst, nullptr);
0106 }
0107 // Construct a copy of flag value in a location pointed by dst
0108 // based on src - pointer to the flag's value.
0109 inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
0110   op(FlagOp::kCopyConstruct, src, dst, nullptr);
0111 }
0112 // Makes a copy of flag value pointed by obj.
0113 inline void* Clone(FlagOpFn op, const void* obj) {
0114   void* res = flags_internal::Alloc(op);
0115   flags_internal::CopyConstruct(op, obj, res);
0116   return res;
0117 }
0118 // Returns true if parsing of input text is successful.
0119 inline bool Parse(FlagOpFn op, absl::string_view text, void* dst,
0120                   std::string* error) {
0121   return op(FlagOp::kParse, &text, dst, error) != nullptr;
0122 }
0123 // Returns string representing supplied value.
0124 inline std::string Unparse(FlagOpFn op, const void* val) {
0125   std::string result;
0126   op(FlagOp::kUnparse, val, &result, nullptr);
0127   return result;
0128 }
0129 // Returns size of flag value type.
0130 inline size_t Sizeof(FlagOpFn op) {
0131   // This sequence of casts reverses the sequence from
0132   // `flags_internal::FlagOps()`
0133   return static_cast<size_t>(reinterpret_cast<intptr_t>(
0134       op(FlagOp::kSizeof, nullptr, nullptr, nullptr)));
0135 }
0136 // Returns fast type id corresponding to the value type.
0137 inline FlagFastTypeId FastTypeId(FlagOpFn op) {
0138   return reinterpret_cast<FlagFastTypeId>(
0139       op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr));
0140 }
0141 // Returns fast type id corresponding to the value type.
0142 inline const std::type_info* RuntimeTypeId(FlagOpFn op) {
0143   return reinterpret_cast<const std::type_info*>(
0144       op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr));
0145 }
0146 // Returns offset of the field value_ from the field impl_ inside of
0147 // absl::Flag<T> data. Given FlagImpl pointer p you can get the
0148 // location of the corresponding value as:
0149 //      reinterpret_cast<char*>(p) + ValueOffset().
0150 inline ptrdiff_t ValueOffset(FlagOpFn op) {
0151   // This sequence of casts reverses the sequence from
0152   // `flags_internal::FlagOps()`
0153   return static_cast<ptrdiff_t>(reinterpret_cast<intptr_t>(
0154       op(FlagOp::kValueOffset, nullptr, nullptr, nullptr)));
0155 }
0156 
0157 // Returns an address of RTTI's typeid(T).
0158 template <typename T>
0159 inline const std::type_info* GenRuntimeTypeId() {
0160 #ifdef ABSL_INTERNAL_HAS_RTTI
0161   return &typeid(T);
0162 #else
0163   return nullptr;
0164 #endif
0165 }
0166 
0167 ///////////////////////////////////////////////////////////////////////////////
0168 // Flag help auxiliary structs.
0169 
0170 // This is help argument for absl::Flag encapsulating the string literal pointer
0171 // or pointer to function generating it as well as enum descriminating two
0172 // cases.
0173 using HelpGenFunc = std::string (*)();
0174 
0175 template <size_t N>
0176 struct FixedCharArray {
0177   char value[N];
0178 
0179   template <size_t... I>
0180   static constexpr FixedCharArray<N> FromLiteralString(
0181       absl::string_view str, absl::index_sequence<I...>) {
0182     return (void)str, FixedCharArray<N>({{str[I]..., '\0'}});
0183   }
0184 };
0185 
0186 template <typename Gen, size_t N = Gen::Value().size()>
0187 constexpr FixedCharArray<N + 1> HelpStringAsArray(int) {
0188   return FixedCharArray<N + 1>::FromLiteralString(
0189       Gen::Value(), absl::make_index_sequence<N>{});
0190 }
0191 
0192 template <typename Gen>
0193 constexpr std::false_type HelpStringAsArray(char) {
0194   return std::false_type{};
0195 }
0196 
0197 union FlagHelpMsg {
0198   constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {}
0199   constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {}
0200 
0201   const char* literal;
0202   HelpGenFunc gen_func;
0203 };
0204 
0205 enum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 };
0206 
0207 struct FlagHelpArg {
0208   FlagHelpMsg source;
0209   FlagHelpKind kind;
0210 };
0211 
0212 extern const char kStrippedFlagHelp[];
0213 
0214 // These two HelpArg overloads allows us to select at compile time one of two
0215 // way to pass Help argument to absl::Flag. We'll be passing
0216 // AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer
0217 // first overload if possible. If help message is evaluatable on constexpr
0218 // context We'll be able to make FixedCharArray out of it and we'll choose first
0219 // overload. In this case the help message expression is immediately evaluated
0220 // and is used to construct the absl::Flag. No additional code is generated by
0221 // ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the
0222 // consideration, in which case the second overload will be used. The second
0223 // overload does not attempt to evaluate the help message expression
0224 // immediately and instead delays the evaluation by returning the function
0225 // pointer (&T::NonConst) generating the help message when necessary. This is
0226 // evaluatable in constexpr context, but the cost is an extra function being
0227 // generated in the ABSL_FLAG code.
0228 template <typename Gen, size_t N>
0229 constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {
0230   return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};
0231 }
0232 
0233 template <typename Gen>
0234 constexpr FlagHelpArg HelpArg(std::false_type) {
0235   return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
0236 }
0237 
0238 ///////////////////////////////////////////////////////////////////////////////
0239 // Flag default value auxiliary structs.
0240 
0241 // Signature for the function generating the initial flag value (usually
0242 // based on default value supplied in flag's definition)
0243 using FlagDfltGenFunc = void (*)(void*);
0244 
0245 union FlagDefaultSrc {
0246   constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg)
0247       : gen_func(gen_func_arg) {}
0248 
0249 #define ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE(T, name) \
0250   T name##_value;                                  \
0251   constexpr explicit FlagDefaultSrc(T value) : name##_value(value) {}  // NOLINT
0252   ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE)
0253 #undef ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE
0254 
0255   void* dynamic_value;
0256   FlagDfltGenFunc gen_func;
0257 };
0258 
0259 enum class FlagDefaultKind : uint8_t {
0260   kDynamicValue = 0,
0261   kGenFunc = 1,
0262   kOneWord = 2  // for default values UP to one word in size
0263 };
0264 
0265 struct FlagDefaultArg {
0266   FlagDefaultSrc source;
0267   FlagDefaultKind kind;
0268 };
0269 
0270 // This struct and corresponding overload to InitDefaultValue are used to
0271 // facilitate usage of {} as default value in ABSL_FLAG macro.
0272 // TODO(rogeeff): Fix handling types with explicit constructors.
0273 struct EmptyBraces {};
0274 
0275 template <typename T>
0276 constexpr T InitDefaultValue(T t) {
0277   return t;
0278 }
0279 
0280 template <typename T>
0281 constexpr T InitDefaultValue(EmptyBraces) {
0282   return T{};
0283 }
0284 
0285 template <typename ValueT, typename GenT,
0286           typename std::enable_if<std::is_integral<ValueT>::value, int>::type =
0287               ((void)GenT{}, 0)>
0288 constexpr FlagDefaultArg DefaultArg(int) {
0289   return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord};
0290 }
0291 
0292 template <typename ValueT, typename GenT>
0293 constexpr FlagDefaultArg DefaultArg(char) {
0294   return {FlagDefaultSrc(&GenT::Gen), FlagDefaultKind::kGenFunc};
0295 }
0296 
0297 ///////////////////////////////////////////////////////////////////////////////
0298 // Flag storage selector traits. Each trait indicates what kind of storage kind
0299 // to use for the flag value.
0300 
0301 template <typename T>
0302 using FlagUseValueAndInitBitStorage =
0303     std::integral_constant<bool, std::is_trivially_copyable<T>::value &&
0304                                      std::is_default_constructible<T>::value &&
0305                                      (sizeof(T) < 8)>;
0306 
0307 template <typename T>
0308 using FlagUseOneWordStorage =
0309     std::integral_constant<bool, std::is_trivially_copyable<T>::value &&
0310                                      (sizeof(T) <= 8)>;
0311 
0312 template <class T>
0313 using FlagUseSequenceLockStorage =
0314     std::integral_constant<bool, std::is_trivially_copyable<T>::value &&
0315                                      (sizeof(T) > 8)>;
0316 
0317 enum class FlagValueStorageKind : uint8_t {
0318   kValueAndInitBit = 0,
0319   kOneWordAtomic = 1,
0320   kSequenceLocked = 2,
0321   kHeapAllocated = 3,
0322 };
0323 
0324 // This constexpr function returns the storage kind for the given flag value
0325 // type.
0326 template <typename T>
0327 static constexpr FlagValueStorageKind StorageKind() {
0328   return FlagUseValueAndInitBitStorage<T>::value
0329              ? FlagValueStorageKind::kValueAndInitBit
0330          : FlagUseOneWordStorage<T>::value
0331              ? FlagValueStorageKind::kOneWordAtomic
0332          : FlagUseSequenceLockStorage<T>::value
0333              ? FlagValueStorageKind::kSequenceLocked
0334              : FlagValueStorageKind::kHeapAllocated;
0335 }
0336 
0337 // This is a base class for the storage classes used by kOneWordAtomic and
0338 // kValueAndInitBit storage kinds. It literally just stores the one word value
0339 // as an atomic. By default, it is initialized to a magic value that is unlikely
0340 // a valid value for the flag value type.
0341 struct FlagOneWordValue {
0342   constexpr static int64_t Uninitialized() {
0343     return static_cast<int64_t>(0xababababababababll);
0344   }
0345 
0346   constexpr FlagOneWordValue() : value(Uninitialized()) {}
0347   constexpr explicit FlagOneWordValue(int64_t v) : value(v) {}
0348   std::atomic<int64_t> value;
0349 };
0350 
0351 // This class represents a memory layout used by kValueAndInitBit storage kind.
0352 template <typename T>
0353 struct alignas(8) FlagValueAndInitBit {
0354   T value;
0355   // Use an int instead of a bool to guarantee that a non-zero value has
0356   // a bit set.
0357   uint8_t init;
0358 };
0359 
0360 // This class implements an aligned pointer with two options stored via masks
0361 // in unused bits of the pointer value (due to alignment requirement).
0362 //  - IsUnprotectedReadCandidate - indicates that the value can be switched to
0363 //    unprotected read without a lock.
0364 //  - HasBeenRead - indicates that the value has been read at least once.
0365 //  - AllowsUnprotectedRead - combination of the two options above and indicates
0366 //    that the value can now be read without a lock.
0367 // Further details of these options and their use is covered in the description
0368 // of the FlagValue<T, FlagValueStorageKind::kHeapAllocated> specialization.
0369 class MaskedPointer {
0370  public:
0371   using mask_t = uintptr_t;
0372   using ptr_t = void*;
0373 
0374   static constexpr int RequiredAlignment() { return 4; }
0375 
0376   constexpr explicit MaskedPointer(ptr_t rhs) : ptr_(rhs) {}
0377   MaskedPointer(ptr_t rhs, bool is_candidate);
0378 
0379   void* Ptr() const {
0380     return reinterpret_cast<void*>(reinterpret_cast<mask_t>(ptr_) &
0381                                    kPtrValueMask);
0382   }
0383   bool AllowsUnprotectedRead() const {
0384     return (reinterpret_cast<mask_t>(ptr_) & kAllowsUnprotectedRead) ==
0385            kAllowsUnprotectedRead;
0386   }
0387   bool IsUnprotectedReadCandidate() const;
0388   bool HasBeenRead() const;
0389 
0390   void Set(FlagOpFn op, const void* src, bool is_candidate);
0391   void MarkAsRead();
0392 
0393  private:
0394   // Masks
0395   // Indicates that the flag value either default or originated from command
0396   // line.
0397   static constexpr mask_t kUnprotectedReadCandidate = 0x1u;
0398   // Indicates that flag has been read.
0399   static constexpr mask_t kHasBeenRead = 0x2u;
0400   static constexpr mask_t kAllowsUnprotectedRead =
0401       kUnprotectedReadCandidate | kHasBeenRead;
0402   static constexpr mask_t kPtrValueMask = ~kAllowsUnprotectedRead;
0403 
0404   void ApplyMask(mask_t mask);
0405   bool CheckMask(mask_t mask) const;
0406 
0407   ptr_t ptr_;
0408 };
0409 
0410 // This class implements a type erased storage of the heap allocated flag value.
0411 // It is used as a base class for the storage class for kHeapAllocated storage
0412 // kind. The initial_buffer is expected to have an alignment of at least
0413 // MaskedPointer::RequiredAlignment(), so that the bits used by the
0414 // MaskedPointer to store masks are set to 0. This guarantees that value starts
0415 // in an uninitialized state.
0416 struct FlagMaskedPointerValue {
0417   constexpr explicit FlagMaskedPointerValue(MaskedPointer::ptr_t initial_buffer)
0418       : value(MaskedPointer(initial_buffer)) {}
0419 
0420   std::atomic<MaskedPointer> value;
0421 };
0422 
0423 // This is the forward declaration for the template that represents a storage
0424 // for the flag values. This template is expected to be explicitly specialized
0425 // for each storage kind and it does not have a generic default
0426 // implementation.
0427 template <typename T,
0428           FlagValueStorageKind Kind = flags_internal::StorageKind<T>()>
0429 struct FlagValue;
0430 
0431 // This specialization represents the storage of flag values types with the
0432 // kValueAndInitBit storage kind. It is based on the FlagOneWordValue class
0433 // and relies on memory layout in FlagValueAndInitBit<T> to indicate that the
0434 // value has been initialized or not.
0435 template <typename T>
0436 struct FlagValue<T, FlagValueStorageKind::kValueAndInitBit> : FlagOneWordValue {
0437   constexpr FlagValue() : FlagOneWordValue(0) {}
0438   bool Get(const SequenceLock&, T& dst) const {
0439     int64_t storage = value.load(std::memory_order_acquire);
0440     if (ABSL_PREDICT_FALSE(storage == 0)) {
0441       // This assert is to ensure that the initialization inside FlagImpl::Init
0442       // is able to set init member correctly.
0443       static_assert(offsetof(FlagValueAndInitBit<T>, init) == sizeof(T),
0444                     "Unexpected memory layout of FlagValueAndInitBit");
0445       return false;
0446     }
0447     dst = absl::bit_cast<FlagValueAndInitBit<T>>(storage).value;
0448     return true;
0449   }
0450 };
0451 
0452 // This specialization represents the storage of flag values types with the
0453 // kOneWordAtomic storage kind. It is based on the FlagOneWordValue class
0454 // and relies on the magic uninitialized state of default constructed instead of
0455 // FlagOneWordValue to indicate that the value has been initialized or not.
0456 template <typename T>
0457 struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
0458   constexpr FlagValue() : FlagOneWordValue() {}
0459   bool Get(const SequenceLock&, T& dst) const {
0460     int64_t one_word_val = value.load(std::memory_order_acquire);
0461     if (ABSL_PREDICT_FALSE(one_word_val == FlagOneWordValue::Uninitialized())) {
0462       return false;
0463     }
0464     std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));
0465     return true;
0466   }
0467 };
0468 
0469 // This specialization represents the storage of flag values types with the
0470 // kSequenceLocked storage kind. This storage is used by trivially copyable
0471 // types with size greater than 8 bytes. This storage relies on uninitialized
0472 // state of the SequenceLock to indicate that the value has been initialized or
0473 // not. This storage also provides lock-free read access to the underlying
0474 // value once it is initialized.
0475 template <typename T>
0476 struct FlagValue<T, FlagValueStorageKind::kSequenceLocked> {
0477   bool Get(const SequenceLock& lock, T& dst) const {
0478     return lock.TryRead(&dst, value_words, sizeof(T));
0479   }
0480 
0481   static constexpr int kNumWords =
0482       flags_internal::AlignUp(sizeof(T), sizeof(uint64_t)) / sizeof(uint64_t);
0483 
0484   alignas(T) alignas(
0485       std::atomic<uint64_t>) std::atomic<uint64_t> value_words[kNumWords];
0486 };
0487 
0488 // This specialization represents the storage of flag values types with the
0489 // kHeapAllocated storage kind. This is a storage of last resort and is used
0490 // if none of other storage kinds are applicable.
0491 //
0492 // Generally speaking the values with this storage kind can't be accessed
0493 // atomically and thus can't be read without holding a lock. If we would ever
0494 // want to avoid the lock, we'd need to leak the old value every time new flag
0495 // value is being set (since we are in danger of having a race condition
0496 // otherwise).
0497 //
0498 // Instead of doing that, this implementation attempts to cater to some common
0499 // use cases by allowing at most 2 values to be leaked - default value and
0500 // value set from the command line.
0501 //
0502 // This specialization provides an initial buffer for the first flag value. This
0503 // is where the default value is going to be stored. We attempt to reuse this
0504 // buffer if possible, including storing the value set from the command line
0505 // there.
0506 //
0507 // As long as we only read this value, we can access it without a lock (in
0508 // practice we still use the lock for the very first read to be able set
0509 // "has been read" option on this flag).
0510 //
0511 // If flag is specified on the command line we store the parsed value either
0512 // in the internal buffer (if the default value never been read) or we leak the
0513 // default value and allocate the new storage for the parse value. This value is
0514 // also a candidate for an unprotected read. If flag is set programmatically
0515 // after the command line is parsed, the storage for this value is going to be
0516 // leaked. Note that in both scenarios we are not going to have a real leak.
0517 // Instead we'll store the leaked value pointers in the internal freelist to
0518 // avoid triggering the memory leak checker complains.
0519 //
0520 // If the flag is ever set programmatically, it stops being the candidate for an
0521 // unprotected read, and any follow up access to the flag value requires a lock.
0522 // Note that if the value if set programmatically before the command line is
0523 // parsed, we can switch back to enabling unprotected reads for that value.
0524 template <typename T>
0525 struct FlagValue<T, FlagValueStorageKind::kHeapAllocated>
0526     : FlagMaskedPointerValue {
0527   // We const initialize the value with unmasked pointer to the internal buffer,
0528   // making sure it is not a candidate for unprotected read. This way we can
0529   // ensure Init is done before any access to the flag value.
0530   constexpr FlagValue() : FlagMaskedPointerValue(&buffer[0]) {}
0531 
0532   bool Get(const SequenceLock&, T& dst) const {
0533     MaskedPointer ptr_value = value.load(std::memory_order_acquire);
0534 
0535     if (ABSL_PREDICT_TRUE(ptr_value.AllowsUnprotectedRead())) {
0536       ::new (static_cast<void*>(&dst)) T(*static_cast<T*>(ptr_value.Ptr()));
0537       return true;
0538     }
0539     return false;
0540   }
0541 
0542   alignas(MaskedPointer::RequiredAlignment()) alignas(
0543       T) char buffer[sizeof(T)]{};
0544 };
0545 
0546 ///////////////////////////////////////////////////////////////////////////////
0547 // Flag callback auxiliary structs.
0548 
0549 // Signature for the mutation callback used by watched Flags
0550 // The callback is noexcept.
0551 // TODO(rogeeff): add noexcept after C++17 support is added.
0552 using FlagCallbackFunc = void (*)();
0553 
0554 struct FlagCallback {
0555   FlagCallbackFunc func;
0556   absl::Mutex guard;  // Guard for concurrent callback invocations.
0557 };
0558 
0559 ///////////////////////////////////////////////////////////////////////////////
0560 // Flag implementation, which does not depend on flag value type.
0561 // The class encapsulates the Flag's data and access to it.
0562 
0563 struct DynValueDeleter {
0564   explicit DynValueDeleter(FlagOpFn op_arg = nullptr);
0565   void operator()(void* ptr) const;
0566 
0567   FlagOpFn op;
0568 };
0569 
0570 class FlagState;
0571 
0572 // These are only used as constexpr global objects.
0573 // They do not use a virtual destructor to simplify their implementation.
0574 // They are not destroyed except at program exit, so leaks do not matter.
0575 #if defined(__GNUC__) && !defined(__clang__)
0576 #pragma GCC diagnostic push
0577 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
0578 #endif
0579 class FlagImpl final : public CommandLineFlag {
0580  public:
0581   constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
0582                      FlagHelpArg help, FlagValueStorageKind value_kind,
0583                      FlagDefaultArg default_arg)
0584       : name_(name),
0585         filename_(filename),
0586         op_(op),
0587         help_(help.source),
0588         help_source_kind_(static_cast<uint8_t>(help.kind)),
0589         value_storage_kind_(static_cast<uint8_t>(value_kind)),
0590         def_kind_(static_cast<uint8_t>(default_arg.kind)),
0591         modified_(false),
0592         on_command_line_(false),
0593         callback_(nullptr),
0594         default_value_(default_arg.source),
0595         data_guard_{} {}
0596 
0597   // Constant access methods
0598   int64_t ReadOneWord() const ABSL_LOCKS_EXCLUDED(*DataGuard());
0599   bool ReadOneBool() const ABSL_LOCKS_EXCLUDED(*DataGuard());
0600   void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(*DataGuard());
0601   void Read(bool* value) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
0602     *value = ReadOneBool();
0603   }
0604   template <typename T,
0605             absl::enable_if_t<flags_internal::StorageKind<T>() ==
0606                                   FlagValueStorageKind::kOneWordAtomic,
0607                               int> = 0>
0608   void Read(T* value) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
0609     int64_t v = ReadOneWord();
0610     std::memcpy(value, static_cast<const void*>(&v), sizeof(T));
0611   }
0612   template <typename T,
0613             typename std::enable_if<flags_internal::StorageKind<T>() ==
0614                                         FlagValueStorageKind::kValueAndInitBit,
0615                                     int>::type = 0>
0616   void Read(T* value) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
0617     *value = absl::bit_cast<FlagValueAndInitBit<T>>(ReadOneWord()).value;
0618   }
0619 
0620   // Mutating access methods
0621   void Write(const void* src) ABSL_LOCKS_EXCLUDED(*DataGuard());
0622 
0623   // Interfaces to operate on callbacks.
0624   void SetCallback(const FlagCallbackFunc mutation_callback)
0625       ABSL_LOCKS_EXCLUDED(*DataGuard());
0626   void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
0627 
0628   // Used in read/write operations to validate source/target has correct type.
0629   // For example if flag is declared as absl::Flag<int> FLAGS_foo, a call to
0630   // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed
0631   // int. To do that we pass the assumed type id (which is deduced from type
0632   // int) as an argument `type_id`, which is in turn is validated against the
0633   // type id stored in flag object by flag definition statement.
0634   void AssertValidType(FlagFastTypeId type_id,
0635                        const std::type_info* (*gen_rtti)()) const;
0636 
0637  private:
0638   template <typename T>
0639   friend class Flag;
0640   friend class FlagState;
0641 
0642   // Ensures that `data_guard_` is initialized and returns it.
0643   absl::Mutex* DataGuard() const
0644       ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_));
0645   // Returns heap allocated value of type T initialized with default value.
0646   std::unique_ptr<void, DynValueDeleter> MakeInitValue() const
0647       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
0648   // Flag initialization called via absl::call_once.
0649   void Init();
0650 
0651   // Offset value access methods. One per storage kind. These methods to not
0652   // respect const correctness, so be very careful using them.
0653 
0654   // This is a shared helper routine which encapsulates most of the magic. Since
0655   // it is only used inside the three routines below, which are defined in
0656   // flag.cc, we can define it in that file as well.
0657   template <typename StorageT>
0658   StorageT* OffsetValue() const;
0659 
0660   // The same as above, but used for sequencelock-protected storage.
0661   std::atomic<uint64_t>* AtomicBufferValue() const;
0662 
0663   // This is an accessor for a value stored as one word atomic. Returns a
0664   // mutable reference to an atomic value.
0665   std::atomic<int64_t>& OneWordValue() const;
0666 
0667   std::atomic<MaskedPointer>& PtrStorage() const;
0668 
0669   // Attempts to parse supplied `value` string. If parsing is successful,
0670   // returns new value. Otherwise returns nullptr.
0671   std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,
0672                                                   std::string& err) const
0673       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
0674   // Stores the flag value based on the pointer to the source.
0675   void StoreValue(const void* src, ValueSource source)
0676       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
0677 
0678   // Copy the flag data, protected by `seq_lock_` into `dst`.
0679   //
0680   // REQUIRES: ValueStorageKind() == kSequenceLocked.
0681   void ReadSequenceLockedData(void* dst) const
0682       ABSL_LOCKS_EXCLUDED(*DataGuard());
0683 
0684   FlagHelpKind HelpSourceKind() const {
0685     return static_cast<FlagHelpKind>(help_source_kind_);
0686   }
0687   FlagValueStorageKind ValueStorageKind() const {
0688     return static_cast<FlagValueStorageKind>(value_storage_kind_);
0689   }
0690   FlagDefaultKind DefaultKind() const
0691       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()) {
0692     return static_cast<FlagDefaultKind>(def_kind_);
0693   }
0694 
0695   // CommandLineFlag interface implementation
0696   absl::string_view Name() const override;
0697   std::string Filename() const override;
0698   std::string Help() const override;
0699   FlagFastTypeId TypeId() const override;
0700   bool IsSpecifiedOnCommandLine() const override
0701       ABSL_LOCKS_EXCLUDED(*DataGuard());
0702   std::string DefaultValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
0703   std::string CurrentValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
0704   bool ValidateInputValue(absl::string_view value) const override
0705       ABSL_LOCKS_EXCLUDED(*DataGuard());
0706   void CheckDefaultValueParsingRoundtrip() const override
0707       ABSL_LOCKS_EXCLUDED(*DataGuard());
0708 
0709   int64_t ModificationCount() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
0710 
0711   // Interfaces to save and restore flags to/from persistent state.
0712   // Returns current flag state or nullptr if flag does not support
0713   // saving and restoring a state.
0714   std::unique_ptr<FlagStateInterface> SaveState() override
0715       ABSL_LOCKS_EXCLUDED(*DataGuard());
0716 
0717   // Restores the flag state to the supplied state object. If there is
0718   // nothing to restore returns false. Otherwise returns true.
0719   bool RestoreState(const FlagState& flag_state)
0720       ABSL_LOCKS_EXCLUDED(*DataGuard());
0721 
0722   bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,
0723                  ValueSource source, std::string& error) override
0724       ABSL_LOCKS_EXCLUDED(*DataGuard());
0725 
0726   // Immutable flag's state.
0727 
0728   // Flags name passed to ABSL_FLAG as second arg.
0729   const char* const name_;
0730   // The file name where ABSL_FLAG resides.
0731   const char* const filename_;
0732   // Type-specific operations vtable.
0733   const FlagOpFn op_;
0734   // Help message literal or function to generate it.
0735   const FlagHelpMsg help_;
0736   // Indicates if help message was supplied as literal or generator func.
0737   const uint8_t help_source_kind_ : 1;
0738   // Kind of storage this flag is using for the flag's value.
0739   const uint8_t value_storage_kind_ : 2;
0740 
0741   uint8_t : 0;  // The bytes containing the const bitfields must not be
0742                 // shared with bytes containing the mutable bitfields.
0743 
0744   // Mutable flag's state (guarded by `data_guard_`).
0745 
0746   // def_kind_ is not guard by DataGuard() since it is accessed in Init without
0747   // locks.
0748   uint8_t def_kind_ : 2;
0749   // Has this flag's value been modified?
0750   bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard());
0751   // Has this flag been specified on command line.
0752   bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard());
0753 
0754   // Unique tag for absl::call_once call to initialize this flag.
0755   absl::once_flag init_control_;
0756 
0757   // Sequence lock / mutation counter.
0758   flags_internal::SequenceLock seq_lock_;
0759 
0760   // Optional flag's callback and absl::Mutex to guard the invocations.
0761   FlagCallback* callback_ ABSL_GUARDED_BY(*DataGuard());
0762   // Either a pointer to the function generating the default value based on the
0763   // value specified in ABSL_FLAG or pointer to the dynamically set default
0764   // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
0765   // these two cases.
0766   FlagDefaultSrc default_value_;
0767 
0768   // This is reserved space for an absl::Mutex to guard flag data. It will be
0769   // initialized in FlagImpl::Init via placement new.
0770   // We can't use "absl::Mutex data_guard_", since this class is not literal.
0771   // We do not want to use "absl::Mutex* data_guard_", since this would require
0772   // heap allocation during initialization, which is both slows program startup
0773   // and can fail. Using reserved space + placement new allows us to avoid both
0774   // problems.
0775   alignas(absl::Mutex) mutable char data_guard_[sizeof(absl::Mutex)];
0776 };
0777 #if defined(__GNUC__) && !defined(__clang__)
0778 #pragma GCC diagnostic pop
0779 #endif
0780 
0781 ///////////////////////////////////////////////////////////////////////////////
0782 // The Flag object parameterized by the flag's value type. This class implements
0783 // flag reflection handle interface.
0784 
0785 template <typename T>
0786 class Flag {
0787  public:
0788   constexpr Flag(const char* name, const char* filename, FlagHelpArg help,
0789                  const FlagDefaultArg default_arg)
0790       : impl_(name, filename, &FlagOps<T>, help,
0791               flags_internal::StorageKind<T>(), default_arg),
0792         value_() {}
0793 
0794   // CommandLineFlag interface
0795   absl::string_view Name() const { return impl_.Name(); }
0796   std::string Filename() const { return impl_.Filename(); }
0797   std::string Help() const { return impl_.Help(); }
0798   // Do not use. To be removed.
0799   bool IsSpecifiedOnCommandLine() const {
0800     return impl_.IsSpecifiedOnCommandLine();
0801   }
0802   std::string DefaultValue() const { return impl_.DefaultValue(); }
0803   std::string CurrentValue() const { return impl_.CurrentValue(); }
0804 
0805  private:
0806   template <typename, bool>
0807   friend class FlagRegistrar;
0808   friend class FlagImplPeer;
0809 
0810   T Get() const {
0811     // See implementation notes in CommandLineFlag::Get().
0812     union U {
0813       T value;
0814       U() {}
0815       ~U() { value.~T(); }
0816     };
0817     U u;
0818 
0819 #if !defined(NDEBUG)
0820     impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
0821 #endif
0822 
0823     if (ABSL_PREDICT_FALSE(!value_.Get(impl_.seq_lock_, u.value))) {
0824       impl_.Read(&u.value);
0825     }
0826     return std::move(u.value);
0827   }
0828   void Set(const T& v) {
0829     impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
0830     impl_.Write(&v);
0831   }
0832 
0833   // Access to the reflection.
0834   const CommandLineFlag& Reflect() const { return impl_; }
0835 
0836   // Flag's data
0837   // The implementation depends on value_ field to be placed exactly after the
0838   // impl_ field, so that impl_ can figure out the offset to the value and
0839   // access it.
0840   FlagImpl impl_;
0841   FlagValue<T> value_;
0842 };
0843 
0844 ///////////////////////////////////////////////////////////////////////////////
0845 // Trampoline for friend access
0846 
0847 class FlagImplPeer {
0848  public:
0849   template <typename T, typename FlagType>
0850   static T InvokeGet(const FlagType& flag) {
0851     return flag.Get();
0852   }
0853   template <typename FlagType, typename T>
0854   static void InvokeSet(FlagType& flag, const T& v) {
0855     flag.Set(v);
0856   }
0857   template <typename FlagType>
0858   static const CommandLineFlag& InvokeReflect(const FlagType& f) {
0859     return f.Reflect();
0860   }
0861 };
0862 
0863 ///////////////////////////////////////////////////////////////////////////////
0864 // Implementation of Flag value specific operations routine.
0865 template <typename T>
0866 void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
0867   struct AlignedSpace {
0868     alignas(MaskedPointer::RequiredAlignment()) alignas(T) char buf[sizeof(T)];
0869   };
0870   using Allocator = std::allocator<AlignedSpace>;
0871   switch (op) {
0872     case FlagOp::kAlloc: {
0873       Allocator alloc;
0874       return std::allocator_traits<Allocator>::allocate(alloc, 1);
0875     }
0876     case FlagOp::kDelete: {
0877       T* p = static_cast<T*>(v2);
0878       p->~T();
0879       Allocator alloc;
0880       std::allocator_traits<Allocator>::deallocate(
0881           alloc, reinterpret_cast<AlignedSpace*>(p), 1);
0882       return nullptr;
0883     }
0884     case FlagOp::kCopy:
0885       *static_cast<T*>(v2) = *static_cast<const T*>(v1);
0886       return nullptr;
0887     case FlagOp::kCopyConstruct:
0888       new (v2) T(*static_cast<const T*>(v1));
0889       return nullptr;
0890     case FlagOp::kSizeof:
0891       return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T)));
0892     case FlagOp::kFastTypeId:
0893       return const_cast<void*>(base_internal::FastTypeId<T>());
0894     case FlagOp::kRuntimeTypeId:
0895       return const_cast<std::type_info*>(GenRuntimeTypeId<T>());
0896     case FlagOp::kParse: {
0897       // Initialize the temporary instance of type T based on current value in
0898       // destination (which is going to be flag's default value).
0899       T temp(*static_cast<T*>(v2));
0900       if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,
0901                               static_cast<std::string*>(v3))) {
0902         return nullptr;
0903       }
0904       *static_cast<T*>(v2) = std::move(temp);
0905       return v2;
0906     }
0907     case FlagOp::kUnparse:
0908       *static_cast<std::string*>(v2) =
0909           absl::UnparseFlag<T>(*static_cast<const T*>(v1));
0910       return nullptr;
0911     case FlagOp::kValueOffset: {
0912       // Round sizeof(FlagImp) to a multiple of alignof(FlagValue<T>) to get the
0913       // offset of the data.
0914       size_t round_to = alignof(FlagValue<T>);
0915       size_t offset = (sizeof(FlagImpl) + round_to - 1) / round_to * round_to;
0916       return reinterpret_cast<void*>(offset);
0917     }
0918   }
0919   return nullptr;
0920 }
0921 
0922 ///////////////////////////////////////////////////////////////////////////////
0923 // This class facilitates Flag object registration and tail expression-based
0924 // flag definition, for example:
0925 // ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
0926 struct FlagRegistrarEmpty {};
0927 template <typename T, bool do_register>
0928 class FlagRegistrar {
0929  public:
0930   constexpr explicit FlagRegistrar(Flag<T>& flag, const char* filename)
0931       : flag_(flag) {
0932     if (do_register)
0933       flags_internal::RegisterCommandLineFlag(flag_.impl_, filename);
0934   }
0935 
0936   FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
0937     flag_.impl_.SetCallback(cb);
0938     return *this;
0939   }
0940 
0941   // Makes the registrar die gracefully as an empty struct on a line where
0942   // registration happens. Registrar objects are intended to live only as
0943   // temporary.
0944   constexpr operator FlagRegistrarEmpty() const { return {}; }  // NOLINT
0945 
0946  private:
0947   Flag<T>& flag_;  // Flag being registered (not owned).
0948 };
0949 
0950 ///////////////////////////////////////////////////////////////////////////////
0951 // Test only API
0952 uint64_t NumLeakedFlagValues();
0953 
0954 }  // namespace flags_internal
0955 ABSL_NAMESPACE_END
0956 }  // namespace absl
0957 
0958 #endif  // ABSL_FLAGS_INTERNAL_FLAG_H_