Export of internal Abseil changes
-- 693f81830b9f9cc8b24a1f38492b8dfcdd1d0e24 by Abseil Team <absl-team@google.com>: Check that absl::int128 works as a std::chrono::duration::rep. In particular, validate that ... std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<absl::int128, std::atto>> is a superset (range and resolution) of absl::Time. PiperOrigin-RevId: 283370280 -- df6073b686bd44223c6f9070fcceec918c728871 by Gennadiy Rozental <rogeeff@google.com>: Changes thread annotations to use DataGuard() function instead of a specific Mutex. Remove unused declaration of InvokeCallback. PiperOrigin-RevId: 283361188 -- b49eb2dd2ee1a0b4c8a7bb1a94e368b81ce5f861 by Abseil Team <absl-team@google.com>: Rewrite GetNominalCPUFrequency to use advapi32 instead of shlwapi Using shlwapi.dll means that gdi32.dll is loaded which then makes process destruction more expensive, which is unacceptable for some uses. There may be other places that pull in gdi32.dll - this just fixes the one. PiperOrigin-RevId: 282960698 -- b5508afec5099a0fdbb55e39a7cd2993259ed860 by Abseil Team <absl-team@google.com>: Small typo fix in comments: initiazliation -> initialization PiperOrigin-RevId: 282891800 -- 4319cc419584e91ee74f6ae1a32d88a412fc5c01 by Abseil Team <absl-team@google.com>: Update c_find_first_of() comment to remove the mention of an ordered container. PiperOrigin-RevId: 282836540 -- 5fcabc0a834dff39a505d5a5fc5403ddeb96028e by Derek Mauro <dmauro@google.com>: Fix NaCl build, where format checking is broken PiperOrigin-RevId: 282826202 -- aaf9ad3274c056a2f68e9b8ccada45c9802e2f1e by Derek Mauro <dmauro@google.com>: Fix more -Wundef warnings PiperOrigin-RevId: 282799820 -- 1fb06150a70ffe98bf4b2d42b2a39d083bf44f8c by Derek Mauro <dmauro@google.com>: Release support for additional platforms PiperOrigin-RevId: 282793384 -- fa947fc28624a316fa872d7045b3838b88a0d69b by Derek Mauro <dmauro@google.com>: Cleanup inconsistent usage of __has_attribute PiperOrigin-RevId: 282793296 -- 990030ad282263d6303c83b780a55fdec8e90d43 by Gennadiy Rozental <rogeeff@google.com>: Eliminate the pointer in absl::Flag, which points to n space where we were storing flag's default value. We also eliminate additional (now unnecessary) allocation for flag's default value. Instead we'll initialize the flags value directly from the value specified in ABSL_FLAG. If the default value is updated via the call to SetCommandLineOptionWithMode we are replacing pointer to initialization routine to pointer to new default value. PiperOrigin-RevId: 282637616 GitOrigin-RevId: 693f81830b9f9cc8b24a1f38492b8dfcdd1d0e24 Change-Id: I6f2edd8ef844de09aa2c182a7ca3133a22364792
This commit is contained in:
parent
0514227d25
commit
a4b757b5d4
20 changed files with 200 additions and 114 deletions
|
@ -268,7 +268,8 @@ container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
|
||||||
// c_find_first_of()
|
// c_find_first_of()
|
||||||
//
|
//
|
||||||
// Container-based version of the <algorithm> `std::find_first_of()` function to
|
// Container-based version of the <algorithm> `std::find_first_of()` function to
|
||||||
// find the first elements in an ordered set within a container.
|
// find the first element within the container that is also within the options
|
||||||
|
// container.
|
||||||
template <typename C1, typename C2>
|
template <typename C1, typename C2>
|
||||||
container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
|
container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
|
||||||
C2& options) {
|
C2& options) {
|
||||||
|
|
|
@ -193,7 +193,7 @@ cc_library(
|
||||||
copts = ABSL_DEFAULT_COPTS,
|
copts = ABSL_DEFAULT_COPTS,
|
||||||
linkopts = select({
|
linkopts = select({
|
||||||
"//absl:windows": [
|
"//absl:windows": [
|
||||||
"-DEFAULTLIB:shlwapi.lib",
|
"-DEFAULTLIB:advapi32.lib",
|
||||||
],
|
],
|
||||||
"//conditions:default": ["-pthread"],
|
"//conditions:default": ["-pthread"],
|
||||||
}) + ABSL_DEFAULT_LINKOPTS,
|
}) + ABSL_DEFAULT_LINKOPTS,
|
||||||
|
|
|
@ -176,7 +176,7 @@ absl_cc_library(
|
||||||
LINKOPTS
|
LINKOPTS
|
||||||
${ABSL_DEFAULT_LINKOPTS}
|
${ABSL_DEFAULT_LINKOPTS}
|
||||||
$<$<BOOL:${LIBRT}>:${LIBRT}>
|
$<$<BOOL:${LIBRT}>:${LIBRT}>
|
||||||
$<$<BOOL:${MINGW}>:"shlwapi">
|
$<$<BOOL:${MINGW}>:"advapi32">
|
||||||
DEPS
|
DEPS
|
||||||
absl::atomic_hook
|
absl::atomic_hook
|
||||||
absl::base_internal
|
absl::base_internal
|
||||||
|
|
|
@ -63,7 +63,7 @@ class AtomicHook<ReturnType (*)(Args...)> {
|
||||||
explicit constexpr AtomicHook(FnPtr default_fn)
|
explicit constexpr AtomicHook(FnPtr default_fn)
|
||||||
: hook_(default_fn), default_fn_(default_fn) {}
|
: hook_(default_fn), default_fn_(default_fn) {}
|
||||||
#else
|
#else
|
||||||
// On MSVC, this function sometimes executes after dynamic initiazliation =(.
|
// On MSVC, this function sometimes executes after dynamic initialization =(.
|
||||||
// If a non-zero `hook_` has been installed by a dynamic initializer, we want
|
// If a non-zero `hook_` has been installed by a dynamic initializer, we want
|
||||||
// to preserve it. If not, `hook_` will be zero initialized and we have no
|
// to preserve it. If not, `hook_` will be zero initialized and we have no
|
||||||
// need to set it to `kUninitialized`.
|
// need to set it to `kUninitialized`.
|
||||||
|
|
|
@ -37,9 +37,9 @@
|
||||||
// this, consider moving both to config.h instead.
|
// this, consider moving both to config.h instead.
|
||||||
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||||
defined(__Fuchsia__) || defined(__native_client__) || \
|
defined(__Fuchsia__) || defined(__native_client__) || \
|
||||||
defined(__EMSCRIPTEN__)
|
defined(__EMSCRIPTEN__) || defined(__ASYLO__)
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#define ABSL_HAVE_POSIX_WRITE 1
|
#define ABSL_HAVE_POSIX_WRITE 1
|
||||||
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
|
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "absl/base/attributes.h"
|
#include "absl/base/attributes.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <shlwapi.h>
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -76,14 +75,23 @@ static int GetNumCPUs() {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
static double GetNominalCPUFrequency() {
|
static double GetNominalCPUFrequency() {
|
||||||
DWORD data;
|
#pragma comment(lib, "advapi32.lib") // For Reg* functions.
|
||||||
DWORD data_size = sizeof(data);
|
HKEY key;
|
||||||
#pragma comment(lib, "shlwapi.lib") // For SHGetValue().
|
// Use the Reg* functions rather than the SH functions because shlwapi.dll
|
||||||
if (SUCCEEDED(
|
// pulls in gdi32.dll which makes process destruction much more costly.
|
||||||
SHGetValueA(HKEY_LOCAL_MACHINE,
|
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
|
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
|
||||||
"~MHz", nullptr, &data, &data_size))) {
|
KEY_READ, &key) == ERROR_SUCCESS) {
|
||||||
return data * 1e6; // Value is MHz.
|
DWORD type = 0;
|
||||||
|
DWORD data = 0;
|
||||||
|
DWORD data_size = sizeof(data);
|
||||||
|
auto result = RegQueryValueExA(key, "~MHz", 0, &type,
|
||||||
|
reinterpret_cast<LPBYTE>(&data), &data_size);
|
||||||
|
RegCloseKey(key);
|
||||||
|
if (result == ERROR_SUCCESS && type == REG_DWORD &&
|
||||||
|
data_size == sizeof(data)) {
|
||||||
|
return data * 1e6; // Value is MHz.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "absl/base/attributes.h"
|
||||||
#include "absl/base/optimization.h"
|
#include "absl/base/optimization.h"
|
||||||
#include "absl/base/port.h"
|
#include "absl/base/port.h"
|
||||||
|
|
||||||
|
@ -176,12 +177,9 @@ enum LinkerInitialized {
|
||||||
// ABSL_BAD_CALL_IF(c <= -1 || c > 255,
|
// ABSL_BAD_CALL_IF(c <= -1 || c > 255,
|
||||||
// "'c' must have the value of an unsigned char or EOF");
|
// "'c' must have the value of an unsigned char or EOF");
|
||||||
// #endif // ABSL_BAD_CALL_IF
|
// #endif // ABSL_BAD_CALL_IF
|
||||||
|
#if ABSL_HAVE_ATTRIBUTE(enable_if)
|
||||||
#if defined(__clang__)
|
#define ABSL_BAD_CALL_IF(expr, msg) \
|
||||||
# if __has_attribute(enable_if)
|
__attribute__((enable_if(expr, "Bad call trap"), unavailable(msg)))
|
||||||
# define ABSL_BAD_CALL_IF(expr, msg) \
|
|
||||||
__attribute__((enable_if(expr, "Bad call trap"), unavailable(msg)))
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ABSL_ASSERT()
|
// ABSL_ASSERT()
|
||||||
|
|
|
@ -96,12 +96,12 @@ class Flag {
|
||||||
constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen,
|
constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen,
|
||||||
const char* filename,
|
const char* filename,
|
||||||
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)
|
||||||
: name_(name),
|
: name_(name),
|
||||||
help_gen_(help_gen),
|
help_gen_(help_gen),
|
||||||
filename_(filename),
|
filename_(filename),
|
||||||
marshalling_op_(marshalling_op),
|
marshalling_op_(marshalling_op),
|
||||||
initial_value_gen_(initial_value_gen),
|
default_value_gen_(default_value_gen),
|
||||||
inited_(false),
|
inited_(false),
|
||||||
impl_(nullptr) {}
|
impl_(nullptr) {}
|
||||||
#endif
|
#endif
|
||||||
|
@ -118,7 +118,7 @@ class Flag {
|
||||||
name_,
|
name_,
|
||||||
{flags_internal::FlagHelpSrc(help_gen_),
|
{flags_internal::FlagHelpSrc(help_gen_),
|
||||||
flags_internal::FlagHelpSrcKind::kGenFunc},
|
flags_internal::FlagHelpSrcKind::kGenFunc},
|
||||||
filename_, marshalling_op_, initial_value_gen_);
|
filename_, marshalling_op_, default_value_gen_);
|
||||||
inited_.store(true, std::memory_order_release);
|
inited_.store(true, std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ class Flag {
|
||||||
const flags_internal::HelpGenFunc help_gen_;
|
const flags_internal::HelpGenFunc help_gen_;
|
||||||
const char* filename_;
|
const char* filename_;
|
||||||
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_;
|
||||||
|
|
||||||
mutable std::atomic<bool> inited_;
|
mutable std::atomic<bool> inited_;
|
||||||
mutable flags_internal::Flag<T>* impl_;
|
mutable flags_internal::Flag<T>* impl_;
|
||||||
|
|
|
@ -49,12 +49,11 @@ void FlagImpl::Init() {
|
||||||
|
|
||||||
absl::MutexLock lock(&locks_->primary_mu);
|
absl::MutexLock lock(&locks_->primary_mu);
|
||||||
|
|
||||||
if (def_ != nullptr) {
|
if (cur_ != nullptr) {
|
||||||
inited_.store(true, std::memory_order_release);
|
inited_.store(true, std::memory_order_release);
|
||||||
} else {
|
} else {
|
||||||
// Need to initialize def and cur fields.
|
// Need to initialize cur field.
|
||||||
def_ = (*initial_value_gen_)();
|
cur_ = MakeInitValue().release();
|
||||||
cur_ = Clone(op_, def_);
|
|
||||||
StoreAtomic();
|
StoreAtomic();
|
||||||
inited_.store(true, std::memory_order_release);
|
inited_.store(true, std::memory_order_release);
|
||||||
InvokeCallback();
|
InvokeCallback();
|
||||||
|
@ -63,8 +62,7 @@ void FlagImpl::Init() {
|
||||||
|
|
||||||
// Ensures that the lazily initialized data is initialized,
|
// Ensures that the lazily initialized data is initialized,
|
||||||
// and returns pointer to the mutex guarding flags data.
|
// and returns pointer to the mutex guarding flags data.
|
||||||
absl::Mutex* FlagImpl::DataGuard() const
|
absl::Mutex* FlagImpl::DataGuard() const {
|
||||||
ABSL_LOCK_RETURNED(locks_->primary_mu) {
|
|
||||||
if (ABSL_PREDICT_FALSE(!inited_.load(std::memory_order_acquire))) {
|
if (ABSL_PREDICT_FALSE(!inited_.load(std::memory_order_acquire))) {
|
||||||
const_cast<FlagImpl*>(this)->Init();
|
const_cast<FlagImpl*>(this)->Init();
|
||||||
}
|
}
|
||||||
|
@ -79,12 +77,23 @@ void FlagImpl::Destroy() const {
|
||||||
|
|
||||||
// Values are heap allocated for Abseil Flags.
|
// Values are heap allocated for Abseil Flags.
|
||||||
if (cur_) Delete(op_, cur_);
|
if (cur_) Delete(op_, cur_);
|
||||||
if (def_) Delete(op_, def_);
|
if (def_kind_ == FlagDefaultSrcKind::kDynamicValue)
|
||||||
|
Delete(op_, default_src_.dynamic_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete locks_;
|
delete locks_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {
|
||||||
|
void* res = nullptr;
|
||||||
|
if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) {
|
||||||
|
res = Clone(op_, default_src_.dynamic_value);
|
||||||
|
} else {
|
||||||
|
res = (*default_src_.gen_func)();
|
||||||
|
}
|
||||||
|
return {res, DynValueDeleter{op_}};
|
||||||
|
}
|
||||||
|
|
||||||
std::string FlagImpl::Help() const {
|
std::string FlagImpl::Help() const {
|
||||||
return help_source_kind_ == FlagHelpSrcKind::kLiteral ? help_.literal
|
return help_source_kind_ == FlagHelpSrcKind::kLiteral ? help_.literal
|
||||||
: help_.gen_func();
|
: help_.gen_func();
|
||||||
|
@ -103,7 +112,8 @@ bool FlagImpl::IsSpecifiedOnCommandLine() const {
|
||||||
std::string FlagImpl::DefaultValue() const {
|
std::string FlagImpl::DefaultValue() const {
|
||||||
absl::MutexLock l(DataGuard());
|
absl::MutexLock l(DataGuard());
|
||||||
|
|
||||||
return Unparse(marshalling_op_, def_);
|
auto obj = MakeInitValue();
|
||||||
|
return Unparse(marshalling_op_, obj.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FlagImpl::CurrentValue() const {
|
std::string FlagImpl::CurrentValue() const {
|
||||||
|
@ -121,8 +131,7 @@ void FlagImpl::SetCallback(
|
||||||
InvokeCallback();
|
InvokeCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlagImpl::InvokeCallback() const
|
void FlagImpl::InvokeCallback() const {
|
||||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) {
|
|
||||||
if (!callback_) return;
|
if (!callback_) return;
|
||||||
|
|
||||||
// If the flag has a mutation callback this function invokes it. While the
|
// If the flag has a mutation callback this function invokes it. While the
|
||||||
|
@ -172,23 +181,20 @@ bool FlagImpl::RestoreState(const CommandLineFlag& flag, const void* value,
|
||||||
// 'dst' assuming it is a pointer to the flag's value type. In case if any error
|
// 'dst' assuming it is a pointer to the flag's value type. In case if any error
|
||||||
// is encountered in either step, the error message is stored in 'err'
|
// is encountered in either step, the error message is stored in 'err'
|
||||||
bool FlagImpl::TryParse(const CommandLineFlag& flag, void* dst,
|
bool FlagImpl::TryParse(const CommandLineFlag& flag, void* dst,
|
||||||
absl::string_view value, std::string* err) const
|
absl::string_view value, std::string* err) const {
|
||||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) {
|
auto tentative_value = MakeInitValue();
|
||||||
void* tentative_value = Clone(op_, def_);
|
|
||||||
std::string parse_err;
|
std::string parse_err;
|
||||||
if (!Parse(marshalling_op_, value, tentative_value, &parse_err)) {
|
if (!Parse(marshalling_op_, value, tentative_value.get(), &parse_err)) {
|
||||||
auto type_name = flag.Typename();
|
auto type_name = flag.Typename();
|
||||||
absl::string_view err_sep = parse_err.empty() ? "" : "; ";
|
absl::string_view err_sep = parse_err.empty() ? "" : "; ";
|
||||||
absl::string_view typename_sep = type_name.empty() ? "" : " ";
|
absl::string_view typename_sep = type_name.empty() ? "" : " ";
|
||||||
*err = absl::StrCat("Illegal value '", value, "' specified for",
|
*err = absl::StrCat("Illegal value '", value, "' specified for",
|
||||||
typename_sep, type_name, " flag '", flag.Name(), "'",
|
typename_sep, type_name, " flag '", flag.Name(), "'",
|
||||||
err_sep, parse_err);
|
err_sep, parse_err);
|
||||||
Delete(op_, tentative_value);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Copy(op_, tentative_value, dst);
|
Copy(op_, tentative_value.get(), dst);
|
||||||
Delete(op_, tentative_value);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +214,7 @@ void FlagImpl::Read(const CommandLineFlag& flag, void* dst,
|
||||||
CopyConstruct(op_, cur_, dst);
|
CopyConstruct(op_, cur_, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlagImpl::StoreAtomic() ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) {
|
void FlagImpl::StoreAtomic() {
|
||||||
size_t data_size = Sizeof(op_);
|
size_t data_size = Sizeof(op_);
|
||||||
|
|
||||||
if (data_size <= sizeof(int64_t)) {
|
if (data_size <= sizeof(int64_t)) {
|
||||||
|
@ -299,12 +305,22 @@ bool FlagImpl::SetFromString(const CommandLineFlag& flag,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SET_FLAGS_DEFAULT: {
|
case SET_FLAGS_DEFAULT: {
|
||||||
// modify the flag's default-value
|
// Flag's new default-value.
|
||||||
if (!TryParse(flag, def_, value, err)) return false;
|
auto new_default_value = MakeInitValue();
|
||||||
|
|
||||||
|
if (!TryParse(flag, new_default_value.get(), value, err)) return false;
|
||||||
|
|
||||||
|
if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) {
|
||||||
|
// Release old default value.
|
||||||
|
Delete(op_, default_src_.dynamic_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
default_src_.dynamic_value = new_default_value.release();
|
||||||
|
def_kind_ = FlagDefaultSrcKind::kDynamicValue;
|
||||||
|
|
||||||
if (!modified_) {
|
if (!modified_) {
|
||||||
// Need to set both default value *and* current, in this case
|
// Need to set both default value *and* current, in this case
|
||||||
Copy(op_, def_, cur_);
|
Copy(op_, default_src_.dynamic_value, cur_);
|
||||||
StoreAtomic();
|
StoreAtomic();
|
||||||
InvokeCallback();
|
InvokeCallback();
|
||||||
}
|
}
|
||||||
|
@ -321,9 +337,9 @@ void FlagImpl::CheckDefaultValueParsingRoundtrip(
|
||||||
|
|
||||||
absl::MutexLock lock(DataGuard());
|
absl::MutexLock lock(DataGuard());
|
||||||
|
|
||||||
void* dst = Clone(op_, def_);
|
auto dst = MakeInitValue();
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!flags_internal::Parse(marshalling_op_, v, dst, &error)) {
|
if (!flags_internal::Parse(marshalling_op_, v, dst.get(), &error)) {
|
||||||
ABSL_INTERNAL_LOG(
|
ABSL_INTERNAL_LOG(
|
||||||
FATAL,
|
FATAL,
|
||||||
absl::StrCat("Flag ", flag.Name(), " (from ", flag.Filename(),
|
absl::StrCat("Flag ", flag.Name(), " (from ", flag.Filename(),
|
||||||
|
@ -333,18 +349,15 @@ void FlagImpl::CheckDefaultValueParsingRoundtrip(
|
||||||
|
|
||||||
// We do not compare dst to def since parsing/unparsing may make
|
// We do not compare dst to def since parsing/unparsing may make
|
||||||
// small changes, e.g., precision loss for floating point types.
|
// small changes, e.g., precision loss for floating point types.
|
||||||
Delete(op_, dst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlagImpl::ValidateInputValue(absl::string_view value) const {
|
bool FlagImpl::ValidateInputValue(absl::string_view value) const {
|
||||||
absl::MutexLock l(DataGuard());
|
absl::MutexLock l(DataGuard());
|
||||||
|
|
||||||
void* obj = Clone(op_, def_);
|
auto obj = MakeInitValue();
|
||||||
std::string ignored_error;
|
std::string ignored_error;
|
||||||
const bool result =
|
return flags_internal::Parse(marshalling_op_, value, obj.get(),
|
||||||
flags_internal::Parse(marshalling_op_, value, obj, &ignored_error);
|
&ignored_error);
|
||||||
Delete(op_, obj);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace flags_internal
|
} // namespace flags_internal
|
||||||
|
|
|
@ -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::InitialValGenFunc initial_value_gen)
|
const flags_internal::FlagDfltGenFunc 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) {}
|
||||||
|
|
|
@ -297,6 +297,7 @@ cc_library(
|
||||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||||
deps = [
|
deps = [
|
||||||
":platform",
|
":platform",
|
||||||
|
"//absl/base:core_headers",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -659,6 +660,7 @@ cc_library(
|
||||||
deps = [
|
deps = [
|
||||||
":platform",
|
":platform",
|
||||||
":randen_engine",
|
":randen_engine",
|
||||||
|
"//absl/base:core_headers",
|
||||||
"//absl/base:raw_logging_internal",
|
"//absl/base:raw_logging_internal",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/base/attributes.h"
|
||||||
#include "absl/base/internal/raw_logging.h"
|
#include "absl/base/internal/raw_logging.h"
|
||||||
#include "absl/random/internal/platform.h"
|
#include "absl/random/internal/platform.h"
|
||||||
#include "absl/random/internal/randen_engine.h"
|
#include "absl/random/internal/randen_engine.h"
|
||||||
|
@ -59,15 +60,6 @@
|
||||||
#include <time.h> // NOLINT
|
#include <time.h> // NOLINT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ABSL_HAVE_ATTRIBUTE
|
|
||||||
#if !defined(ABSL_HAVE_ATTRIBUTE)
|
|
||||||
#ifdef __has_attribute
|
|
||||||
#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x)
|
|
||||||
#else
|
|
||||||
#define ABSL_HAVE_ATTRIBUTE(x) 0
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE prevents inlining of the method.
|
// ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE prevents inlining of the method.
|
||||||
#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))
|
#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))
|
||||||
#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE __attribute__((noinline))
|
#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE __attribute__((noinline))
|
||||||
|
|
|
@ -18,17 +18,9 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "absl/base/attributes.h"
|
||||||
#include "absl/random/internal/platform.h"
|
#include "absl/random/internal/platform.h"
|
||||||
|
|
||||||
// ABSL_HAVE_ATTRIBUTE
|
|
||||||
#if !defined(ABSL_HAVE_ATTRIBUTE)
|
|
||||||
#ifdef __has_attribute
|
|
||||||
#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x)
|
|
||||||
#else
|
|
||||||
#define ABSL_HAVE_ATTRIBUTE(x) 0
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ABSL_HAVE_ATTRIBUTE(always_inline) || \
|
#if ABSL_HAVE_ATTRIBUTE(always_inline) || \
|
||||||
(defined(__GNUC__) && !defined(__clang__))
|
(defined(__GNUC__) && !defined(__clang__))
|
||||||
#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE \
|
#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE \
|
||||||
|
|
|
@ -45,6 +45,9 @@
|
||||||
#define ABSL_RANDOM_USE_BCRYPT 1
|
#define ABSL_RANDOM_USE_BCRYPT 1
|
||||||
#pragma comment(lib, "bcrypt.lib")
|
#pragma comment(lib, "bcrypt.lib")
|
||||||
|
|
||||||
|
#elif defined(__Fuchsia__)
|
||||||
|
#include <zircon/syscalls.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ABSL_RANDOM_USE_BCRYPT)
|
#if defined(ABSL_RANDOM_USE_BCRYPT)
|
||||||
|
@ -107,6 +110,15 @@ bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(__Fuchsia__)
|
||||||
|
|
||||||
|
bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
|
||||||
|
auto buffer = reinterpret_cast<uint8_t*>(values.data());
|
||||||
|
size_t buffer_size = sizeof(uint32_t) * values.size();
|
||||||
|
zx_cprng_draw(buffer, buffer_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// On *nix, read entropy from /dev/urandom.
|
// On *nix, read entropy from /dev/urandom.
|
||||||
|
|
|
@ -73,7 +73,7 @@ class FormatSpecTemplate
|
||||||
using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
|
using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
||||||
|
|
||||||
// Honeypot overload for when the std::string is not constexpr.
|
// Honeypot overload for when the std::string is not constexpr.
|
||||||
// We use the 'unavailable' attribute to give a better compiler error than
|
// We use the 'unavailable' attribute to give a better compiler error than
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
|
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
|
||||||
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
|
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
|
||||||
|
|
||||||
|
#include "absl/base/attributes.h"
|
||||||
#include "absl/strings/internal/str_format/arg.h"
|
#include "absl/strings/internal/str_format/arg.h"
|
||||||
#include "absl/strings/internal/str_format/extension.h"
|
#include "absl/strings/internal/str_format/extension.h"
|
||||||
|
|
||||||
// Compile time check support for entry points.
|
// Compile time check support for entry points.
|
||||||
|
|
||||||
#ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
#ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
||||||
#if defined(__clang__) && !defined(__native_client__)
|
#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
|
||||||
#if __has_attribute(enable_if)
|
|
||||||
#define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
|
#define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
|
||||||
#endif // __has_attribute(enable_if)
|
#endif // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
|
||||||
#endif // defined(__clang__) && !defined(__native_client__)
|
|
||||||
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
||||||
|
|
||||||
namespace absl {
|
namespace absl {
|
||||||
|
@ -31,7 +30,7 @@ constexpr Conv ArgumentToConv() {
|
||||||
std::declval<FormatSinkImpl*>()))::kConv;
|
std::declval<FormatSinkImpl*>()))::kConv;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
||||||
|
|
||||||
constexpr bool ContainsChar(const char* chars, char c) {
|
constexpr bool ContainsChar(const char* chars, char c) {
|
||||||
return *chars == c || (*chars && ContainsChar(chars + 1, c));
|
return *chars == c || (*chars && ContainsChar(chars + 1, c));
|
||||||
|
|
|
@ -35,7 +35,7 @@ TEST(StrFormatChecker, ArgumentToConv) {
|
||||||
EXPECT_EQ(ConvToString(conv), "p");
|
EXPECT_EQ(ConvToString(conv), "p");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
||||||
|
|
||||||
struct Case {
|
struct Case {
|
||||||
bool result;
|
bool result;
|
||||||
|
|
|
@ -274,7 +274,7 @@ template <str_format_internal::Conv... C>
|
||||||
class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
|
class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
|
||||||
public:
|
public:
|
||||||
explicit ExtendedParsedFormat(string_view format)
|
explicit ExtendedParsedFormat(string_view format)
|
||||||
#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
|
||||||
__attribute__((
|
__attribute__((
|
||||||
enable_if(str_format_internal::EnsureConstexpr(format),
|
enable_if(str_format_internal::EnsureConstexpr(format),
|
||||||
"Format std::string is not constexpr."),
|
"Format std::string is not constexpr."),
|
||||||
|
|
|
@ -93,6 +93,7 @@ cc_test(
|
||||||
":time",
|
":time",
|
||||||
"//absl/base:config",
|
"//absl/base:config",
|
||||||
"//absl/base:core_headers",
|
"//absl/base:core_headers",
|
||||||
|
"//absl/numeric:int128",
|
||||||
"//absl/time/internal/cctz:time_zone",
|
"//absl/time/internal/cctz:time_zone",
|
||||||
"@com_google_googletest//:gtest_main",
|
"@com_google_googletest//:gtest_main",
|
||||||
],
|
],
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "absl/numeric/int128.h"
|
||||||
#include "absl/time/clock.h"
|
#include "absl/time/clock.h"
|
||||||
#include "absl/time/internal/test_util.h"
|
#include "absl/time/internal/test_util.h"
|
||||||
|
|
||||||
|
@ -575,6 +576,50 @@ TEST(Time, ToChronoTime) {
|
||||||
absl::ToChronoTime(absl::UnixEpoch() - tick));
|
absl::ToChronoTime(absl::UnixEpoch() - tick));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that absl::int128 works as a std::chrono::duration representation.
|
||||||
|
TEST(Time, Chrono128) {
|
||||||
|
// Define a std::chrono::time_point type whose time[sic]_since_epoch() is
|
||||||
|
// a signed 128-bit count of attoseconds. This has a range and resolution
|
||||||
|
// (currently) beyond those of absl::Time, and undoubtedly also beyond those
|
||||||
|
// of std::chrono::system_clock::time_point.
|
||||||
|
//
|
||||||
|
// Note: The to/from-chrono support should probably be updated to handle
|
||||||
|
// such wide representations.
|
||||||
|
using Timestamp =
|
||||||
|
std::chrono::time_point<std::chrono::system_clock,
|
||||||
|
std::chrono::duration<absl::int128, std::atto>>;
|
||||||
|
|
||||||
|
// Expect that we can round-trip the std::chrono::system_clock::time_point
|
||||||
|
// extremes through both absl::Time and Timestamp, and that Timestamp can
|
||||||
|
// handle the (current) absl::Time extremes.
|
||||||
|
//
|
||||||
|
// Note: We should use std::chrono::floor() instead of time_point_cast(),
|
||||||
|
// but floor() is only available since c++17.
|
||||||
|
for (const auto tp : {std::chrono::system_clock::time_point::min(),
|
||||||
|
std::chrono::system_clock::time_point::max()}) {
|
||||||
|
EXPECT_EQ(tp, absl::ToChronoTime(absl::FromChrono(tp)));
|
||||||
|
EXPECT_EQ(tp, std::chrono::time_point_cast<
|
||||||
|
std::chrono::system_clock::time_point::duration>(
|
||||||
|
std::chrono::time_point_cast<Timestamp::duration>(tp)));
|
||||||
|
}
|
||||||
|
Timestamp::duration::rep v = std::numeric_limits<int64_t>::min();
|
||||||
|
v *= Timestamp::duration::period::den;
|
||||||
|
auto ts = Timestamp(Timestamp::duration(v));
|
||||||
|
ts += std::chrono::duration<int64_t, std::atto>(0);
|
||||||
|
EXPECT_EQ(std::numeric_limits<int64_t>::min(),
|
||||||
|
ts.time_since_epoch().count() / Timestamp::duration::period::den);
|
||||||
|
EXPECT_EQ(0,
|
||||||
|
ts.time_since_epoch().count() % Timestamp::duration::period::den);
|
||||||
|
v = std::numeric_limits<int64_t>::max();
|
||||||
|
v *= Timestamp::duration::period::den;
|
||||||
|
ts = Timestamp(Timestamp::duration(v));
|
||||||
|
ts += std::chrono::duration<int64_t, std::atto>(999999999750000000);
|
||||||
|
EXPECT_EQ(std::numeric_limits<int64_t>::max(),
|
||||||
|
ts.time_since_epoch().count() / Timestamp::duration::period::den);
|
||||||
|
EXPECT_EQ(999999999750000000,
|
||||||
|
ts.time_since_epoch().count() % Timestamp::duration::period::den);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Time, TimeZoneAt) {
|
TEST(Time, TimeZoneAt) {
|
||||||
const absl::TimeZone nyc =
|
const absl::TimeZone nyc =
|
||||||
absl::time_internal::LoadTimeZone("America/New_York");
|
absl::time_internal::LoadTimeZone("America/New_York");
|
||||||
|
|
Loading…
Reference in a new issue