Commit dbae8764 by Abseil Team Committed by Shaindel Schwartz

Export of internal Abseil changes.

--
3f04cd3c25a99df91ff913977b8c5b343532db5d by Abseil Team <absl-team@google.com>:

Stricter memory order constraints for CycleClock callback.

PiperOrigin-RevId: 242670115

--
216db48375306490f1722a11aaf33080939d9f2f by Abseil Team <absl-team@google.com>:

internal/optional.h: move macro from types/optional.h

ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS is only used within this file.
additionally check the macro with #ifdef rather than #if, fixes -Wundef
warning:
'ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS' is not defined, evaluates to 0
PiperOrigin-RevId: 242548205

--
fbe22e7d8dc5c0b3d43ac26297e97ddbaeab3d39 by Samuel Benzaquen <sbenza@google.com>:

Implement %f natively for any input.
It evaluates the input at runtime and allocates stack space accordingly.

This removes a potential fallback into snprintf, improves performance, and removes all memory allocations in this formatting path.

PiperOrigin-RevId: 242531736

--
1458f9ba2a79ef0534e46527cd34770dee54164d by Greg Falcon <gfalcon@google.com>:

Add explicit check for NVCC in compressed_tuple.h.

NVCC claims to be MSVC, but does not implement this MSVC attribute.

