diff options
-rw-r--r-- | absl/container/inlined_vector_benchmark.cc | 110 | ||||
-rw-r--r-- | absl/flags/internal/flag.h | 2 | ||||
-rw-r--r-- | absl/flags/marshalling.h | 9 | ||||
-rw-r--r-- | absl/time/internal/cctz/include/cctz/civil_time.h | 4 | ||||
-rw-r--r-- | absl/time/internal/cctz/src/civil_time_test.cc | 2 | ||||
-rw-r--r-- | absl/time/internal/cctz/src/time_zone_info.cc | 3 | ||||
-rw-r--r-- | absl/time/internal/cctz/src/time_zone_libc.cc | 95 | ||||
-rw-r--r-- | absl/time/internal/cctz/src/zone_info_source.cc | 18 | ||||
-rw-r--r-- | absl/types/internal/variant.h | 12 | ||||
-rw-r--r-- | absl/types/variant_test.cc | 5 |
10 files changed, 182 insertions, 78 deletions
diff --git a/absl/container/inlined_vector_benchmark.cc b/absl/container/inlined_vector_benchmark.cc index b57fc1de9e3b..a8368d418c53 100644 --- a/absl/container/inlined_vector_benchmark.cc +++ b/absl/container/inlined_vector_benchmark.cc @@ -379,6 +379,10 @@ constexpr size_t kLargeSize = kInlinedCapacity * 2; constexpr size_t kSmallSize = kInlinedCapacity / 2; constexpr size_t kBatchSize = 100; +#define ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_FunctionTemplate, T) \ + BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize); \ + BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize) + template <typename T> using InlVec = absl::InlinedVector<T, kInlinedCapacity>; @@ -420,29 +424,115 @@ void BatchedBenchmark(benchmark::State& state, PrepareVecFn prepare_vec, while (state.KeepRunningBatch(kBatchSize)) { // Prepare batch state.PauseTiming(); - for (auto& vec : vector_batch) { - prepare_vec(&vec); + for (size_t i = 0; i < kBatchSize; ++i) { + prepare_vec(vector_batch.data() + i, i); } benchmark::DoNotOptimize(vector_batch); state.ResumeTiming(); // Test batch - for (auto& vec : vector_batch) { - test_vec(&vec); + for (size_t i = 0; i < kBatchSize; ++i) { + test_vec(vector_batch.data() + i, i); } } } +template <typename T, size_t ToSize> +void BM_ConstructFromSize(benchmark::State& state) { + using VecT = InlVec<T>; + auto size = ToSize; + BatchedBenchmark<T>( + state, + /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); }, + /* test_vec = */ + [&](void* ptr, size_t) { + benchmark::DoNotOptimize(size); + ::new (ptr) VecT(size); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, NontrivialType); + +template <typename T, size_t ToSize> +void BM_ConstructFromSizeRef(benchmark::State& state) { + using VecT = InlVec<T>; + auto size = ToSize; + auto ref = T(); + BatchedBenchmark<T>( + state, + /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); }, + /* test_vec = */ + [&](void* ptr, size_t) { + benchmark::DoNotOptimize(size); + benchmark::DoNotOptimize(ref); + ::new (ptr) VecT(size, ref); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, NontrivialType); + +template <typename T, size_t ToSize> +void BM_ConstructFromRange(benchmark::State& state) { + using VecT = InlVec<T>; + std::array<T, ToSize> arr{}; + BatchedBenchmark<T>( + state, + /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); }, + /* test_vec = */ + [&](void* ptr, size_t) { + benchmark::DoNotOptimize(arr); + ::new (ptr) VecT(arr.begin(), arr.end()); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, NontrivialType); + +template <typename T, size_t ToSize> +void BM_ConstructFromCopy(benchmark::State& state) { + using VecT = InlVec<T>; + VecT other_vec(ToSize); + BatchedBenchmark<T>( + state, + /* prepare_vec = */ + [](InlVec<T>* vec, size_t) { vec->~VecT(); }, + /* test_vec = */ + [&](void* ptr, size_t) { + benchmark::DoNotOptimize(other_vec); + ::new (ptr) VecT(other_vec); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, NontrivialType); + +template <typename T, size_t ToSize> +void BM_ConstructFromMove(benchmark::State& state) { + using VecT = InlVec<T>; + std::array<VecT, kBatchSize> vector_batch{}; + BatchedBenchmark<T>( + state, + /* prepare_vec = */ + [&](InlVec<T>* vec, size_t i) { + vector_batch[i].clear(); + vector_batch[i].resize(ToSize); + vec->~VecT(); + }, + /* test_vec = */ + [&](void* ptr, size_t i) { + benchmark::DoNotOptimize(vector_batch[i]); + ::new (ptr) VecT(std::move(vector_batch[i])); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, NontrivialType); + template <typename T, size_t FromSize> void BM_Clear(benchmark::State& state) { BatchedBenchmark<T>( state, - /* prepare_vec = */ [](InlVec<T>* vec) { vec->resize(FromSize); }, - /* test_vec = */ [](InlVec<T>* vec) { vec->clear(); }); + /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); }, + /* test_vec = */ [](InlVec<T>* vec, size_t) { vec->clear(); }); } -BENCHMARK_TEMPLATE(BM_Clear, TrivialType, kLargeSize); -BENCHMARK_TEMPLATE(BM_Clear, TrivialType, kSmallSize); -BENCHMARK_TEMPLATE(BM_Clear, NontrivialType, kLargeSize); -BENCHMARK_TEMPLATE(BM_Clear, NontrivialType, kSmallSize); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, NontrivialType); } // namespace diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 6402866f2249..9b32f46735b6 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -56,7 +56,7 @@ class Flag { // forward declared types. // auto IsCopyConstructible(const T& v) -> decltype(T(v)); // auto HasAbslParseFlag(absl::string_view in, T* dst, std::string* err) - // -> decltype(AbslParseFlag(in, dst, GlobalStringADLGuard(err))); + // -> decltype(AbslParseFlag(in, dst, err)); // auto HasAbslUnparseFlag(const T& v) -> decltype(AbslUnparseFlag(v)); }; diff --git a/absl/flags/marshalling.h b/absl/flags/marshalling.h index 669cf452c4b0..7eb75cde7623 100644 --- a/absl/flags/marshalling.h +++ b/absl/flags/marshalling.h @@ -185,18 +185,11 @@ bool AbslParseFlag(absl::string_view, double*, std::string*); bool AbslParseFlag(absl::string_view, std::string*, std::string*); bool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*); -struct GlobalStringADLGuard { - explicit GlobalStringADLGuard(std::string* p) : ptr(p) {} - operator std::string*() { return ptr; } // NOLINT - std::string* ptr; -}; - template <typename T> bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) { // Comment on next line provides a good compiler error message if T // does not have AbslParseFlag(absl::string_view, T*, std::string*). - return AbslParseFlag( // Is T missing AbslParseFlag? - input, dst, GlobalStringADLGuard(err)); + return AbslParseFlag(input, dst, err); // Is T missing AbslParseFlag? } // Strings and std:: containers do not have the same overload resolution diff --git a/absl/time/internal/cctz/include/cctz/civil_time.h b/absl/time/internal/cctz/include/cctz/civil_time.h index f844182b1c90..aa578ee3648c 100644 --- a/absl/time/internal/cctz/include/cctz/civil_time.h +++ b/absl/time/internal/cctz/include/cctz/civil_time.h @@ -306,9 +306,9 @@ using detail::get_weekday; // // civil_day d = ... // // Gets the following Thursday if d is not already Thursday -// civil_day thurs1 = prev_weekday(d, weekday::thursday) + 7; +// civil_day thurs1 = next_weekday(d - 1, weekday::thursday); // // Gets the previous Thursday if d is not already Thursday -// civil_day thurs2 = next_weekday(d, weekday::thursday) - 7; +// civil_day thurs2 = prev_weekday(d + 1, weekday::thursday); // using detail::next_weekday; using detail::prev_weekday; diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc index dc7e5a1d35c6..b1f46f1284e0 100644 --- a/absl/time/internal/cctz/src/civil_time_test.cc +++ b/absl/time/internal/cctz/src/civil_time_test.cc @@ -1035,7 +1035,7 @@ TEST(CivilTime, LeapYears) { TEST(CivilTime, FirstThursdayInMonth) { const civil_day nov1(2014, 11, 1); - const civil_day thursday = prev_weekday(nov1, weekday::thursday) + 7; + const civil_day thursday = next_weekday(nov1 - 1, weekday::thursday); EXPECT_EQ("2014-11-06", Format(thursday)); // Bonus: Date of Thanksgiving in the United States diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index 50f7de54014f..184bd434c2d2 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc @@ -682,7 +682,6 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open( // Use of the "file:" prefix is intended for testing purposes only. if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5)); -#if defined(__ANDROID__) // See Android's libc/tzcode/bionic.cpp for additional information. for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata", "/system/usr/share/zoneinfo/tzdata"}) { @@ -717,7 +716,7 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open( } } } -#endif // __ANDROID__ + return nullptr; } diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 3ab1623cbd17..6095e764df0d 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -21,7 +21,6 @@ #include <chrono> #include <ctime> #include <limits> -#include <tuple> #include <utility> #include "absl/time/internal/cctz/include/cctz/civil_time.h" @@ -33,57 +32,75 @@ namespace cctz { namespace { -// .first is seconds east of UTC; .second is the time-zone abbreviation. -using OffsetAbbr = std::pair<int, const char*>; - -// Defines a function that can be called as follows: -// -// std::tm tm = ...; -// OffsetAbbr off_abbr = get_offset_abbr(tm); -// #if defined(_WIN32) || defined(_WIN64) // Uses the globals: '_timezone', '_dstbias' and '_tzname'. -OffsetAbbr get_offset_abbr(const std::tm& tm) { +auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) { const bool is_dst = tm.tm_isdst > 0; - const int off = _timezone + (is_dst ? _dstbias : 0); - const char* abbr = _tzname[is_dst]; - return {off, abbr}; + return _timezone + (is_dst ? _dstbias : 0); +} +auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return _tzname[is_dst]; } #elif defined(__sun) // Uses the globals: 'timezone', 'altzone' and 'tzname'. -OffsetAbbr get_offset_abbr(const std::tm& tm) { +auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) { const bool is_dst = tm.tm_isdst > 0; - const int off = is_dst ? altzone : timezone; - const char* abbr = tzname[is_dst]; - return {off, abbr}; + return is_dst ? altzone : timezone; +} +auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return tzname[is_dst]; } #elif defined(__native_client__) || defined(__myriad2__) || \ defined(__EMSCRIPTEN__) // Uses the globals: 'timezone' and 'tzname'. -OffsetAbbr get_offset_abbr(const std::tm& tm) { +auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) { + const bool is_dst = tm.tm_isdst > 0; + return _timezone + (is_dst ? 60 * 60 : 0); +} +auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { const bool is_dst = tm.tm_isdst > 0; - const int off = _timezone + (is_dst ? 60 * 60 : 0); - const char* abbr = tzname[is_dst]; - return {off, abbr}; + return tzname[is_dst]; +} +#else +// Adapt to different spellings of the struct std::tm extension fields. +#if defined(tm_gmtoff) +auto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) { + return tm.tm_gmtoff; +} +#elif defined(__tm_gmtoff) +auto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) { + return tm.__tm_gmtoff; +} +#else +template <typename T> +auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) { + return tm.tm_gmtoff; +} +template <typename T> +auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) { + return tm.__tm_gmtoff; +} +#endif // tm_gmtoff +#if defined(tm_zone) +auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { + return tm.tm_zone; +} +#elif defined(__tm_zone) +auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) { + return tm.__tm_zone; } #else -// -// Returns an OffsetAbbr using std::tm fields with various spellings. -// -#if !defined(tm_gmtoff) && !defined(tm_zone) template <typename T> -OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::tm_gmtoff) = nullptr, - decltype(&T::tm_zone) = nullptr) { - return {tm.tm_gmtoff, tm.tm_zone}; +auto tm_zone(const T& tm) -> decltype(tm.tm_zone) { + return tm.tm_zone; } -#endif // !defined(tm_gmtoff) && !defined(tm_zone) -#if !defined(__tm_gmtoff) && !defined(__tm_zone) template <typename T> -OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::__tm_gmtoff) = nullptr, - decltype(&T::__tm_zone) = nullptr) { - return {tm.__tm_gmtoff, tm.__tm_zone}; +auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) { + return tm.__tm_zone; } -#endif // !defined(__tm_gmtoff) && !defined(__tm_zone) +#endif // tm_zone #endif inline std::tm* gm_time(const std::time_t *timep, std::tm *result) { @@ -126,7 +143,7 @@ bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) { return false; } } - *off = get_offset_abbr(tm).first; + *off = static_cast<int>(tm_gmtoff(tm)); return true; } @@ -137,7 +154,7 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { while (lo + 1 != hi) { const std::time_t mid = lo + (hi - lo) / 2; if (std::tm* tmp = local_time(&mid, &tm)) { - if (get_offset_abbr(*tmp).first == offset) { + if (tm_gmtoff(*tmp) == offset) { hi = mid; } else { lo = mid; @@ -147,7 +164,7 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { // ignoring all failed conversions. Slow, but never really happens. while (++lo != hi) { if (std::tm* tmp = local_time(&lo, &tm)) { - if (get_offset_abbr(*tmp).first == offset) break; + if (tm_gmtoff(*tmp) == offset) break; } } return lo; @@ -193,8 +210,8 @@ time_zone::absolute_lookup TimeZoneLibC::BreakTime( const year_t year = tmp->tm_year + year_t{1900}; al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); - std::tie(al.offset, al.abbr) = get_offset_abbr(*tmp); - if (!local_) al.abbr = "UTC"; // as expected by cctz + al.offset = static_cast<int>(tm_gmtoff(*tmp)); + al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz al.is_dst = tmp->tm_isdst > 0; return al; } diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc index 132484628cd9..42f50c5e8fb4 100644 --- a/absl/time/internal/cctz/src/zone_info_source.cc +++ b/absl/time/internal/cctz/src/zone_info_source.cc @@ -46,7 +46,13 @@ std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory( // A "weak" definition for cctz_extension::zone_info_source_factory. // The user may override this with their own "strong" definition (see // zone_info_source.h). -#if defined(_MSC_VER) +#if !defined(__has_attribute) +#define __has_attribute(x) 0 +#endif +#if __has_attribute(weak) || defined(__GNUC__) +ZoneInfoSourceFactory zone_info_source_factory + __attribute__((weak)) = DefaultFactory; +#elif defined(_MSC_VER) && !defined(_LIBCPP_VERSION) extern ZoneInfoSourceFactory zone_info_source_factory; extern ZoneInfoSourceFactory default_factory; ZoneInfoSourceFactory default_factory = DefaultFactory; @@ -60,19 +66,11 @@ ZoneInfoSourceFactory default_factory = DefaultFactory; "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA") #else #error Unsupported MSVC platform -#endif -#else // _MSC_VER -#if !defined(__has_attribute) -#define __has_attribute(x) 0 -#endif -#if __has_attribute(weak) || defined(__GNUC__) -ZoneInfoSourceFactory zone_info_source_factory - __attribute__((weak)) = DefaultFactory; +#endif // _M_<PLATFORM> #else // Make it a "strong" definition if we have no other choice. ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory; #endif -#endif // _MSC_VER } // namespace cctz_extension } // namespace time_internal diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h index 5ca66e2902c6..85201b4ae1f9 100644 --- a/absl/types/internal/variant.h +++ b/absl/types/internal/variant.h @@ -837,8 +837,8 @@ struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> { // NOTE: const& and && are used instead of by-value due to lack of guaranteed // move elision of C++17. This may have other minor differences, but tests // pass. - static SizeT<I> Run(const H&); - static SizeT<I> Run(H&&); + static SizeT<I> Run(const H&, SizeT<I>); + static SizeT<I> Run(H&&, SizeT<I>); }; // The following metafunctions are used in constructor and assignment @@ -860,7 +860,8 @@ struct ConversionIsPossibleImpl : std::false_type {}; template <class Variant, class T> struct ConversionIsPossibleImpl< - Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>> + Variant, T, + void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> : std::true_type {}; template <class Variant, class T> @@ -868,8 +869,9 @@ struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {}; template <class Variant, class T> struct IndexOfConstructedType< - Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>> - : decltype(ImaginaryFun<Variant>::Run(std::declval<T>())) {}; + Variant, T, + void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>> + : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {}; template <std::size_t... Is> struct ContainsVariantNPos diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index b9c981181c50..d702482768a4 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -460,6 +460,11 @@ TYPED_TEST(VariantTypesTest, TestValueCtor) { EXPECT_EQ(value.value, mutable_valptr->value); } +TEST(VariantTest, AmbiguousValueConstructor) { + EXPECT_FALSE((std::is_convertible<int, absl::variant<int, int>>::value)); + EXPECT_FALSE((std::is_constructible<absl::variant<int, int>, int>::value)); +} + TEST(VariantTest, InPlaceType) { using Var = variant<int, std::string, NonCopyable, std::vector<int>>; |