@ -119,47 +119,61 @@ constexpr flags_internal::HelpInitArg HelpArg(char) {
flags_internal : : FlagHelpSrcKind : : kGenFunc } ;
flags_internal : : FlagHelpSrcKind : : kGenFunc } ;
}
}
// Signature for the function generating the initial flag value based (usually
// Signature for the function generating the initial flag value (usually
// based on default value supplied in flag's definition)
// based on default value supplied in flag's definition)
using InitialValGenFunc = void * ( * ) ( ) ;
using FlagDfltGenFunc = void * ( * ) ( ) ;
union FlagDefaultSrc {
constexpr explicit FlagDefaultSrc ( FlagDfltGenFunc gen_func_arg )
: gen_func ( gen_func_arg ) { }
void * dynamic_value ;
FlagDfltGenFunc gen_func ;
} ;
enum class FlagDefaultSrcKind : int8_t { kDynamicValue , kGenFunc } ;
// Signature for the mutation callback used by watched Flags
// Signature for the mutation callback used by watched Flags
// The callback is noexcept.
// The callback is noexcept.
// TODO(rogeeff): add noexcept after C++17 support is added.
// TODO(rogeeff): add noexcept after C++17 support is added.
using FlagCallback = void ( * ) ( ) ;
using FlagCallback = void ( * ) ( ) ;
void InvokeCallback ( absl : : Mutex * primary_mu , absl : : Mutex * callback_mu ,
struct DynValueDeleter {
FlagCallback cb ) ABSL_EXCLUSIVE_LOCKS_REQUIRED ( primary_mu ) ;
void operator ( ) ( void * ptr ) const { Delete ( op , ptr ) ; }
const FlagOpFn op ;
} ;
// The class encapsulates the Flag's data and safe access to it.
// The class encapsulates the Flag's data and safe access to it.
class FlagImpl {
class FlagImpl {
public :
public :
constexpr FlagImpl ( const flags_internal : : FlagOpFn op ,
constexpr FlagImpl ( const flags_internal : : FlagOpFn op ,
const flags_internal : : FlagMarshallingOpFn marshalling_op ,
const flags_internal : : FlagMarshallingOpFn marshalling_op ,
const flags_internal : : InitialValGenFunc initial _value_gen,
const flags_internal : : FlagDfltGenFunc default _value_gen,
const HelpInitArg help )
const HelpInitArg help )
: op_ ( op ) ,
: op_ ( op ) ,
marshalling_op_ ( marshalling_op ) ,
marshalling_op_ ( marshalling_op ) ,
initial_value_gen_ ( initial_value_gen ) ,
help_ ( help . source ) ,
help_ ( help . source ) ,
help_source_kind_ ( help . kind ) { }
help_source_kind_ ( help . kind ) ,
def_kind_ ( flags_internal : : FlagDefaultSrcKind : : kGenFunc ) ,
default_src_ ( default_value_gen ) { }
// Forces destruction of the Flag's data.
// Forces destruction of the Flag's data.
void Destroy ( ) const ;
void Destroy ( ) const ;
// Constant access methods
// Constant access methods
std : : string Help ( ) const ;
std : : string Help ( ) const ;
bool IsModified ( ) const ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
bool IsModified ( ) const ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
bool IsSpecifiedOnCommandLine ( ) const ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
bool IsSpecifiedOnCommandLine ( ) const ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
std : : string DefaultValue ( ) const ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
std : : string DefaultValue ( ) const ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
std : : string CurrentValue ( ) const ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
std : : string CurrentValue ( ) const ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
void Read ( const CommandLineFlag & flag , void * dst ,
void Read ( const CommandLineFlag & flag , void * dst ,
const flags_internal : : FlagOpFn dst_op ) const
const flags_internal : : FlagOpFn dst_op ) const
ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
// Attempts to parse supplied `value` std::string.
// Attempts to parse supplied `value` std::string.
bool TryParse ( const CommandLineFlag & flag , void * dst , absl : : string_view value ,
bool TryParse ( const CommandLineFlag & flag , void * dst , absl : : string_view value ,
std : : string * err ) const
std : : string * err ) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED ( locks_ - > primary_mu ) ;
ABSL_EXCLUSIVE_LOCKS_REQUIRED ( * DataGuard ( ) ) ;
template < typename T >
template < typename T >
bool AtomicGet ( T * v ) const {
bool AtomicGet ( T * v ) const {
const int64_t r = atomic_ . load ( std : : memory_order_acquire ) ;
const int64_t r = atomic_ . load ( std : : memory_order_acquire ) ;
@ -174,23 +188,23 @@ class FlagImpl {
// Mutating access methods
// Mutating access methods
void Write ( const CommandLineFlag & flag , const void * src ,
void Write ( const CommandLineFlag & flag , const void * src ,
const flags_internal : : FlagOpFn src_op )
const flags_internal : : FlagOpFn src_op )
ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
bool SetFromString ( const CommandLineFlag & flag , absl : : string_view value ,
bool SetFromString ( const CommandLineFlag & flag , absl : : string_view value ,
FlagSettingMode set_mode , ValueSource source ,
FlagSettingMode set_mode , ValueSource source ,
std : : string * err ) ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
std : : string * err ) ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
// If possible, updates copy of the Flag's value that is stored in an
// If possible, updates copy of the Flag's value that is stored in an
// atomic word.
// atomic word.
void StoreAtomic ( ) ABSL_EXCLUSIVE_LOCKS_REQUIRED ( locks_ - > primary_mu ) ;
void StoreAtomic ( ) ABSL_EXCLUSIVE_LOCKS_REQUIRED ( * DataGuard ( ) ) ;
// Interfaces to operate on callbacks.
// Interfaces to operate on callbacks.
void SetCallback ( const flags_internal : : FlagCallback mutation_callback )
void SetCallback ( const flags_internal : : FlagCallback mutation_callback )
ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
void InvokeCallback ( ) const ABSL_EXCLUSIVE_LOCKS_REQUIRED ( locks_ - > primary_mu ) ;
void InvokeCallback ( ) const ABSL_EXCLUSIVE_LOCKS_REQUIRED ( * DataGuard ( ) ) ;
// Interfaces to save/restore mutable flag data
// Interfaces to save/restore mutable flag data
template < typename T >
template < typename T >
std : : unique_ptr < flags_internal : : FlagStateInterface > SaveState (
std : : unique_ptr < flags_internal : : FlagStateInterface > SaveState (
Flag < T > * flag ) const ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) {
Flag < T > * flag ) const ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) {
T & & cur_value = flag - > Get ( ) ;
T & & cur_value = flag - > Get ( ) ;
absl : : MutexLock l ( DataGuard ( ) ) ;
absl : : MutexLock l ( DataGuard ( ) ) ;
@ -199,13 +213,13 @@ class FlagImpl {
}
}
bool RestoreState ( const CommandLineFlag & flag , const void * value ,
bool RestoreState ( const CommandLineFlag & flag , const void * value ,
bool modified , bool on_command_line , int64_t counter )
bool modified , bool on_command_line , int64_t counter )
ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
// Value validation interfaces.
// Value validation interfaces.
void CheckDefaultValueParsingRoundtrip ( const CommandLineFlag & flag ) const
void CheckDefaultValueParsingRoundtrip ( const CommandLineFlag & flag ) const
ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
bool ValidateInputValue ( absl : : string_view value ) const
bool ValidateInputValue ( absl : : string_view value ) const
ABSL_LOCKS_EXCLUDED ( locks_ - > primary_mu ) ;
ABSL_LOCKS_EXCLUDED ( * DataGuard ( ) ) ;
private :
private :
// Lazy initialization of the Flag's data.
// Lazy initialization of the Flag's data.
@ -214,27 +228,36 @@ class FlagImpl {
// and returns pointer to the mutex guarding flags data.
// and returns pointer to the mutex guarding flags data.
absl : : Mutex * DataGuard ( ) const ABSL_LOCK_RETURNED ( locks_ - > primary_mu ) ;
absl : : Mutex * DataGuard ( ) const ABSL_LOCK_RETURNED ( locks_ - > primary_mu ) ;
// Returns heap allocated value of type T initialized with default value.
std : : unique_ptr < void , DynValueDeleter > MakeInitValue ( ) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED ( * DataGuard ( ) ) ;
// Immutable Flag's data.
// Immutable Flag's data.
const FlagOpFn op_ ; // Type-specific handler.
const FlagOpFn op_ ; // Type-specific handler.
const FlagMarshallingOpFn marshalling_op_ ; // Marshalling ops handler.
const FlagMarshallingOpFn marshalling_op_ ; // Marshalling ops handler.
const InitialValGenFunc initial_value_gen_ ; // Makes flag's initial value.
const FlagHelpSrc help_ ; // Help message literal or function to generate it.
const FlagHelpSrc help_ ; // Help message literal or function to generate it.
// Indicates if help message was supplied as literal or generator func.
// Indicates if help message was supplied as literal or generator func.
const FlagHelpSrcKind help_source_kind_ ;
const FlagHelpSrcKind help_source_kind_ ;
// Mutable Flag's data. (guarded by locks_->primary_mu ).
// Mutable Flag's data. (guarded by DataGuard() ).
// Indicates that locks_, cur_ and def _ fields have been lazily initialized.
// Indicates that locks_ and cur _ fields have been lazily initialized.
std : : atomic < bool > inited_ { false } ;
std : : atomic < bool > inited_ { false } ;
// Has flag value been modified?
// Has flag value been modified?
bool modified_ ABSL_GUARDED_BY ( locks_ - > primary_mu ) = false ;
bool modified_ ABSL_GUARDED_BY ( * DataGuard ( ) ) = false ;
// Specified on command line.
// Specified on command line.
bool on_command_line_ ABSL_GUARDED_BY ( locks_ - > primary_mu ) = false ;
bool on_command_line_ ABSL_GUARDED_BY ( * DataGuard ( ) ) = false ;
// Lazily initialized pointer to default value
// If def_kind_ == kDynamicValue, default_src_ holds a dynamically allocated
void * def_ ABSL_GUARDED_BY ( locks_ - > primary_mu ) = nullptr ;
// value.
FlagDefaultSrcKind def_kind_ ABSL_GUARDED_BY ( * DataGuard ( ) ) ;
// Either a pointer to the function generating the default value based on the
// value specified in ABSL_FLAG or pointer to the dynamically set default
// value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
// these two cases.
FlagDefaultSrc default_src_ ABSL_GUARDED_BY ( * DataGuard ( ) ) ;
// Lazily initialized pointer to current value
// Lazily initialized pointer to current value
void * cur_ ABSL_GUARDED_BY ( locks_ - > primary_mu ) = nullptr ;
void * cur_ ABSL_GUARDED_BY ( * DataGuard ( ) ) = nullptr ;
// Mutation counter
// Mutation counter
int64_t counter_ ABSL_GUARDED_BY ( locks_ - > primary_mu ) = 0 ;
int64_t counter_ ABSL_GUARDED_BY ( * DataGuard ( ) ) = 0 ;
// For some types, a copy of the current value is kept in an atomically
// For some types, a copy of the current value is kept in an atomically
// accessible field.
// accessible field.
std : : atomic < int64_t > atomic_ { flags_internal : : AtomicInit ( ) } ;
std : : atomic < int64_t > atomic_ { flags_internal : : AtomicInit ( ) } ;
@ -263,7 +286,7 @@ class Flag final : public flags_internal::CommandLineFlag {
constexpr Flag ( const char * name , const flags_internal : : HelpInitArg help ,
constexpr Flag ( const char * name , const flags_internal : : HelpInitArg help ,
const char * filename ,
const char * filename ,
const flags_internal : : FlagMarshallingOpFn marshalling_op ,
const flags_internal : : FlagMarshallingOpFn marshalling_op ,
const flags_internal : : InitialVal GenFunc initial_value_gen )
const flags_internal : : FlagDflt GenFunc initial_value_gen )
: flags_internal : : CommandLineFlag ( name , filename ) ,
: flags_internal : : CommandLineFlag ( name , filename ) ,
impl_ ( & flags_internal : : FlagOps < T > , marshalling_op , initial_value_gen ,
impl_ ( & flags_internal : : FlagOps < T > , marshalling_op , initial_value_gen ,
help ) { }
help ) { }