PiperOrigin-RevId: 242513453
GitOrigin-RevId: 3f04cd3c25a99df91ff913977b8c5b343532db5d
Change-Id: I0742e8619c5248c7607961113e406486bc0e279b
parent 044da8a2
...@@ -55,10 +55,23 @@ static constexpr int32_t kShift = 2; ...@@ -55,10 +55,23 @@ static constexpr int32_t kShift = 2;
static constexpr double kFrequencyScale = 1.0 / (1 << kShift); static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
static std::atomic<CycleClockSourceFunc> cycle_clock_source; static std::atomic<CycleClockSourceFunc> cycle_clock_source;
CycleClockSourceFunc LoadCycleClockSource() {
// Optimize for the common case (no callback) by first doing a relaxed load;
// this is significantly faster on non-x86 platforms.
if (cycle_clock_source.load(std::memory_order_relaxed) == nullptr) {
return nullptr;
}
// This corresponds to the store(std::memory_order_release) in
// CycleClockSource::Register, and makes sure that any updates made prior to
// registering the callback are visible to this thread before the callback is
// invoked.
return cycle_clock_source.load(std::memory_order_acquire);
}
} // namespace } // namespace
int64_t CycleClock::Now() { int64_t CycleClock::Now() {
auto fn = cycle_clock_source.load(std::memory_order_relaxed); auto fn = LoadCycleClockSource();
if (fn == nullptr) { if (fn == nullptr) {
return base_internal::UnscaledCycleClock::Now() >> kShift; return base_internal::UnscaledCycleClock::Now() >> kShift;
} }
...@@ -70,7 +83,8 @@ double CycleClock::Frequency() { ...@@ -70,7 +83,8 @@ double CycleClock::Frequency() {
} }
void CycleClockSource::Register(CycleClockSourceFunc source) { void CycleClockSource::Register(CycleClockSourceFunc source) {
cycle_clock_source.store(source, std::memory_order_relaxed); // Corresponds to the load(std::memory_order_acquire) in LoadCycleClockSource.
cycle_clock_source.store(source, std::memory_order_release);
} }
#else #else
......
...@@ -38,13 +38,13 @@ ...@@ -38,13 +38,13 @@
#include "absl/utility/utility.h" #include "absl/utility/utility.h"
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__NVCC__)
// We need to mark these classes with this declspec to ensure that // We need to mark these classes with this declspec to ensure that
// CompressedTuple happens. // CompressedTuple happens.
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases) #define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
#else // _MSC_VER #else
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC #define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
#endif // _MSC_VER #endif
namespace absl { namespace absl {
namespace container_internal { namespace container_internal {
......
...@@ -557,7 +557,6 @@ cc_library( ...@@ -557,7 +557,6 @@ cc_library(
visibility = ["//visibility:private"], visibility = ["//visibility:private"],
deps = [ deps = [
":strings", ":strings",
"//absl/base:bits",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/container:inlined_vector", "//absl/container:inlined_vector",
"//absl/meta:type_traits", "//absl/meta:type_traits",
......
...@@ -384,7 +384,6 @@ absl_cc_library( ...@@ -384,7 +384,6 @@ absl_cc_library(
COPTS COPTS
${ABSL_DEFAULT_COPTS} ${ABSL_DEFAULT_COPTS}
DEPS DEPS
absl::bits
absl::strings absl::strings
absl::core_headers absl::core_headers
absl::inlined_vector absl::inlined_vector
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <cmath> #include <cmath>
#include <limits>
#include <string> #include <string>
#include "gtest/gtest.h" #include "gtest/gtest.h"
...@@ -398,8 +397,8 @@ TEST_F(FormatConvertTest, Float) { ...@@ -398,8 +397,8 @@ TEST_F(FormatConvertTest, Float) {
#endif // _MSC_VER #endif // _MSC_VER
const char *const kFormats[] = { const char *const kFormats[] = {
"%", "%.3", "%8.5", "%9", "%.5000", "%.60", "%.30", "%03", "%", "%.3", "%8.5", "%9", "%.60", "%.30", "%03", "%+",
"%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"};
std::vector<double> doubles = {0.0, std::vector<double> doubles = {0.0,
-0.0, -0.0,
...@@ -439,36 +438,12 @@ TEST_F(FormatConvertTest, Float) { ...@@ -439,36 +438,12 @@ TEST_F(FormatConvertTest, Float) {
} }
} }
// Workaround libc bug.
// https://sourceware.org/bugzilla/show_bug.cgi?id=22142
if (StrPrint("%f", std::numeric_limits<double>::max()) !=
"1797693134862315708145274237317043567980705675258449965989174768031"
"5726078002853876058955863276687817154045895351438246423432132688946"
"4182768467546703537516986049910576551282076245490090389328944075868"
"5084551339423045832369032229481658085593321233482747978262041447231"
"68738177180919299881250404026184124858368.000000") {
for (auto &d : doubles) {
using L = std::numeric_limits<double>;
double d2 = std::abs(d);
if (d2 == L::max() || d2 == L::min() || d2 == L::denorm_min()) {
d = 0;
}
}
}
for (const char *fmt : kFormats) { for (const char *fmt : kFormats) {
for (char f : {'f', 'F', // for (char f : {'f', 'F', //
'g', 'G', // 'g', 'G', //
'a', 'A', // 'a', 'A', //
'e', 'E'}) { 'e', 'E'}) {
std::string fmt_str = std::string(fmt) + f; std::string fmt_str = std::string(fmt) + f;
if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') {
// This particular test takes way too long with snprintf.
// Disable for the case we are not implementing natively.
continue;
}
for (double d : doubles) { for (double d : doubles) {
int i = -10; int i = -10;
FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)};
...@@ -479,24 +454,27 @@ TEST_F(FormatConvertTest, Float) { ...@@ -479,24 +454,27 @@ TEST_F(FormatConvertTest, Float) {
ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i), ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i),
FormatPack(format, absl::MakeSpan(args))) FormatPack(format, absl::MakeSpan(args)))
<< fmt_str << " " << StrPrint("%.18g", d) << " " << fmt_str << " " << StrPrint("%.18g", d) << " "
<< StrPrint("%a", d) << " " << StrPrint("%.1080f", d); << StrPrint("%.999f", d);
} }
} }
} }
} }
TEST_F(FormatConvertTest, LongDouble) { TEST_F(FormatConvertTest, LongDouble) {
#if _MSC_VER const char *const kFormats[] = {"%", "%.3", "%8.5", "%9",
// MSVC has a different rounding policy than us so we can't test our
// implementation against the native one there.
return;
#endif // _MSC_VER
const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000",
"%.60", "%+", "% ", "%-10"}; "%.60", "%+", "% ", "%-10"};
// This value is not representable in double, but it is in long double that
// uses the extended format.
// This is to verify that we are not truncating the value mistakenly through a
// double.
long double very_precise = 10000000000000000.25L;
std::vector<long double> doubles = { std::vector<long double> doubles = {
0.0, 0.0,
-0.0, -0.0,
very_precise,
1 / very_precise,
std::numeric_limits<long double>::max(), std::numeric_limits<long double>::max(),
-std::numeric_limits<long double>::max(), -std::numeric_limits<long double>::max(),
std::numeric_limits<long double>::min(), std::numeric_limits<long double>::min(),
...@@ -504,44 +482,22 @@ TEST_F(FormatConvertTest, LongDouble) { ...@@ -504,44 +482,22 @@ TEST_F(FormatConvertTest, LongDouble) {
std::numeric_limits<long double>::infinity(), std::numeric_limits<long double>::infinity(),
-std::numeric_limits<long double>::infinity()}; -std::numeric_limits<long double>::infinity()};
for (long double base : {1.L, 12.L, 123.L, 1234.L, 12345.L, 123456.L,
1234567.L, 12345678.L, 123456789.L, 1234567890.L,
12345678901.L, 123456789012.L, 1234567890123.L,
// This value is not representable in double, but it
// is in long double that uses the extended format.
// This is to verify that we are not truncating the
// value mistakenly through a double.
10000000000000000.25L}) {
for (int exp : {-1000, -500, 0, 500, 1000}) {
for (int sign : {1, -1}) {
doubles.push_back(sign * std::ldexp(base, exp));
doubles.push_back(sign / std::ldexp(base, exp));
}
}
}
for (const char *fmt : kFormats) { for (const char *fmt : kFormats) {
for (char f : {'f', 'F', // for (char f : {'f', 'F', //
'g', 'G', // 'g', 'G', //
'a', 'A', // 'a', 'A', //
'e', 'E'}) { 'e', 'E'}) {
std::string fmt_str = std::string(fmt) + 'L' + f; std::string fmt_str = std::string(fmt) + 'L' + f;
if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') {
// This particular test takes way too long with snprintf.
// Disable for the case we are not implementing natively.
continue;
}
for (auto d : doubles) { for (auto d : doubles) {
FormatArgImpl arg(d); FormatArgImpl arg(d);
UntypedFormatSpecImpl format(fmt_str); UntypedFormatSpecImpl format(fmt_str);
// We use ASSERT_EQ here because failures are usually correlated and a // We use ASSERT_EQ here because failures are usually correlated and a
// bug would print way too many failed expectations causing the test to // bug would print way too many failed expectations causing the test to
// time out. // time out.
ASSERT_EQ(StrPrint(fmt_str.c_str(), d), FormatPack(format, {&arg, 1})) ASSERT_EQ(StrPrint(fmt_str.c_str(), d),
FormatPack(format, {&arg, 1}))
<< fmt_str << " " << StrPrint("%.18Lg", d) << " " << fmt_str << " " << StrPrint("%.18Lg", d) << " "
<< StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d); << StrPrint("%.999Lf", d);
} }
} }
} }
......
...@@ -25,6 +25,34 @@ ...@@ -25,6 +25,34 @@
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
#include "absl/utility/utility.h" #include "absl/utility/utility.h"
// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
//
// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015.
// __cpp_inheriting_constructors is a predefined macro and a recommended way to
// check for this language feature, but GCC doesn't support it until 5.0 and
// Clang doesn't support it until 3.6.
// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template
// constructor. For example, the following code won't work on MSVC 2015 Update3:
// struct Base {
// int t;
// template <typename T>
// constexpr Base(T t_) : t(t_) {}
// };
// struct Foo : Base {
// using Base::Base;
// }
// constexpr Foo foo(0); // doesn't work on MSVC 2015
#if defined(__clang__)
#if __has_feature(cxx_inheriting_constructors)
#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
#endif
#elif (defined(__GNUC__) && \
(__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
(__cpp_inheriting_constructors >= 200802) || \
(defined(_MSC_VER) && _MSC_VER >= 1910)
#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
#endif
namespace absl { namespace absl {
// Forward declaration // Forward declaration
...@@ -108,7 +136,7 @@ template <typename T> ...@@ -108,7 +136,7 @@ template <typename T>
class optional_data_base : public optional_data_dtor_base<T> { class optional_data_base : public optional_data_dtor_base<T> {
protected: protected:
using base = optional_data_dtor_base<T>; using base = optional_data_dtor_base<T>;
#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS #ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
using base::base; using base::base;
#else #else
optional_data_base() = default; optional_data_base() = default;
...@@ -151,7 +179,7 @@ class optional_data; ...@@ -151,7 +179,7 @@ class optional_data;
template <typename T> template <typename T>
class optional_data<T, true> : public optional_data_base<T> { class optional_data<T, true> : public optional_data_base<T> {
protected: protected:
#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS #ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
using optional_data_base<T>::optional_data_base; using optional_data_base<T>::optional_data_base;
#else #else
optional_data() = default; optional_data() = default;
...@@ -165,7 +193,7 @@ class optional_data<T, true> : public optional_data_base<T> { ...@@ -165,7 +193,7 @@ class optional_data<T, true> : public optional_data_base<T> {
template <typename T> template <typename T>
class optional_data<T, false> : public optional_data_base<T> { class optional_data<T, false> : public optional_data_base<T> {
protected: protected:
#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS #ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
using optional_data_base<T>::optional_data_base; using optional_data_base<T>::optional_data_base;
#else #else
template <typename... Args> template <typename... Args>
...@@ -361,4 +389,6 @@ struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()( ...@@ -361,4 +389,6 @@ struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
} // namespace optional_internal } // namespace optional_internal
} // namespace absl } // namespace absl
#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
#endif // ABSL_TYPES_INTERNAL_OPTIONAL_H_ #endif // ABSL_TYPES_INTERNAL_OPTIONAL_H_
...@@ -64,34 +64,6 @@ using std::nullopt; ...@@ -64,34 +64,6 @@ using std::nullopt;
#include "absl/types/bad_optional_access.h" #include "absl/types/bad_optional_access.h"
#include "absl/types/internal/optional.h" #include "absl/types/internal/optional.h"
// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
//
// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015.
// __cpp_inheriting_constructors is a predefined macro and a recommended way to
// check for this language feature, but GCC doesn't support it until 5.0 and
// Clang doesn't support it until 3.6.
// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template
// constructor. For example, the following code won't work on MSVC 2015 Update3:
// struct Base {
// int t;
// template <typename T>
// constexpr Base(T t_) : t(t_) {}
// };
// struct Foo : Base {
// using Base::Base;
// }
// constexpr Foo foo(0); // doesn't work on MSVC 2015
#if defined(__clang__)
#if __has_feature(cxx_inheriting_constructors)
#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
#endif
#elif (defined(__GNUC__) && \
(__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
(__cpp_inheriting_constructors >= 200802) || \
(defined(_MSC_VER) && _MSC_VER >= 1910)
#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
#endif
namespace absl { namespace absl {
// nullopt_t // nullopt_t
...@@ -791,7 +763,6 @@ struct hash<absl::optional<T> > ...@@ -791,7 +763,6 @@ struct hash<absl::optional<T> >
} // namespace std } // namespace std
#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
#undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS #undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS
#endif // ABSL_HAVE_STD_OPTIONAL #endif // ABSL_HAVE_STD_OPTIONAL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment