From 38b704384cd2f17590b3922b97744be0b43622c9 Mon Sep 17 00:00:00 2001 From: nik7273 Date: Fri, 8 Mar 2019 10:27:53 -0500 Subject: Changed HTTP URLs to HTTPS where possible (#270) --- absl/base/internal/low_level_scheduling.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'absl/base/internal/low_level_scheduling.h') diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index e716f2b4..2a5a3847 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, -- cgit v1.2.3 From bf29470384a101b307873b26d358433138c857fc Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 19 Mar 2019 11:14:01 -0700 Subject: Export of internal Abseil changes. -- bdce7e57e9e886eff1114d0266781b443f7ec639 by Derek Mauro : Change {Get|Set}EnvironmentVariable to {Get|Set}EnvironmentVariableA for compatibility with /DUNICODE. PiperOrigin-RevId: 239229514 -- 2276ed502326a044a84060d34eb19d499e3a3be2 by Derek Mauro : Import of CCTZ from GitHub. PiperOrigin-RevId: 239228622 -- a462efb970ff43b08a362ef2343fb75ac1295a50 by Derek Mauro : Adding linking of CoreFoundation to CMakeLists in absl/time. Import https://github.com/abseil/abseil-cpp/pull/280. Fix #283 PiperOrigin-RevId: 239220785 -- fc23327b97f940c682aae1956cf7a1bf87f88c06 by Derek Mauro : Add hermetic test script that uses Docker to build with a very recent version of gcc (8.3.0 today) with libstdc++ and bazel. PiperOrigin-RevId: 239220448 -- 418c08a8f6a53e63b84e39473035774417ca3aa7 by Derek Mauro : Disable part of the variant exeception safety test on move assignment when using versions of libstd++ that contain a bug. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7 PiperOrigin-RevId: 239062455 -- 799722217aeda79679577843c91d5be62cbcbb42 by Matt Calabrese : Add internal-only IsSwappable traits corresponding to std::is_swappable and std::is_nothrow_swappable, which are used with the swap implementations of optional and variant. PiperOrigin-RevId: 239049448 -- aa46a036038a3de5c68ac5e5d3b4bf76f818d2ea by CJ Johnson : Make InlinedVectorStorage constructor explicit PiperOrigin-RevId: 239044361 -- 17949715b3aa21c794701f69f2154e91b6acabc3 by CJ Johnson : Add absl namesapce to internal/inlined_vector.h PiperOrigin-RevId: 239030789 -- 834628325953078cc08ed10d23bb8890e5bec897 by Derek Mauro : Add test script that uses Docker to build Abseil with gcc-4.8, libstdc++, and cmake. PiperOrigin-RevId: 239028433 -- 80fe24149ed73ed2ced995ad1e372fb060c60427 by CJ Johnson : Factors data members of InlinedVector into an impl type called InlinedVectorStorage so that (in future changes) the contents of a vector can be grouped together with a single pointer. PiperOrigin-RevId: 239021086 -- 585331436d5d4d79f845e45dcf79d918a0dc6169 by Derek Mauro : Add -Wno-missing-field-initializers to gcc compiler flags. gcc-4.x has spurious missing field initializer warnings. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 PiperOrigin-RevId: 239017217 -- 94602fe4e33ee3a552a7f2939c0f57a992f55075 by Abseil Team : Formatting fixes. PiperOrigin-RevId: 238983038 -- a1c1b63c08505574e0a8c491561840cecb2bb93e by Derek Mauro : Add hermetic test script that uses Docker to build with a very recent version of clang with libc++ and bazel. PiperOrigin-RevId: 238669118 -- e525f8d20bc2f79a0d69336b902f63858f3bff9d by Derek Mauro : Disable the test optionalTest.InPlaceTSFINAEBug until libc++ is updated. PiperOrigin-RevId: 238661703 -- f99a2a0b5ec424a059678f7f226600f137b4c74e by Derek Mauro : Correct the check for the FlatHashMap-Any test bug (list conditions instead of platforms when possible) PiperOrigin-RevId: 238653344 -- 777928035dbcbf39f361eb7d10dc3696822f692f by Jon Cohen : Add install rules for Abseil CMake. These are attempted to be limited to in-project installation. This serves two purposes -- first it's morally the same as using Abseil in-source, except you don't have to rebuild us every time. Second, the presence of an install rule makes life massively simpler for package manager maintainers. Currently this doesn't install absl tests or testonly libraries. This can be added in a follow-up patch. Fixes #38, Fixes #80, Closes #182 PiperOrigin-RevId: 238645836 -- ded1c6ce697c191b7a6ff14572b3e6d183117b2c by Derek Mauro : Add hermetic test script that uses Docker to build with a very recent version of clang with libstdc++ and bazel. PiperOrigin-RevId: 238517815 GitOrigin-RevId: bdce7e57e9e886eff1114d0266781b443f7ec639 Change-Id: I6f745869cb8ef63851891ccac05ae9a7dd241c4f --- CMake/AbseilHelpers.cmake | 39 +++-- CMake/abslConfig.cmake.in | 6 + CMakeLists.txt | 47 ++++++ absl/algorithm/container.h | 2 - absl/base/const_init.h | 1 - absl/base/dynamic_annotations.h | 1 + absl/base/internal/cycleclock.h | 1 - absl/base/internal/low_level_alloc.h | 1 + absl/base/internal/low_level_alloc_test.cc | 1 + absl/base/internal/low_level_scheduling.h | 3 +- absl/base/internal/raw_logging.h | 1 + absl/base/internal/scoped_set_env.cc | 6 +- absl/base/internal/scoped_set_env_test.cc | 4 +- absl/base/internal/thread_identity.h | 1 + absl/base/internal/unscaledcycleclock.h | 2 + absl/base/log_severity.h | 1 - absl/base/spinlock_test_common.cc | 2 + absl/base/thread_annotations.h | 2 +- absl/compiler_config_setting.bzl | 1 - absl/container/BUILD.bazel | 10 ++ absl/container/CMakeLists.txt | 12 ++ absl/container/fixed_array.h | 1 + absl/container/flat_hash_map_test.cc | 7 +- absl/container/inlined_vector.h | 180 +++++++-------------- absl/container/internal/hashtablez_sampler.h | 1 - absl/container/internal/inlined_vector.h | 130 +++++++++++++++ absl/container/internal/raw_hash_set_test.cc | 2 + absl/copts/GENERATED_AbseilCopts.cmake | 1 + absl/copts/GENERATED_copts.bzl | 1 + absl/copts/copts.py | 5 + absl/debugging/internal/address_is_readable.h | 1 - absl/debugging/internal/demangle_test.cc | 1 + absl/debugging/internal/stacktrace_x86-inl.inc | 1 + absl/debugging/leak_check.cc | 1 + absl/debugging/stacktrace.cc | 1 + absl/hash/hash.h | 1 + absl/hash/hash_test.cc | 1 + absl/hash/internal/city.h | 1 - absl/meta/type_traits.h | 61 +++++++ absl/meta/type_traits_test.cc | 81 ++++++++++ absl/numeric/int128.h | 1 - absl/strings/BUILD.bazel | 1 - absl/strings/escaping.h | 2 - absl/strings/internal/str_format/arg.h | 2 + absl/strings/internal/str_format/convert_test.cc | 1 + absl/strings/internal/str_format/extension.h | 1 - absl/strings/internal/str_format/extension_test.cc | 1 + absl/strings/internal/str_format/output_test.cc | 1 - absl/strings/internal/utf8.h | 1 - absl/strings/str_cat.h | 1 - absl/strings/str_format.h | 1 + absl/strings/str_split.h | 1 - absl/strings/string_view.h | 2 +- absl/strings/substitute.h | 1 - .../internal/create_thread_identity.h | 1 + absl/synchronization/internal/kernel_timeout.h | 2 + absl/synchronization/internal/per_thread_sem.cc | 1 + absl/synchronization/internal/per_thread_sem.h | 1 + absl/synchronization/internal/waiter.cc | 2 + absl/synchronization/mutex.cc | 1 + absl/synchronization/mutex.h | 4 + absl/synchronization/mutex_test.cc | 6 +- absl/synchronization/notification.h | 1 + absl/time/civil_time.h | 1 - absl/time/duration.cc | 1 + absl/time/internal/cctz/src/time_zone_lookup.cc | 2 +- absl/time/time.cc | 1 + absl/time/time.h | 3 +- absl/types/any_exception_safety_test.cc | 1 + absl/types/internal/variant.h | 5 +- absl/types/optional.h | 19 +-- absl/types/optional_test.cc | 2 + absl/types/variant.h | 17 +- absl/types/variant_exception_safety_test.cc | 9 ++ absl/types/variant_test.cc | 1 + absl/utility/utility.h | 1 - ci/linux_clang-latest_libcxx_bazel.sh | 62 +++++++ ci/linux_clang-latest_libstdcxx_bazel.sh | 61 +++++++ ci/linux_gcc-4.8_libstdcxx_cmake.sh | 61 +++++++ ci/linux_gcc-latest_libstdcxx_bazel.sh | 59 +++++++ 80 files changed, 770 insertions(+), 194 deletions(-) create mode 100644 CMake/abslConfig.cmake.in create mode 100644 absl/container/internal/inlined_vector.h create mode 100755 ci/linux_clang-latest_libcxx_bazel.sh create mode 100755 ci/linux_clang-latest_libstdcxx_bazel.sh create mode 100755 ci/linux_gcc-4.8_libstdcxx_cmake.sh create mode 100755 ci/linux_gcc-latest_libstdcxx_bazel.sh (limited to 'absl/base/internal/low_level_scheduling.h') diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index 8fdd510f..6d26169d 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -16,6 +16,7 @@ include(CMakeParseArguments) include(AbseilConfigureCopts) +include(GNUInstallDirs) # The IDE folder for Abseil that will be used if Abseil is included in a CMake # project that sets @@ -59,20 +60,17 @@ set(ABSL_IDE_FOLDER Abseil) # "b.cc" # DEPS # absl_internal_awesome # not "awesome"! +# PUBLIC # ) # -# If PUBLIC is set, absl_cc_library will instead create a target named -# absl_${NAME} and still an alias absl::${NAME}. -# # absl_cc_library( # NAME # main_lib # ... -# PUBLIC +# DEPS +# absl::fantastic_lib # since fantastic_lib is public # ) # -# User can then use the library as absl::main_lib (although absl_main_lib is defined too). -# # TODO: Implement "ALWAYSLINK" function(absl_cc_library) cmake_parse_arguments(ABSL_CC_LIB @@ -83,7 +81,7 @@ function(absl_cc_library) ) if (NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS) - set(_NAME "absl_${ABSL_CC_LIB_NAME}") + set(_NAME "${ABSL_CC_LIB_NAME}") # Check if this is a header-only library # Note that as of February 2019, many popular OS's (for example, Ubuntu @@ -105,7 +103,10 @@ function(absl_cc_library) add_library(${_NAME} STATIC "") target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) target_include_directories(${_NAME} - PUBLIC ${ABSL_COMMON_INCLUDE_DIRS}) + PUBLIC + $ + $ + ) target_compile_options(${_NAME} PRIVATE ${ABSL_CC_LIB_COPTS}) target_link_libraries(${_NAME} @@ -126,17 +127,37 @@ function(absl_cc_library) # INTERFACE libraries can't have the CXX_STANDARD property set set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD}) set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) + + # When being installed, we lose the absl_ prefix. We want to put it back + # to have properly named lib files. This is a no-op when we are not being + # installed. + set_target_properties(${_NAME} PROPERTIES + OUTPUT_NAME "absl_${_NAME}" + ) else() # Generating header-only library add_library(${_NAME} INTERFACE) target_include_directories(${_NAME} - INTERFACE ${ABSL_COMMON_INCLUDE_DIRS}) + INTERFACE + $ + $ + ) target_link_libraries(${_NAME} INTERFACE ${ABSL_CC_LIB_DEPS} ${ABSL_CC_LIB_LINKOPTS} ) target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES}) endif() + # TODO currently we don't install googletest alongside abseil sources, so + # installed abseil can't be tested. + if (NOT ABSL_CC_LIB_TESTONLY) + install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + endif() + add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME}) endif() endfunction() diff --git a/CMake/abslConfig.cmake.in b/CMake/abslConfig.cmake.in new file mode 100644 index 00000000..bf8c4f6a --- /dev/null +++ b/CMake/abslConfig.cmake.in @@ -0,0 +1,6 @@ +## absl CMake configuration file. Note that there is no corresponding +# abslConfigVersion.cmake since non-LTS Abseil isn't versioned. + +@PACKAGE_INIT@ + +include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 571e48c5..e3bb8d05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,14 +26,26 @@ if (POLICY CMP0025) cmake_policy(SET CMP0025 NEW) endif() +# if command can use IN_LIST +cmake_policy(SET CMP0057 NEW) + project(absl) +# when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp)) +# in the source tree of a project that uses it, install rules are disabled. +if(NOT "^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$") + set(ABSL_ENABLE_INSTALL FALSE) +else() + set(ABSL_ENABLE_INSTALL TRUE) +endif() + list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CMake ${CMAKE_CURRENT_LIST_DIR}/absl/copts ) include(GNUInstallDirs) +include(CMakePackageConfigHelpers) include(AbseilHelpers) @@ -73,11 +85,23 @@ if(${ABSL_RUN_TESTS}) enable_testing() endif() +# We don't support system-wide installation +list(APPEND SYSTEM_INSTALL_DIRS "/usr/local" "/usr" "/opt/" "/opt/local" "c:/Program Files/${PROJECT_NAME}") +if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX IN_LIST SYSTEM_INSTALL_DIRS) + message(WARNING "\ +The default and system-level install directories are unsupported except in LTS \ +releases of Abseil. Please set CMAKE_INSTALL_PREFIX to install Abseil in your \ +source or build tree directly.\ + ") +endif() + ## check targets if(BUILD_TESTING) if(${ABSL_USE_GOOGLETEST_HEAD}) include(CMake/DownloadGTest.cmake) + set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src) + set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build) endif() check_target(gtest) @@ -93,3 +117,26 @@ if(BUILD_TESTING) endif() add_subdirectory(absl) + +# install as a subdirectory only +install(EXPORT ${PROJECT_NAME}Targets + NAMESPACE absl:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake" +) + +configure_package_config_file( + CMake/abslConfig.cmake.in + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake" +) + +install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake +) + +install(DIRECTORY absl + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING + PATTERN "*.inc" + PATTERN "*.h" +) diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index 7348d632..752e47b2 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -36,7 +36,6 @@ // For template parameter and variable naming, `C` indicates the container type // to which the function is applied, `Pred` indicates the predicate object type // to be used by the function and `T` indicates the applicable element type. -// #ifndef ABSL_ALGORITHM_CONTAINER_H_ #define ABSL_ALGORITHM_CONTAINER_H_ @@ -648,7 +647,6 @@ container_algorithm_internal::ContainerIter c_generate_n(C& c, Size n, // and `unique()` are omitted, because it's not clear whether or not such // functions should call erase on their supplied sequences afterwards. Either // behavior would be surprising for a different set of users. -// // c_remove_copy() // diff --git a/absl/base/const_init.h b/absl/base/const_init.h index 1b2b8c2b..17858a77 100644 --- a/absl/base/const_init.h +++ b/absl/base/const_init.h @@ -60,7 +60,6 @@ // // The absl::kConstInit tag should only be used to define objects with static // or thread_local storage duration. -// namespace absl { diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h index cdeb18c2..ac33df9e 100644 --- a/absl/base/dynamic_annotations.h +++ b/absl/base/dynamic_annotations.h @@ -139,6 +139,7 @@ #define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */ #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */ #endif /* DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */ + /* TODO(delesley) -- Replace __CLANG_SUPPORT_DYN_ANNOTATION__ with the appropriate feature ID. */ #if defined(__clang__) && (!defined(SWIG)) \ diff --git a/absl/base/internal/cycleclock.h b/absl/base/internal/cycleclock.h index 7874db71..794564e1 100644 --- a/absl/base/internal/cycleclock.h +++ b/absl/base/internal/cycleclock.h @@ -28,7 +28,6 @@ // not necessarily "CPU cycles" and code should not rely on that behavior, even // if experimentally observed. // -// // An arbitrary offset may have been added to the counter at power on. // // On some platforms, the rate and offset of the counter may differ diff --git a/absl/base/internal/low_level_alloc.h b/absl/base/internal/low_level_alloc.h index f83c7bc8..b35673de 100644 --- a/absl/base/internal/low_level_alloc.h +++ b/absl/base/internal/low_level_alloc.h @@ -119,4 +119,5 @@ class LowLevelAlloc { } // namespace base_internal } // namespace absl + #endif // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_ diff --git a/absl/base/internal/low_level_alloc_test.cc b/absl/base/internal/low_level_alloc_test.cc index d2d31820..34a080cb 100644 --- a/absl/base/internal/low_level_alloc_test.cc +++ b/absl/base/internal/low_level_alloc_test.cc @@ -137,6 +137,7 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) { TEST_ASSERT(LowLevelAlloc::DeleteArena(arena)); } } + // LowLevelAlloc is designed to be safe to call before main(). static struct BeforeMain { BeforeMain() { diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 2a5a3847..0fcc8d3b 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -86,6 +86,7 @@ class SchedulingGuard { //------------------------------------------------------------------------------ // End of public interfaces. //------------------------------------------------------------------------------ + inline bool SchedulingGuard::ReschedulingIsAllowed() { return false; } @@ -98,7 +99,7 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) { return; } - } // namespace base_internal } // namespace absl + #endif // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h index 4cbbbe59..6a4c0936 100644 --- a/absl/base/internal/raw_logging.h +++ b/absl/base/internal/raw_logging.h @@ -38,6 +38,7 @@ // ABSL_RAW_LOG(ERROR, "Failed foo with %i: %s", status, error); // This will print an almost standard log line like this to stderr only: // E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file + #define ABSL_RAW_LOG(severity, ...) \ do { \ constexpr const char* absl_raw_logging_internal_basename = \ diff --git a/absl/base/internal/scoped_set_env.cc b/absl/base/internal/scoped_set_env.cc index 9b164124..3ac3f68d 100644 --- a/absl/base/internal/scoped_set_env.cc +++ b/absl/base/internal/scoped_set_env.cc @@ -33,7 +33,7 @@ const int kMaxEnvVarValueSize = 1024; void SetEnvVar(const char* name, const char* value) { #ifdef _WIN32 - SetEnvironmentVariable(name, value); + SetEnvironmentVariableA(name, value); #else if (value == nullptr) { ::unsetenv(name); @@ -49,7 +49,7 @@ ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value) : var_name_(var_name), was_unset_(false) { #ifdef _WIN32 char buf[kMaxEnvVarValueSize]; - auto get_res = GetEnvironmentVariable(var_name_.c_str(), buf, sizeof(buf)); + auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf)); ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size"); if (get_res == 0) { @@ -58,7 +58,7 @@ ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value) old_value_.assign(buf, get_res); } - SetEnvironmentVariable(var_name_.c_str(), new_value); + SetEnvironmentVariableA(var_name_.c_str(), new_value); #else const char* val = ::getenv(var_name_.c_str()); if (val == nullptr) { diff --git a/absl/base/internal/scoped_set_env_test.cc b/absl/base/internal/scoped_set_env_test.cc index 4bd68c48..5cbad246 100644 --- a/absl/base/internal/scoped_set_env_test.cc +++ b/absl/base/internal/scoped_set_env_test.cc @@ -26,8 +26,8 @@ using absl::base_internal::ScopedSetEnv; std::string GetEnvVar(const char* name) { #ifdef _WIN32 char buf[1024]; - auto get_res = GetEnvironmentVariable(name, buf, sizeof(buf)); - if (get_res == sizeof(buf)) { + auto get_res = GetEnvironmentVariableA(name, buf, sizeof(buf)); + if (get_res >= sizeof(buf)) { return "TOO_BIG"; } diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h index dde3e010..b34674a6 100644 --- a/absl/base/internal/thread_identity.h +++ b/absl/base/internal/thread_identity.h @@ -237,4 +237,5 @@ inline ThreadIdentity* CurrentThreadIdentityIfPresent() { } // namespace base_internal } // namespace absl + #endif // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_ diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h index d5e186a9..58950cc2 100644 --- a/absl/base/internal/unscaledcycleclock.h +++ b/absl/base/internal/unscaledcycleclock.h @@ -83,6 +83,7 @@ defined(_M_IX86) || defined(_M_X64)) #define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY #endif + namespace absl { namespace time_internal { class UnscaledCycleClockWrapperForGetCurrentTime; @@ -114,6 +115,7 @@ class UnscaledCycleClock { } // namespace base_internal } // namespace absl + #endif // ABSL_USE_UNSCALED_CYCLECLOCK #endif // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_ diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h index 4b9833eb..b19a7ffa 100644 --- a/absl/base/log_severity.h +++ b/absl/base/log_severity.h @@ -11,7 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// #ifndef ABSL_BASE_INTERNAL_LOG_SEVERITY_H_ #define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_ diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc index b32cea29..e62b2eae 100644 --- a/absl/base/spinlock_test_common.cc +++ b/absl/base/spinlock_test_common.cc @@ -54,6 +54,7 @@ namespace { static constexpr int kArrayLength = 10; static uint32_t values[kArrayLength]; + static SpinLock static_spinlock(base_internal::kLinkerInitialized); static SpinLock static_cooperative_spinlock( base_internal::kLinkerInitialized, @@ -189,6 +190,7 @@ TEST(SpinLock, WaitCyclesEncoding) { SpinLockTest::DecodeWaitCycles(before_max_value); EXPECT_GT(expected_max_value_decoded, before_max_value_decoded); } + TEST(SpinLockWithThreads, StaticSpinLock) { ThreadedTest(&static_spinlock); } diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h index a8162d41..0b2c306c 100644 --- a/absl/base/thread_annotations.h +++ b/absl/base/thread_annotations.h @@ -21,7 +21,6 @@ // code. The annotations can also help program analysis tools to identify // potential thread safety issues. // -// // These annotations are implemented using compiler attributes. Using the macros // defined here instead of raw attributes allow for portability and future // compatibility. @@ -34,6 +33,7 @@ #ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_ #define ABSL_BASE_THREAD_ANNOTATIONS_H_ + #if defined(__clang__) #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) #else diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl index e03f94ec..66962294 100644 --- a/absl/compiler_config_setting.bzl +++ b/absl/compiler_config_setting.bzl @@ -12,7 +12,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# """Creates config_setting that allows selecting based on 'compiler' value.""" diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index b6592ca5..cd914baf 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -111,11 +111,21 @@ cc_test( ], ) +cc_library( + name = "inlined_vector_internal", + hdrs = ["internal/inlined_vector.h"], + copts = ABSL_DEFAULT_COPTS, + deps = [ + "//absl/meta:type_traits", + ], +) + cc_library( name = "inlined_vector", hdrs = ["inlined_vector.h"], copts = ABSL_DEFAULT_COPTS, deps = [ + ":inlined_vector_internal", "//absl/algorithm", "//absl/base:core_headers", "//absl/base:throw_delegate", diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index 76542be1..292fea2a 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -107,6 +107,18 @@ absl_cc_test( gmock_main ) +absl_cc_library( + NAME + inlined_vector_internal + HDRS + "internal/inlined_vector.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::type_traits + PUBLIC +) + absl_cc_library( NAME inlined_vector diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index 0161d0a9..2a8240ae 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h @@ -515,4 +515,5 @@ void FixedArray::NonEmptyInlinedStorage::AnnotateDestruct( static_cast(n); // Mark used when not in asan mode } } // namespace absl + #endif // ABSL_CONTAINER_FIXED_ARRAY_H_ diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc index bae5c15d..ebcb560f 100644 --- a/absl/container/flat_hash_map_test.cc +++ b/absl/container/flat_hash_map_test.cc @@ -206,7 +206,9 @@ TEST(FlatHashMap, MergeExtractInsert) { m.insert(std::move(node)); EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9))); } -#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__) + +#if (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) && \ + !defined(__EMSCRIPTEN__) TEST(FlatHashMap, Any) { absl::flat_hash_map m; m.emplace(1, 7); @@ -237,7 +239,8 @@ TEST(FlatHashMap, Any) { ASSERT_NE(it2, m2.end()); EXPECT_EQ(7, it2->second); } -#endif // __ANDROID__ +#endif // (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) && + // !defined(__EMSCRIPTEN__) } // namespace } // namespace container_internal diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index 80929e36..68308750 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -1,4 +1,4 @@ -// Copyright 2018 The Abseil Authors. +// Copyright 2019 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -50,6 +50,7 @@ #include "absl/base/internal/throw_delegate.h" #include "absl/base/optimization.h" #include "absl/base/port.h" +#include "absl/container/internal/inlined_vector.h" #include "absl/memory/memory.h" namespace absl { @@ -65,10 +66,10 @@ namespace absl { // designed to cover the same API footprint as covered by `std::vector`. template > class InlinedVector { - static_assert(N > 0, "InlinedVector requires inline capacity greater than 0"); - constexpr static typename A::size_type GetInlinedCapacity() { - return static_cast(N); - } + using Storage = inlined_vector_internal::InlinedVectorStorage; + using Tag = typename Storage::Tag; + using AllocatorAndTag = typename Storage::AllocatorAndTag; + using Allocation = typename Storage::Allocation; template using IsAtLeastForwardIterator = std::is_convertible< @@ -83,21 +84,21 @@ class InlinedVector { using DisableIfAtLeastForwardIterator = absl::enable_if_t::value>; - using rvalue_reference = typename A::value_type&&; + using rvalue_reference = typename Storage::rvalue_reference; public: - using allocator_type = A; - using value_type = typename allocator_type::value_type; - using pointer = typename allocator_type::pointer; - using const_pointer = typename allocator_type::const_pointer; - using reference = typename allocator_type::reference; - using const_reference = typename allocator_type::const_reference; - using size_type = typename allocator_type::size_type; - using difference_type = typename allocator_type::difference_type; - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; + using allocator_type = typename Storage::allocator_type; + using value_type = typename Storage::value_type; + using pointer = typename Storage::pointer; + using const_pointer = typename Storage::const_pointer; + using reference = typename Storage::reference; + using const_reference = typename Storage::const_reference; + using size_type = typename Storage::size_type; + using difference_type = typename Storage::difference_type; + using iterator = typename Storage::iterator; + using const_iterator = typename Storage::const_iterator; + using reverse_iterator = typename Storage::reverse_iterator; + using const_reverse_iterator = typename Storage::const_reverse_iterator; // --------------------------------------------------------------------------- // InlinedVector Constructors and Destructor @@ -105,30 +106,30 @@ class InlinedVector { // Creates an empty inlined vector with a default initialized allocator. InlinedVector() noexcept(noexcept(allocator_type())) - : allocator_and_tag_(allocator_type()) {} + : storage_(allocator_type()) {} // Creates an empty inlined vector with a specified allocator. explicit InlinedVector(const allocator_type& alloc) noexcept - : allocator_and_tag_(alloc) {} + : storage_(alloc) {} // Creates an inlined vector with `n` copies of `value_type()`. explicit InlinedVector(size_type n, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { InitAssign(n); } // Creates an inlined vector with `n` copies of `v`. InlinedVector(size_type n, const_reference v, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { InitAssign(n, v); } // Creates an inlined vector of copies of the values in `list`. InlinedVector(std::initializer_list list, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { AppendForwardRange(list.begin(), list.end()); } @@ -142,7 +143,7 @@ class InlinedVector { EnableIfAtLeastForwardIterator* = nullptr> InlinedVector(ForwardIterator first, ForwardIterator last, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { AppendForwardRange(first, last); } @@ -152,7 +153,7 @@ class InlinedVector { DisableIfAtLeastForwardIterator* = nullptr> InlinedVector(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { std::copy(first, last, std::back_inserter(*this)); } @@ -162,7 +163,7 @@ class InlinedVector { // Creates a copy of an `other` inlined vector using a specified allocator. InlinedVector(const InlinedVector& other, const allocator_type& alloc) - : allocator_and_tag_(alloc) { + : storage_(alloc) { reserve(other.size()); if (allocated()) { UninitializedCopy(other.begin(), other.end(), allocated_space()); @@ -191,7 +192,7 @@ class InlinedVector { InlinedVector(InlinedVector&& other) noexcept( absl::allocator_is_nothrow::value || std::is_nothrow_move_constructible::value) - : allocator_and_tag_(other.allocator()) { + : storage_(other.allocator()) { if (other.allocated()) { // We can just steal the underlying buffer from the source. // That leaves the source empty, so we clear its size. @@ -222,7 +223,7 @@ class InlinedVector { // ownership of `other`'s allocated memory. InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept( absl::allocator_is_nothrow::value) - : allocator_and_tag_(alloc) { + : storage_(alloc) { if (other.allocated()) { if (alloc == other.allocator()) { // We can just steal the allocation from the source. @@ -282,7 +283,8 @@ class InlinedVector { // will no longer be inlined and `capacity()` will equal its capacity on the // allocated heap. size_type capacity() const noexcept { - return allocated() ? allocation().capacity() : GetInlinedCapacity(); + return allocated() ? allocation().capacity() + : Storage::GetInlinedCapacity(); } // `InlinedVector::data()` @@ -800,19 +802,19 @@ class InlinedVector { // `InlinedVector::shrink_to_fit()` // // Reduces memory usage by freeing unused memory. After this call, calls to - // `capacity()` will be equal to `(std::max)(GetInlinedCapacity(), size())`. + // `capacity()` will be equal to `max(Storage::GetInlinedCapacity(), size())`. // - // If `size() <= GetInlinedCapacity()` and the elements are currently stored - // on the heap, they will be moved to the inlined storage and the heap memory - // will be deallocated. + // If `size() <= Storage::GetInlinedCapacity()` and the elements are currently + // stored on the heap, they will be moved to the inlined storage and the heap + // memory will be deallocated. // - // If `size() > GetInlinedCapacity()` and `size() < capacity()` the elements - // will be moved to a smaller heap allocation. + // If `size() > Storage::GetInlinedCapacity()` and `size() < capacity()` the + // elements will be moved to a smaller heap allocation. void shrink_to_fit() { const auto s = size(); if (ABSL_PREDICT_FALSE(!allocated() || s == capacity())) return; - if (s <= GetInlinedCapacity()) { + if (s <= Storage::GetInlinedCapacity()) { // Move the elements to the inlined storage. // We have to do this using a temporary, because `inlined_storage` and // `allocation_storage` are in a union field. @@ -845,88 +847,33 @@ class InlinedVector { template friend auto AbslHashValue(H h, const InlinedVector& v) -> H; - // Holds whether the vector is allocated or not in the lowest bit and the size - // in the high bits: - // `size_ = (size << 1) | is_allocated;` - class Tag { - public: - Tag() : size_(0) {} - size_type size() const { return size_ / 2; } - void add_size(size_type n) { size_ += n * 2; } - void set_inline_size(size_type n) { size_ = n * 2; } - void set_allocated_size(size_type n) { size_ = (n * 2) + 1; } - bool allocated() const { return size_ % 2; } - - private: - size_type size_; - }; - - // Derives from `allocator_type` to use the empty base class optimization. - // If the `allocator_type` is stateless, we can store our instance for free. - class AllocatorAndTag : private allocator_type { - public: - explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {} - - Tag& tag() { return tag_; } - const Tag& tag() const { return tag_; } - - allocator_type& allocator() { return *this; } - const allocator_type& allocator() const { return *this; } - - private: - Tag tag_; - }; - - class Allocation { - public: - Allocation(allocator_type& a, size_type capacity) - : capacity_(capacity), buffer_(Create(a, capacity)) {} - - void Dealloc(allocator_type& a) { - std::allocator_traits::deallocate(a, buffer_, capacity_); - } - - size_type capacity() const { return capacity_; } - - const_pointer buffer() const { return buffer_; } - - pointer buffer() { return buffer_; } + const Tag& tag() const { return storage_.allocator_and_tag_.tag(); } - private: - static pointer Create(allocator_type& a, size_type n) { - return std::allocator_traits::allocate(a, n); - } - - size_type capacity_; - pointer buffer_; - }; - - const Tag& tag() const { return allocator_and_tag_.tag(); } - - Tag& tag() { return allocator_and_tag_.tag(); } + Tag& tag() { return storage_.allocator_and_tag_.tag(); } Allocation& allocation() { - return reinterpret_cast(rep_.allocation_storage.allocation); + return reinterpret_cast( + storage_.rep_.allocation_storage.allocation); } const Allocation& allocation() const { return reinterpret_cast( - rep_.allocation_storage.allocation); + storage_.rep_.allocation_storage.allocation); } void init_allocation(const Allocation& allocation) { - new (&rep_.allocation_storage.allocation) Allocation(allocation); + new (&storage_.rep_.allocation_storage.allocation) Allocation(allocation); } // TODO(absl-team): investigate whether the reinterpret_cast is appropriate. pointer inlined_space() { return reinterpret_cast( - std::addressof(rep_.inlined_storage.inlined[0])); + std::addressof(storage_.rep_.inlined_storage.inlined[0])); } const_pointer inlined_space() const { return reinterpret_cast( - std::addressof(rep_.inlined_storage.inlined[0])); + std::addressof(storage_.rep_.inlined_storage.inlined[0])); } pointer allocated_space() { return allocation().buffer(); } @@ -934,10 +881,12 @@ class InlinedVector { const_pointer allocated_space() const { return allocation().buffer(); } const allocator_type& allocator() const { - return allocator_and_tag_.allocator(); + return storage_.allocator_and_tag_.allocator(); } - allocator_type& allocator() { return allocator_and_tag_.allocator(); } + allocator_type& allocator() { + return storage_.allocator_and_tag_.allocator(); + } bool allocated() const { return tag().allocated(); } @@ -994,7 +943,7 @@ class InlinedVector { const size_type s = size(); assert(s <= capacity()); - size_type target = (std::max)(GetInlinedCapacity(), s + delta); + size_type target = (std::max)(Storage::GetInlinedCapacity(), s + delta); // Compute new capacity by repeatedly doubling current capacity // TODO(psrc): Check and avoid overflow? @@ -1097,7 +1046,7 @@ class InlinedVector { } void InitAssign(size_type n) { - if (n > GetInlinedCapacity()) { + if (n > Storage::GetInlinedCapacity()) { Allocation new_allocation(allocator(), n); init_allocation(new_allocation); UninitializedFill(allocated_space(), allocated_space() + n); @@ -1109,7 +1058,7 @@ class InlinedVector { } void InitAssign(size_type n, const_reference v) { - if (n > GetInlinedCapacity()) { + if (n > Storage::GetInlinedCapacity()) { Allocation new_allocation(allocator(), n); init_allocation(new_allocation); UninitializedFill(allocated_space(), allocated_space() + n, v); @@ -1267,28 +1216,7 @@ class InlinedVector { assert(a->size() == b_size); } - // Stores either the inlined or allocated representation - union Rep { - using ValueTypeBuffer = - absl::aligned_storage_t; - using AllocationBuffer = - absl::aligned_storage_t; - - // Structs wrap the buffers to perform indirection that solves a bizarre - // compilation error on Visual Studio (all known versions). - struct InlinedRep { - ValueTypeBuffer inlined[N]; - }; - struct AllocatedRep { - AllocationBuffer allocation; - }; - - InlinedRep inlined_storage; - AllocatedRep allocation_storage; - }; - - AllocatorAndTag allocator_and_tag_; - Rep rep_; + Storage storage_; }; // ----------------------------------------------------------------------------- diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h index aff8d15f..a308e788 100644 --- a/absl/container/internal/hashtablez_sampler.h +++ b/absl/container/internal/hashtablez_sampler.h @@ -34,7 +34,6 @@ // are using a table in an unusual circumstance where allocation or calling a // linux syscall is unacceptable, this could interfere. // -// // This utility is internal-only. Use at your own risk. #ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_ diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h new file mode 100644 index 00000000..30850609 --- /dev/null +++ b/absl/container/internal/inlined_vector.h @@ -0,0 +1,130 @@ +// Copyright 2019 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ +#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ + +#include +#include +#include + +#include "absl/meta/type_traits.h" + +namespace absl { +namespace inlined_vector_internal { + +template +class InlinedVectorStorage { + static_assert( + N > 0, "InlinedVector cannot be instantiated with `0` inline elements."); + + public: + using allocator_type = A; + using value_type = typename allocator_type::value_type; + using pointer = typename allocator_type::pointer; + using const_pointer = typename allocator_type::const_pointer; + using reference = typename allocator_type::reference; + using const_reference = typename allocator_type::const_reference; + using rvalue_reference = typename allocator_type::value_type&&; + using size_type = typename allocator_type::size_type; + using difference_type = typename allocator_type::difference_type; + using iterator = pointer; + using const_iterator = const_pointer; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + constexpr static size_type GetInlinedCapacity() { + return static_cast(N); + } + + explicit InlinedVectorStorage(const allocator_type& a) + : allocator_and_tag_(a) {} + + // TODO(johnsoncj): Make the below types and members private after migration + + // Holds whether the vector is allocated or not in the lowest bit and the size + // in the high bits: + // `size_ = (size << 1) | is_allocated;` + class Tag { + size_type size_; + + public: + Tag() : size_(0) {} + size_type size() const { return size_ / 2; } + void add_size(size_type n) { size_ += n * 2; } + void set_inline_size(size_type n) { size_ = n * 2; } + void set_allocated_size(size_type n) { size_ = (n * 2) + 1; } + bool allocated() const { return size_ % 2; } + }; + + // Derives from `allocator_type` to use the empty base class optimization. + // If the `allocator_type` is stateless, we can store our instance for free. + class AllocatorAndTag : private allocator_type { + Tag tag_; + + public: + explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {} + Tag& tag() { return tag_; } + const Tag& tag() const { return tag_; } + allocator_type& allocator() { return *this; } + const allocator_type& allocator() const { return *this; } + }; + + class Allocation { + size_type capacity_; + pointer buffer_; + + public: + Allocation(allocator_type& a, size_type capacity) + : capacity_(capacity), buffer_(Create(a, capacity)) {} + void Dealloc(allocator_type& a) { + std::allocator_traits::deallocate(a, buffer_, capacity_); + } + size_type capacity() const { return capacity_; } + const_pointer buffer() const { return buffer_; } + pointer buffer() { return buffer_; } + static pointer Create(allocator_type& a, size_type n) { + return std::allocator_traits::allocate(a, n); + } + }; + + // Stores either the inlined or allocated representation + union Rep { + using ValueTypeBuffer = + absl::aligned_storage_t; + using AllocationBuffer = + absl::aligned_storage_t; + + // Structs wrap the buffers to perform indirection that solves a bizarre + // compilation error on Visual Studio (all known versions). + struct InlinedRep { + ValueTypeBuffer inlined[N]; + }; + + struct AllocatedRep { + AllocationBuffer allocation; + }; + + InlinedRep inlined_storage; + AllocatedRep allocation_storage; + }; + + AllocatorAndTag allocator_and_tag_; + Rep rep_; +}; + +} // namespace inlined_vector_internal +} // namespace absl + +#endif // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 9e79cb38..87511148 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -1080,6 +1080,7 @@ ExpectedStats XorSeedExpectedStats() { ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width"); return {}; } + TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) { ProbeStatsPerSize stats; std::vector sizes = {Group::kWidth << 5, Group::kWidth << 10}; @@ -1173,6 +1174,7 @@ ExpectedStats LinearTransformExpectedStats() { ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width"); return {}; } + TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) { ProbeStatsPerSize stats; std::vector sizes = {Group::kWidth << 5, Group::kWidth << 10}; diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake index 80c98193..d02ea193 100644 --- a/absl/copts/GENERATED_AbseilCopts.cmake +++ b/absl/copts/GENERATED_AbseilCopts.cmake @@ -20,6 +20,7 @@ list(APPEND GCC_FLAGS "-Wvarargs" "-Wvla" "-Wwrite-strings" + "-Wno-missing-field-initializers" "-Wno-sign-compare" ) diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl index a001347d..d23f4069 100644 --- a/absl/copts/GENERATED_copts.bzl +++ b/absl/copts/GENERATED_copts.bzl @@ -21,6 +21,7 @@ GCC_FLAGS = [ "-Wvarargs", "-Wvla", "-Wwrite-strings", + "-Wno-missing-field-initializers", "-Wno-sign-compare", ] diff --git a/absl/copts/copts.py b/absl/copts/copts.py index 4da8442d..5a2d91a3 100644 --- a/absl/copts/copts.py +++ b/absl/copts/copts.py @@ -10,6 +10,7 @@ compilation options: The generated copts are consumed by configure_copts.bzl and AbseilConfigureCopts.cmake. """ + COPT_VARS = { "GCC_FLAGS": [ "-Wall", @@ -24,6 +25,10 @@ COPT_VARS = { "-Wvarargs", "-Wvla", # variable-length array "-Wwrite-strings", + # gcc-4.x has spurious missing field initializer warnings. + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 + # Remove when gcc-4.x is no longer supported. + "-Wno-missing-field-initializers", # Google style does not use unsigned integers, though STL containers # have unsigned types. "-Wno-sign-compare", diff --git a/absl/debugging/internal/address_is_readable.h b/absl/debugging/internal/address_is_readable.h index 64c3f1ea..ca8003e6 100644 --- a/absl/debugging/internal/address_is_readable.h +++ b/absl/debugging/internal/address_is_readable.h @@ -11,7 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// #ifndef ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ #define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index d410a232..883b92db 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -176,6 +176,7 @@ static void TestOnInput(const char* input) { TEST(DemangleRegression, NegativeLength) { TestOnInput("_ZZn4"); } + TEST(DemangleRegression, DeeplyNestedArrayType) { const int depth = 100000; std::string data = "_ZStI"; diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc index 248966b0..25aa8bdf 100644 --- a/absl/debugging/internal/stacktrace_x86-inl.inc +++ b/absl/debugging/internal/stacktrace_x86-inl.inc @@ -33,6 +33,7 @@ #include "absl/debugging/internal/address_is_readable.h" #include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems #include "absl/debugging/stacktrace.h" + #include "absl/base/internal/raw_logging.h" #if defined(__linux__) && defined(__i386__) diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc index a1cae969..ffe3d1bd 100644 --- a/absl/debugging/leak_check.cc +++ b/absl/debugging/leak_check.cc @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + // Wrappers around lsan_interface functions. // When lsan is not linked in, these functions are not available, // therefore Abseil code which depends on these functions is conditioned on the diff --git a/absl/debugging/stacktrace.cc b/absl/debugging/stacktrace.cc index 9935adfa..9de8782f 100644 --- a/absl/debugging/stacktrace.cc +++ b/absl/debugging/stacktrace.cc @@ -46,6 +46,7 @@ #include ABSL_STACKTRACE_INL_HEADER #else # error Cannot calculate stack trace: will need to write for your environment + # include "absl/debugging/internal/stacktrace_aarch64-inl.inc" # include "absl/debugging/internal/stacktrace_arm-inl.inc" # include "absl/debugging/internal/stacktrace_generic-inl.inc" diff --git a/absl/hash/hash.h b/absl/hash/hash.h index 94cb6747..c0ede35a 100644 --- a/absl/hash/hash.h +++ b/absl/hash/hash.h @@ -309,4 +309,5 @@ class HashState : public hash_internal::HashStateBase { }; } // namespace absl + #endif // ABSL_HASH_HASH_H_ diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index a2430e7a..af959385 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc @@ -276,6 +276,7 @@ TEST(HashValueTest, Strings) { const std::string dup = "foofoo"; const std::string large = "large"; const std::string huge = std::string(5000, 'a'); + EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( std::string(), absl::string_view(), std::string(""), absl::string_view(""), diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h index 1b3b4ef9..b43d3407 100644 --- a/absl/hash/internal/city.h +++ b/absl/hash/internal/city.h @@ -49,7 +49,6 @@ #include // for size_t. #include - namespace absl { namespace hash_internal { diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index 8a788dea..b1b14914 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h @@ -485,4 +485,65 @@ inline void AssertHashEnabled() { } // namespace absl +// An internal namespace that is required to implement the C++17 swap traits. +// +// NOTE: This is its own top-level namespace to avoid subtleties due to +// functions named "swap" that may appear in the absl namespace. +namespace absl_internal_swap { + +using std::swap; + +template +using IsSwappableImpl = decltype(swap(std::declval(), std::declval())); + +// NOTE: This dance with the default template parameter is for MSVC. +template (), std::declval()))>> +using IsNothrowSwappableImpl = typename std::enable_if::type; + +// IsSwappable +// +// Determines whether the standard swap idiom is a valid expression for +// arguments of type `T`. +template +struct IsSwappable + : absl::type_traits_internal::is_detected {}; + +// IsNothrowSwappable +// +// Determines whether the standard swap idiom is a valid expression for +// arguments of type `T` and is noexcept. +template +struct IsNothrowSwappable + : absl::type_traits_internal::is_detected {}; + +// Swap() +// +// Performs the swap idiom from a namespace with no additional `swap` overloads. +template ::value, int> = 0> +void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable::value) { + swap(lhs, rhs); +} + +} // namespace absl_internal_swap + +namespace absl { +namespace type_traits_internal { + +// Make the swap-related traits/function accessible from this namespace. +using absl_internal_swap::IsNothrowSwappable; +using absl_internal_swap::IsSwappable; +using absl_internal_swap::Swap; + +// StdSwapIsUnconstrained +// +// Some standard library implementations are broken in that they do not +// constrain `std::swap`. This will effectively tell us if we are dealing with +// one of those implementations. +using StdSwapIsUnconstrained = IsSwappable; + +} // namespace type_traits_internal +} // namespace absl + #endif // ABSL_META_TYPE_TRAITS_H_ diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc index 29a6db69..912336e9 100644 --- a/absl/meta/type_traits_test.cc +++ b/absl/meta/type_traits_test.cc @@ -953,4 +953,85 @@ TEST(TypeTraitsTest, IsMoveAssignable) { #endif // _LIBCPP_VERSION } +namespace adl_namespace { + +struct DeletedSwap { +}; + +void swap(DeletedSwap&, DeletedSwap&) = delete; + +struct SpecialNoexceptSwap { + SpecialNoexceptSwap(SpecialNoexceptSwap&&) {} + SpecialNoexceptSwap& operator=(SpecialNoexceptSwap&&) { return *this; } + ~SpecialNoexceptSwap() = default; +}; + +void swap(SpecialNoexceptSwap&, SpecialNoexceptSwap&) noexcept {} + +} // namespace adl_namespace + +TEST(TypeTraitsTest, IsSwappable) { + using absl::type_traits_internal::IsSwappable; + using absl::type_traits_internal::StdSwapIsUnconstrained; + + EXPECT_TRUE(IsSwappable::value); + + struct S {}; + EXPECT_TRUE(IsSwappable::value); + + struct NoConstruct { + NoConstruct(NoConstruct&&) = delete; + NoConstruct& operator=(NoConstruct&&) { return *this; } + ~NoConstruct() = default; + }; + + EXPECT_EQ(IsSwappable::value, StdSwapIsUnconstrained::value); + struct NoAssign { + NoAssign(NoAssign&&) {} + NoAssign& operator=(NoAssign&&) = delete; + ~NoAssign() = default; + }; + + EXPECT_EQ(IsSwappable::value, StdSwapIsUnconstrained::value); + + EXPECT_FALSE(IsSwappable::value); + + EXPECT_TRUE(IsSwappable::value); +} + +TEST(TypeTraitsTest, IsNothrowSwappable) { + using absl::type_traits_internal::IsNothrowSwappable; + using absl::type_traits_internal::StdSwapIsUnconstrained; + + EXPECT_TRUE(IsNothrowSwappable::value); + + struct NonNoexceptMoves { + NonNoexceptMoves(NonNoexceptMoves&&) {} + NonNoexceptMoves& operator=(NonNoexceptMoves&&) { return *this; } + ~NonNoexceptMoves() = default; + }; + + EXPECT_FALSE(IsNothrowSwappable::value); + + struct NoConstruct { + NoConstruct(NoConstruct&&) = delete; + NoConstruct& operator=(NoConstruct&&) { return *this; } + ~NoConstruct() = default; + }; + + EXPECT_FALSE(IsNothrowSwappable::value); + + struct NoAssign { + NoAssign(NoAssign&&) {} + NoAssign& operator=(NoAssign&&) = delete; + ~NoAssign() = default; + }; + + EXPECT_FALSE(IsNothrowSwappable::value); + + EXPECT_FALSE(IsNothrowSwappable::value); + + EXPECT_TRUE(IsNothrowSwappable::value); +} + } // namespace diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h index c0ec03d4..2f5b8ad7 100644 --- a/absl/numeric/int128.h +++ b/absl/numeric/int128.h @@ -53,7 +53,6 @@ namespace absl { - // uint128 // // An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 8afe8177..9640ff46 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -12,7 +12,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# load( "//absl:copts/configure_copts.bzl", diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h index 03ab0ae7..fd9be786 100644 --- a/absl/strings/escaping.h +++ b/absl/strings/escaping.h @@ -19,7 +19,6 @@ // // This header file contains string utilities involved in escaping and // unescaping strings in various ways. -// #ifndef ABSL_STRINGS_ESCAPING_H_ #define ABSL_STRINGS_ESCAPING_H_ @@ -56,7 +55,6 @@ namespace absl { // UTF-8. (E.g., `\u2019` unescapes to the three bytes 0xE2, 0x80, and // 0x99). // -// // If any errors are encountered, this function returns `false`, leaving the // `dest` output parameter in an unspecified state, and stores the first // encountered error in `error`. To disable error reporting, set `error` to diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index c54cd1ab..4d48af06 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -35,12 +35,14 @@ struct HasUserDefinedConvert< T, void_t(), std::declval(), std::declval()))>> : std::true_type {}; + template class StreamedWrapper; // If 'v' can be converted (in the printf sense) according to 'conv', // then convert it, appending to `sink` and return `true`. // Otherwise fail and return `false`. + // Raw pointers. struct VoidPtr { VoidPtr() = default; diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 5d77856d..99cc0afe 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -363,6 +363,7 @@ typedef ::testing::Types< AllIntTypes; INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes, TypedFormatConvertTest, AllIntTypes); + TEST_F(FormatConvertTest, Uint128) { absl::uint128 v = static_cast(0x1234567890abcdef) * 1979; absl::uint128 max = absl::Uint128Max(); diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h index 30235e08..eb81f8a1 100644 --- a/absl/strings/internal/str_format/extension.h +++ b/absl/strings/internal/str_format/extension.h @@ -13,7 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc index 334a1484..4e23fefb 100644 --- a/absl/strings/internal/str_format/extension_test.cc +++ b/absl/strings/internal/str_format/extension_test.cc @@ -18,6 +18,7 @@ #include #include + #include "absl/strings/str_format.h" #include "gtest/gtest.h" diff --git a/absl/strings/internal/str_format/output_test.cc b/absl/strings/internal/str_format/output_test.cc index ca93d1e3..6e04abef 100644 --- a/absl/strings/internal/str_format/output_test.cc +++ b/absl/strings/internal/str_format/output_test.cc @@ -17,7 +17,6 @@ #include #include - #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/absl/strings/internal/utf8.h b/absl/strings/internal/utf8.h index 445d4c35..04236304 100644 --- a/absl/strings/internal/utf8.h +++ b/absl/strings/internal/utf8.h @@ -13,7 +13,6 @@ // limitations under the License. // // UTF8 utilities, implemented to reduce dependencies. -// #ifndef ABSL_STRINGS_INTERNAL_UTF8_H_ #define ABSL_STRINGS_INTERNAL_UTF8_H_ diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h index 69d6eaad..cba8ceb0 100644 --- a/absl/strings/str_cat.h +++ b/absl/strings/str_cat.h @@ -42,7 +42,6 @@ // Floating point numbers are formatted with six-digit precision, which is // the default for "std::cout <<" or printf "%g" (the same as "%.6g"). // -// // You can convert to hexadecimal output rather than decimal output using the // `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to // `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h index 486fe0eb..539d9516 100644 --- a/absl/strings/str_format.h +++ b/absl/strings/str_format.h @@ -513,4 +513,5 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped( } } // namespace absl + #endif // ABSL_STRINGS_STR_FORMAT_H_ diff --git a/absl/strings/str_split.h b/absl/strings/str_split.h index 8eb55089..73330789 100644 --- a/absl/strings/str_split.h +++ b/absl/strings/str_split.h @@ -71,7 +71,6 @@ namespace absl { // - `ByLength` // - `MaxSplits` // -// // A Delimiter's `Find()` member function will be passed an input `text` that is // to be split and a position (`pos`) to begin searching for the next delimiter // in `text`. The returned absl::string_view should refer to the next occurrence diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h index bd894e1d..f8b20015 100644 --- a/absl/strings/string_view.h +++ b/absl/strings/string_view.h @@ -101,7 +101,6 @@ namespace absl { // example, when splitting a string, `std::vector` is a // natural data type for the output. // -// // When constructed from a source which is nul-terminated, the `string_view` // itself will not include the nul-terminator unless a specific size (including // the nul) is passed to the constructor. As a result, common idioms that work @@ -508,6 +507,7 @@ inline bool operator==(string_view x, string_view y) noexcept { if (len != y.size()) { return false; } + return x.data() == y.data() || len <= 0 || memcmp(x.data(), y.data(), len) == 0; } diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index a45ff039..507bc4ff 100644 --- a/absl/strings/substitute.h +++ b/absl/strings/substitute.h @@ -45,7 +45,6 @@ // SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5); // EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s); // -// // Supported types: // * absl::string_view, std::string, const char* (null is equivalent to "") // * int32_t, int64_t, uint32_t, uint64 diff --git a/absl/synchronization/internal/create_thread_identity.h b/absl/synchronization/internal/create_thread_identity.h index b2525b72..ebb16c56 100644 --- a/absl/synchronization/internal/create_thread_identity.h +++ b/absl/synchronization/internal/create_thread_identity.h @@ -50,4 +50,5 @@ inline base_internal::ThreadIdentity* GetOrCreateCurrentThreadIdentity() { } // namespace synchronization_internal } // namespace absl + #endif // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_ diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h index 543c4a03..61c72e75 100644 --- a/absl/synchronization/internal/kernel_timeout.h +++ b/absl/synchronization/internal/kernel_timeout.h @@ -53,6 +53,7 @@ class KernelTimeout { // We explicitly do not support other custom formats: timespec, int64_t nanos. // Unify on this and absl::Time, please. + bool has_timeout() const { return ns_ != 0; } private: @@ -148,4 +149,5 @@ class KernelTimeout { } // namespace synchronization_internal } // namespace absl + #endif // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_ diff --git a/absl/synchronization/internal/per_thread_sem.cc b/absl/synchronization/internal/per_thread_sem.cc index d22539dc..b7014fb2 100644 --- a/absl/synchronization/internal/per_thread_sem.cc +++ b/absl/synchronization/internal/per_thread_sem.cc @@ -89,6 +89,7 @@ ABSL_ATTRIBUTE_WEAK bool AbslInternalPerThreadSemWait( if (identity->blocked_count_ptr != nullptr) { identity->blocked_count_ptr->fetch_sub(1, std::memory_order_relaxed); } + identity->is_idle.store(false, std::memory_order_relaxed); identity->wait_start.store(0, std::memory_order_relaxed); return !timeout; diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h index d373f63b..e7da070b 100644 --- a/absl/synchronization/internal/per_thread_sem.h +++ b/absl/synchronization/internal/per_thread_sem.h @@ -104,4 +104,5 @@ bool absl::synchronization_internal::PerThreadSem::Wait( absl::synchronization_internal::KernelTimeout t) { return AbslInternalPerThreadSemWait(t); } + #endif // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_ diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc index bab6d1a1..74b09650 100644 --- a/absl/synchronization/internal/waiter.cc +++ b/absl/synchronization/internal/waiter.cc @@ -40,6 +40,7 @@ #include #include #include + #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/thread_identity.h" #include "absl/base/optimization.h" @@ -81,6 +82,7 @@ static void MaybeBecomeIdle() { #define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF #endif #endif + class Futex { public: static int WaitUntil(std::atomic *v, int32_t val, diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index f4ed0d00..6b2eb331 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -265,6 +265,7 @@ static const struct { { 0, "Signal on " }, { 0, "SignalAll on " }, }; + static absl::base_internal::SpinLock synch_event_mu( absl::base_internal::kLinkerInitialized); // protects synch_event diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index cf0f86dc..c38e3561 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -157,6 +157,7 @@ class LOCKABLE Mutex { // ABSL_CONST_INIT Mutex mu(absl::kConstInit); // } explicit constexpr Mutex(absl::ConstInitType); + ~Mutex(); // Mutex::Lock() @@ -900,10 +901,12 @@ class SCOPED_LOCKABLE ReleasableMutexLock { #ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {} + #else inline Mutex::Mutex() : mu_(0) { ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); } + inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {} inline CondVar::CondVar() : cv_(0) {} @@ -1047,4 +1050,5 @@ void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode); extern "C" { void AbslInternalMutexYield(); } // extern "C" + #endif // ABSL_SYNCHRONIZATION_MUTEX_H_ diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc index 53c1f744..10211229 100644 --- a/absl/synchronization/mutex_test.cc +++ b/absl/synchronization/mutex_test.cc @@ -1032,9 +1032,9 @@ class ScopedDisableBazelTestWarnings { ScopedDisableBazelTestWarnings() { #ifdef WIN32 char file[MAX_PATH]; - if (GetEnvironmentVariable(kVarName, file, sizeof(file)) < sizeof(file)) { + if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) { warnings_output_file_ = file; - SetEnvironmentVariable(kVarName, nullptr); + SetEnvironmentVariableA(kVarName, nullptr); } #else const char *file = getenv(kVarName); @@ -1048,7 +1048,7 @@ class ScopedDisableBazelTestWarnings { ~ScopedDisableBazelTestWarnings() { if (!warnings_output_file_.empty()) { #ifdef WIN32 - SetEnvironmentVariable(kVarName, warnings_output_file_.c_str()); + SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str()); #else setenv(kVarName, warnings_output_file_.c_str(), 0); #endif diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h index 19f51de7..82d111a5 100644 --- a/absl/synchronization/notification.h +++ b/absl/synchronization/notification.h @@ -110,4 +110,5 @@ class Notification { }; } // namespace absl + #endif // ABSL_SYNCHRONIZATION_NOTIFICATION_H_ diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h index f231e4f8..2dfcbd27 100644 --- a/absl/time/civil_time.h +++ b/absl/time/civil_time.h @@ -66,7 +66,6 @@ // // // Valid in C++14 // constexpr absl::CivilDay cd(1969, 07, 20); -// #ifndef ABSL_TIME_CIVIL_TIME_H_ #define ABSL_TIME_CIVIL_TIME_H_ diff --git a/absl/time/duration.cc b/absl/time/duration.cc index 8ce4acbb..67791fee 100644 --- a/absl/time/duration.cc +++ b/absl/time/duration.cc @@ -901,6 +901,7 @@ bool ParseDuration(const std::string& dur_string, Duration* d) { *d = dur; return true; } + bool ParseFlag(const std::string& text, Duration* dst, std::string* ) { return ParseDuration(text, dst); } diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc index 4a68c7d5..fd04e2df 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup.cc @@ -127,7 +127,7 @@ time_zone local_time_zone() { #if defined(_MSC_VER) _dupenv_s(&tz_env, nullptr, "TZ"); #elif defined(__APPLE__) - CFTimeZoneRef system_time_zone = CFTimeZoneCopySystem(); + CFTimeZoneRef system_time_zone = CFTimeZoneCopyDefault(); CFStringRef tz_name = CFTimeZoneGetName(system_time_zone); tz_env = strdup(CFStringGetCStringPtr(tz_name, CFStringGetSystemEncoding())); CFRelease(system_time_zone); diff --git a/absl/time/time.cc b/absl/time/time.cc index 799bf859..977a9517 100644 --- a/absl/time/time.cc +++ b/absl/time/time.cc @@ -41,6 +41,7 @@ #include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace cctz = absl::time_internal::cctz; + namespace absl { namespace { diff --git a/absl/time/time.h b/absl/time/time.h index 59e1dc64..594396c7 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -58,7 +58,6 @@ // std::string s = absl::FormatTime( // "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S", // landing, syd); -// #ifndef ABSL_TIME_TIME_H_ #define ABSL_TIME_TIME_H_ @@ -569,7 +568,6 @@ std::string UnparseFlag(Duration d); // The `absl::Time` class represents an instant in time as a count of clock // ticks of some granularity (resolution) from some starting point (epoch). // -// // `absl::Time` uses a resolution that is high enough to avoid loss in // precision, and a range that is wide enough to avoid overflow, when // converting between tick counts in most Google time scales (i.e., resolution @@ -1450,6 +1448,7 @@ T ToChronoDuration(Duration d) { } } // namespace time_internal + constexpr Duration Nanoseconds(int64_t n) { return time_internal::FromInt64(n, std::nano{}); } diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc index 00d0fb72..5d7d8a5c 100644 --- a/absl/types/any_exception_safety_test.cc +++ b/absl/types/any_exception_safety_test.cc @@ -135,6 +135,7 @@ TEST(AnyExceptionSafety, Assignment) { EXPECT_TRUE(strong_empty_any_tester.Test(assign_val)); EXPECT_TRUE(strong_empty_any_tester.Test(move)); } + // libstdc++ std::any fails this test #if !defined(ABSL_HAVE_STD_ANY) TEST(AnyExceptionSafety, Emplace) { diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h index 4926b321..5ca66e29 100644 --- a/absl/types/internal/variant.h +++ b/absl/types/internal/variant.h @@ -15,7 +15,6 @@ // Implementation details of absl/types/variant.h, pulled into a // separate file to avoid cluttering the top of the API header with // implementation details. -// #ifndef ABSL_TYPES_variant_internal_H_ #define ABSL_TYPES_variant_internal_H_ @@ -1549,8 +1548,8 @@ struct SwapSameIndex { variant* w; template void operator()(SizeT) const { - using std::swap; - swap(VariantCoreAccess::Access(*v), VariantCoreAccess::Access(*w)); + type_traits_internal::Swap(VariantCoreAccess::Access(*v), + VariantCoreAccess::Access(*w)); } void operator()(SizeT) const {} diff --git a/absl/types/optional.h b/absl/types/optional.h index c0488797..58906aa4 100644 --- a/absl/types/optional.h +++ b/absl/types/optional.h @@ -114,10 +114,6 @@ namespace absl { // need the inline variable support in C++17 for external linkage. // * Throws `absl::bad_optional_access` instead of // `std::bad_optional_access`. -// * `optional::swap()` and `absl::swap()` relies on -// `std::is_(nothrow_)swappable()`, which has been introduced in C++17. -// As a workaround, we assume `is_swappable()` is always `true` -// and `is_nothrow_swappable()` is the same as `std::is_trivial()`. // * `make_optional()` cannot be declared `constexpr` due to the absence of // guaranteed copy elision. // * The move constructor's `noexcept` specification is stronger, i.e. if the @@ -753,11 +749,10 @@ class optional : private optional_internal::optional_data, // Swap, standard semantics void swap(optional& rhs) noexcept( std::is_nothrow_move_constructible::value&& - std::is_trivial::value) { + type_traits_internal::IsNothrowSwappable::value) { if (*this) { if (rhs) { - using std::swap; - swap(**this, *rhs); + type_traits_internal::Swap(**this, *rhs); } else { rhs.construct(std::move(**this)); this->destruct(); @@ -909,12 +904,10 @@ class optional : private optional_internal::optional_data, // // Performs a swap between two `absl::optional` objects, using standard // semantics. -// -// NOTE: we assume `is_swappable()` is always `true`. A compile error will -// result if this is not the case. -template ::value, - bool>::type = false> +template ::value && + type_traits_internal::IsSwappable::value, + bool>::type = false> void swap(optional& a, optional& b) noexcept(noexcept(a.swap(b))) { a.swap(b); } diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc index 68842abb..0665488e 100644 --- a/absl/types/optional_test.cc +++ b/absl/types/optional_test.cc @@ -1636,6 +1636,7 @@ TEST(optionalTest, AssignmentConstraints) { EXPECT_TRUE(absl::is_copy_assignable>::value); } +#if !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION) struct NestedClassBug { struct Inner { bool dummy = false; @@ -1658,5 +1659,6 @@ TEST(optionalTest, InPlaceTSFINAEBug) { o.emplace(); EXPECT_TRUE(o.has_value()); } +#endif // !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION) } // namespace diff --git a/absl/types/variant.h b/absl/types/variant.h index 8d8b5dbd..ebd52d28 100644 --- a/absl/types/variant.h +++ b/absl/types/variant.h @@ -129,7 +129,12 @@ class variant; // type (in which case, they will be swapped) or to two different types (in // which case the values will need to be moved). // -template +template < + typename... Ts, + absl::enable_if_t< + absl::conjunction..., + type_traits_internal::IsSwappable...>::value, + int> = 0> void swap(variant& v, variant& w) noexcept(noexcept(v.swap(w))) { v.swap(w); } @@ -688,12 +693,12 @@ class variant : private variant_internal::VariantBase { // // Swaps the values of two variant objects. // - // TODO(calabrese) - // `variant::swap()` and `swap()` rely on `std::is_(nothrow)_swappable()` - // which is introduced in C++17. So we assume `is_swappable()` is always - // true and `is_nothrow_swappable()` is same as `std::is_trivial()`. void swap(variant& rhs) noexcept( - absl::conjunction, std::is_trivial...>::value) { + absl::conjunction< + std::is_nothrow_move_constructible, + std::is_nothrow_move_constructible..., + type_traits_internal::IsNothrowSwappable, + type_traits_internal::IsNothrowSwappable...>::value) { return variant_internal::VisitIndices::Run( variant_internal::Swap{this, &rhs}, rhs.index()); } diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc index 086fcff0..76beb595 100644 --- a/absl/types/variant_exception_safety_test.cc +++ b/absl/types/variant_exception_safety_test.cc @@ -24,6 +24,7 @@ #include "absl/base/config.h" #include "absl/base/internal/exception_safety_testing.h" #include "absl/memory/memory.h" + // See comment in absl/base/config.h #if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) @@ -315,6 +316,12 @@ TEST(VariantExceptionSafetyTest, MoveAssign) { EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); } { + // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06. + // The fix is targeted for gcc-9. + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7 + // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614 +#if !(defined(ABSL_HAVE_STD_VARIANT) && \ + defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8) // - otherwise (index() != j), equivalent to // emplace(get(std::move(rhs))) // - If an exception is thrown during the call to Tj's move construction @@ -330,6 +337,8 @@ TEST(VariantExceptionSafetyTest, MoveAssign) { auto copy = rhs; *lhs = std::move(copy); })); +#endif // !(defined(ABSL_HAVE_STD_VARIANT) && + // defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8) } } diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index 9df702df..ab40ed2a 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -561,6 +561,7 @@ TEST(VariantTest, TestDtor) { } #ifdef ABSL_HAVE_EXCEPTIONS + // See comment in absl/base/config.h #if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) TEST(VariantTest, DISABLED_TestDtorValuelessByException) diff --git a/absl/utility/utility.h b/absl/utility/utility.h index 62ce6f3a..853c1fb8 100644 --- a/absl/utility/utility.h +++ b/absl/utility/utility.h @@ -35,7 +35,6 @@ // https://en.cppreference.com/w/cpp/utility/integer_sequence // https://en.cppreference.com/w/cpp/utility/apply // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html -// #ifndef ABSL_UTILITY_UTILITY_H_ #define ABSL_UTILITY_UTILITY_H_ diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh new file mode 100755 index 00000000..741e48c4 --- /dev/null +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script that can be invoked to test abseil-cpp in a hermetic environment +# using a Docker image on Linux. You must have Docker installed to use this +# script. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${STD:-} ]; then + STD="c++11 c++14 c++17" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +for std in ${STD}; do + for compilation_mode in ${COMPILATION_MODE}; do + echo "--------------------------------------------------------------------" + echo "Testing with --compilation_mode=${compilation_mode} and --std=${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/opt/llvm/clang/bin/clang" \ + -e BAZEL_COMPILER="llvm" \ + -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \ + -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \ + -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \ + gcr.io/google.com/absl-177019/linux_clang-latest:20190313 \ + /usr/local/bin/bazel test ... \ + --compilation_mode=${compilation_mode} \ + --copt=-Werror \ + --define="absl=1" \ + --keep_going \ + --show_timestamps \ + --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark + done +done diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh new file mode 100755 index 00000000..d703a776 --- /dev/null +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script that can be invoked to test abseil-cpp in a hermetic environment +# using a Docker image on Linux. You must have Docker installed to use this +# script. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${STD:-} ]; then + STD="c++11 c++14 c++17" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +for std in ${STD}; do + for compilation_mode in ${COMPILATION_MODE}; do + echo "--------------------------------------------------------------------" + echo "Testing with --compilation_mode=${compilation_mode} and --std=${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/opt/llvm/clang/bin/clang" \ + -e BAZEL_COMPILER="llvm" \ + -e BAZEL_CXXOPTS="-std=${std}" \ + -e CPLUS_INCLUDE_PATH="/usr/include/c++/6" \ + gcr.io/google.com/absl-177019/linux_clang-latest:20190313 \ + /usr/local/bin/bazel test ... \ + --compilation_mode=${compilation_mode} \ + --copt=-Werror \ + --define="absl=1" \ + --keep_going \ + --show_timestamps \ + --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark + done +done diff --git a/ci/linux_gcc-4.8_libstdcxx_cmake.sh b/ci/linux_gcc-4.8_libstdcxx_cmake.sh new file mode 100755 index 00000000..4f964e2b --- /dev/null +++ b/ci/linux_gcc-4.8_libstdcxx_cmake.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# TODO(absl-team): This script isn't fully hermetic because +# -DABSL_USE_GOOGLETEST_HEAD=ON means that this script isn't pinned to a fixed +# version of GoogleTest. This means that an upstream change to GoogleTest could +# break this test. Fix this by allowing this script to pin to a known-good +# version of GoogleTest. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then + ABSL_CMAKE_CXX_STANDARDS="11 14" +fi + +if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then + ABSL_CMAKE_BUILD_TYPES="Debug Release" +fi + +for std in ${ABSL_CMAKE_CXX_STANDARDS}; do + for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do + echo "--------------------------------------------------------------------" + echo "Testing with CMAKE_BUILD_TYPE=${compilation_mode} and -std=c++${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --tmpfs=/buildfs:exec \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CFLAGS="-Werror" \ + -e CXXFLAGS="-Werror" \ + gcr.io/google.com/absl-177019/linux_gcc-4.8:20190316 \ + /bin/bash -c " + cd /buildfs && \ + cmake /abseil-cpp \ + -DABSL_USE_GOOGLETEST_HEAD=ON \ + -DABSL_RUN_TESTS=ON \ + -DCMAKE_BUILD_TYPE=${compilation_mode} \ + -DCMAKE_CXX_STANDARD=${std} && \ + make -j$(nproc) VERBOSE=1 && \ + ctest -j$(nproc) --output-on-failure" + done +done diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh new file mode 100755 index 00000000..e14a019c --- /dev/null +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script that can be invoked to test abseil-cpp in a hermetic environment +# using a Docker image on Linux. You must have Docker installed to use this +# script. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${STD:-} ]; then + STD="c++11 c++14 c++17" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +for std in ${STD}; do + for compilation_mode in ${COMPILATION_MODE}; do + echo "--------------------------------------------------------------------" + echo "Testing with --compilation_mode=${compilation_mode} and --std=${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/usr/local/bin/gcc" \ + -e BAZEL_CXXOPTS="-std=${std}" \ + gcr.io/google.com/absl-177019/linux_gcc-latest:20190318 \ + /usr/local/bin/bazel test ... \ + --compilation_mode=${compilation_mode} \ + --copt=-Werror \ + --define="absl=1" \ + --keep_going \ + --show_timestamps \ + --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark + done +done -- cgit v1.2.3 From 1e39f8626a4dadec1f56920b999dd4c3cfae333e Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 10 Dec 2019 09:03:32 -0800 Subject: Export of internal Abseil changes -- b842b7fd9b1289be31f0b7ee8e62e48e550747cf by Greg Falcon : Change the Cord str_format formatter to use iteration instead of CordReader. When Cord is publicly released, CordReader is not going with it. PiperOrigin-RevId: 284780736 -- 28e76c08ea7185a7ff9f4e0e02ae565fbbf7980f by Greg Falcon : Implementation detail change. Introduce ABSL_NAMESPACE_BEGIN and _END annotation macros which indicate the beginning and end of a `namespace absl` scope. Currently these do nothing, but they will be used to inject an inline namespace for LTS builds (to avoid symbol collisions against other Abseil versions). These macros should not be used by end users, because end users should never write `namespace absl {` in their own code. This CL applies these annotations to all code under //absl/base/. The rest of Abseil will be annotated in this way in follow-up CLs. PiperOrigin-RevId: 284776410 -- e1711dc6d696dcca50d4e7d4b4d8f3076575b7ec by Abseil Team : --help changed to report long flags. PiperOrigin-RevId: 284757720 -- 78f66a68f428bbbd19d8d60e1125f43ba765fd35 by Tom Manshreck : Update comment on + or - in SimpleAToi() PiperOrigin-RevId: 284231843 GitOrigin-RevId: b842b7fd9b1289be31f0b7ee8e62e48e550747cf Change-Id: I3046b31391bd11c8bc4abab7785a863c377cd757 --- absl/base/BUILD.bazel | 22 ++++++-- absl/base/CMakeLists.txt | 6 ++ absl/base/bit_cast_test.cc | 2 + absl/base/call_once.h | 2 + absl/base/call_once_test.cc | 2 + absl/base/casts.h | 2 + absl/base/config.h | 27 +++++++++ absl/base/const_init.h | 4 ++ absl/base/inline_variable_test.cc | 2 + absl/base/inline_variable_test_a.cc | 2 + absl/base/inline_variable_test_b.cc | 2 + absl/base/internal/atomic_hook.h | 4 ++ absl/base/internal/atomic_hook_test_helper.cc | 2 + absl/base/internal/atomic_hook_test_helper.h | 2 + absl/base/internal/bits.h | 4 ++ absl/base/internal/cycleclock.cc | 2 + absl/base/internal/cycleclock.h | 4 ++ absl/base/internal/direct_mmap.h | 4 ++ absl/base/internal/endian.h | 2 + absl/base/internal/endian_test.cc | 2 + absl/base/internal/exponential_biased.cc | 2 + absl/base/internal/exponential_biased.h | 3 + absl/base/internal/exponential_biased_test.cc | 2 + absl/base/internal/hide_ptr.h | 4 ++ absl/base/internal/identity.h | 4 ++ absl/base/internal/inline_variable_testing.h | 2 + absl/base/internal/invoke.h | 2 + absl/base/internal/low_level_alloc.cc | 2 + absl/base/internal/low_level_alloc.h | 2 + absl/base/internal/low_level_alloc_test.cc | 2 + absl/base/internal/low_level_scheduling.h | 2 + absl/base/internal/periodic_sampler.cc | 2 + absl/base/internal/periodic_sampler.h | 2 + absl/base/internal/periodic_sampler_benchmark.cc | 2 + absl/base/internal/periodic_sampler_test.cc | 2 + absl/base/internal/raw_logging.cc | 2 + absl/base/internal/raw_logging.h | 2 + absl/base/internal/scheduling_mode.h | 4 ++ absl/base/internal/scoped_set_env.cc | 2 + absl/base/internal/scoped_set_env.h | 4 ++ absl/base/internal/spinlock.cc | 2 + absl/base/internal/spinlock.h | 2 + absl/base/internal/spinlock_wait.cc | 2 + absl/base/internal/spinlock_wait.h | 2 + absl/base/internal/sysinfo.cc | 2 + absl/base/internal/sysinfo.h | 2 + absl/base/internal/sysinfo_test.cc | 2 + absl/base/internal/thread_identity.cc | 2 + absl/base/internal/thread_identity.h | 2 + absl/base/internal/thread_identity_test.cc | 2 + absl/base/internal/throw_delegate.cc | 2 + absl/base/internal/throw_delegate.h | 4 ++ absl/base/internal/unaligned_access.h | 6 ++ absl/base/internal/unscaledcycleclock.cc | 2 + absl/base/internal/unscaledcycleclock.h | 2 + absl/base/invoke_test.cc | 2 + absl/base/log_severity.cc | 2 + absl/base/log_severity.h | 3 + absl/base/macros.h | 4 ++ absl/base/spinlock_test_common.cc | 2 + absl/base/thread_annotations.h | 3 + absl/flags/internal/usage.cc | 2 +- absl/flags/internal/usage_test.cc | 70 ++++++++++++------------ absl/strings/internal/str_format/arg.h | 19 ++++--- absl/strings/numbers.h | 17 +++--- 65 files changed, 253 insertions(+), 55 deletions(-) (limited to 'absl/base/internal/low_level_scheduling.h') diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index f8eb8aeb..e2068f51 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -34,6 +34,7 @@ cc_library( visibility = [ "//absl:__subpackages__", ], + deps = [":config"], ) cc_library( @@ -42,7 +43,10 @@ cc_library( hdrs = ["log_severity.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [":core_headers"], + deps = [ + ":config", + ":core_headers", + ], ) cc_library( @@ -165,6 +169,7 @@ cc_library( "//absl:__subpackages__", ], deps = [ + ":config", "//absl/meta:type_traits", ], ) @@ -545,7 +550,10 @@ cc_library( visibility = [ "//absl:__subpackages__", ], - deps = [":core_headers"], + deps = [ + ":config", + ":core_headers", + ], ) cc_test( @@ -568,7 +576,10 @@ cc_library( visibility = [ "//absl:__subpackages__", ], - deps = [":core_headers"], + deps = [ + ":config", + ":core_headers", + ], ) cc_test( @@ -635,7 +646,10 @@ cc_library( visibility = [ "//absl:__subpackages__", ], - deps = [":raw_logging_internal"], + deps = [ + ":config", + ":raw_logging_internal", + ], ) cc_test( diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index c521f32d..60fc1a83 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -21,6 +21,8 @@ absl_cc_library( atomic_hook HDRS "internal/atomic_hook.h" + DEPS + absl::config COPTS ${ABSL_DEFAULT_COPTS} ) @@ -148,6 +150,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::type_traits ) @@ -493,6 +496,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::core_headers ) @@ -518,6 +522,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::core_headers ) @@ -571,6 +576,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::raw_logging_internal ) diff --git a/absl/base/bit_cast_test.cc b/absl/base/bit_cast_test.cc index 4846add4..8a3a41ea 100644 --- a/absl/base/bit_cast_test.cc +++ b/absl/base/bit_cast_test.cc @@ -22,6 +22,7 @@ #include "absl/base/macros.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { template @@ -104,4 +105,5 @@ TEST(BitCast, Double) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/call_once.h b/absl/base/call_once.h index e1614e51..bc5ec937 100644 --- a/absl/base/call_once.h +++ b/absl/base/call_once.h @@ -41,6 +41,7 @@ #include "absl/base/port.h" namespace absl { +ABSL_NAMESPACE_BEGIN class once_flag; @@ -219,6 +220,7 @@ void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) { } } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_CALL_ONCE_H_ diff --git a/absl/base/call_once_test.cc b/absl/base/call_once_test.cc index 9a5a5c13..11d26c44 100644 --- a/absl/base/call_once_test.cc +++ b/absl/base/call_once_test.cc @@ -24,6 +24,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { absl::once_flag once; @@ -102,4 +103,5 @@ TEST(CallOnceTest, ExecutionCount) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/casts.h b/absl/base/casts.h index aba01782..322cc1d2 100644 --- a/absl/base/casts.h +++ b/absl/base/casts.h @@ -34,6 +34,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace internal_casts { @@ -177,6 +178,7 @@ inline Dest bit_cast(const Source& source) { return dest; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_CASTS_H_ diff --git a/absl/base/config.h b/absl/base/config.h index 556b186c..87f5b4ae 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -66,6 +66,33 @@ #include "absl/base/options.h" #include "absl/base/policy_checks.h" +// ----------------------------------------------------------------------------- +// Abseil namespace annotations +// ----------------------------------------------------------------------------- + +// ABSL_NAMESPACE_BEGIN/ABSL_NAMESPACE_END +// +// An annotation placed at the beginning/end of each `namespace absl` scope. +// This is used to inject an inline namespace. +// +// The proper way to write Abseil code in the `absl` namespace is: +// +// namespace absl { +// ABSL_NAMESPACE_BEGIN +// +// void Foo(); // absl::Foo(). +// +// ABSL_NAMESPACE_END +// } // namespace absl +// +// Users of Abseil should not use these macros, because users of Abseil should +// not write `namespace absl {` in their own code for any reason. (Abseil does +// not support forward declarations of its own types, nor does it support +// user-provided specialization of Abseil templates. Code that violates these +// rules may be broken without warning.) +#define ABSL_NAMESPACE_BEGIN +#define ABSL_NAMESPACE_END + // ----------------------------------------------------------------------------- // Compiler Feature Checks // ----------------------------------------------------------------------------- diff --git a/absl/base/const_init.h b/absl/base/const_init.h index 17858a77..16520b61 100644 --- a/absl/base/const_init.h +++ b/absl/base/const_init.h @@ -22,6 +22,8 @@ #ifndef ABSL_BASE_CONST_INIT_H_ #define ABSL_BASE_CONST_INIT_H_ +#include "absl/base/config.h" + // In general, objects with static storage duration (such as global variables) // can trigger tricky object lifetime situations. Attempting to access them // from the constructors or destructors of other global objects can result in @@ -62,11 +64,13 @@ // or thread_local storage duration. namespace absl { +ABSL_NAMESPACE_BEGIN enum ConstInitType { kConstInit, }; +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_CONST_INIT_H_ diff --git a/absl/base/inline_variable_test.cc b/absl/base/inline_variable_test.cc index 471f7063..37a40e1e 100644 --- a/absl/base/inline_variable_test.cc +++ b/absl/base/inline_variable_test.cc @@ -20,6 +20,7 @@ #include "gtest/gtest.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace inline_variable_testing_internal { namespace { @@ -59,4 +60,5 @@ TEST(InlineVariableTest, FunPtrType) { } // namespace } // namespace inline_variable_testing_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/inline_variable_test_a.cc b/absl/base/inline_variable_test_a.cc index d0b8e7d3..f96a58d9 100644 --- a/absl/base/inline_variable_test_a.cc +++ b/absl/base/inline_variable_test_a.cc @@ -15,6 +15,7 @@ #include "absl/base/internal/inline_variable_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace inline_variable_testing_internal { const Foo& get_foo_a() { return inline_variable_foo; } @@ -22,4 +23,5 @@ const Foo& get_foo_a() { return inline_variable_foo; } const int& get_int_a() { return inline_variable_int; } } // namespace inline_variable_testing_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/inline_variable_test_b.cc b/absl/base/inline_variable_test_b.cc index 931d56d0..038adc30 100644 --- a/absl/base/inline_variable_test_b.cc +++ b/absl/base/inline_variable_test_b.cc @@ -15,6 +15,7 @@ #include "absl/base/internal/inline_variable_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace inline_variable_testing_internal { const Foo& get_foo_b() { return inline_variable_foo; } @@ -22,4 +23,5 @@ const Foo& get_foo_b() { return inline_variable_foo; } const int& get_int_b() { return inline_variable_int; } } // namespace inline_variable_testing_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/atomic_hook.h b/absl/base/internal/atomic_hook.h index 6df956a6..d885bc05 100644 --- a/absl/base/internal/atomic_hook.h +++ b/absl/base/internal/atomic_hook.h @@ -20,6 +20,8 @@ #include #include +#include "absl/base/config.h" + #ifdef _MSC_FULL_VER #define ABSL_HAVE_WORKING_ATOMIC_POINTER 0 #define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 0 @@ -29,6 +31,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { template @@ -170,6 +173,7 @@ class AtomicHook { #undef ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_ diff --git a/absl/base/internal/atomic_hook_test_helper.cc b/absl/base/internal/atomic_hook_test_helper.cc index fad7a89a..f95d962b 100644 --- a/absl/base/internal/atomic_hook_test_helper.cc +++ b/absl/base/internal/atomic_hook_test_helper.cc @@ -18,6 +18,7 @@ #include "absl/base/internal/atomic_hook.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace atomic_hook_internal { ABSL_CONST_INIT absl::base_internal::AtomicHook func(DefaultFunc); @@ -26,4 +27,5 @@ void DefaultFunc() { default_func_calls++; } void RegisterFunc(VoidF f) { func.Store(f); } } // namespace atomic_hook_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/atomic_hook_test_helper.h b/absl/base/internal/atomic_hook_test_helper.h index 44ff780d..3e72b497 100644 --- a/absl/base/internal/atomic_hook_test_helper.h +++ b/absl/base/internal/atomic_hook_test_helper.h @@ -18,6 +18,7 @@ #include "absl/base/internal/atomic_hook.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace atomic_hook_internal { using VoidF = void (*)(); @@ -27,6 +28,7 @@ void DefaultFunc(); void RegisterFunc(VoidF func); } // namespace atomic_hook_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_ diff --git a/absl/base/internal/bits.h b/absl/base/internal/bits.h index 450b923f..8b03453c 100644 --- a/absl/base/internal/bits.h +++ b/absl/base/internal/bits.h @@ -20,6 +20,8 @@ #include +#include "absl/base/config.h" + // Clang on Windows has __builtin_clzll; otherwise we need to use the // windows intrinsic functions. #if defined(_MSC_VER) @@ -46,6 +48,7 @@ namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64Slow(uint64_t n) { @@ -209,6 +212,7 @@ ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32(uint32_t n) { #undef ABSL_BASE_INTERNAL_FORCEINLINE } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_BITS_H_ diff --git a/absl/base/internal/cycleclock.cc b/absl/base/internal/cycleclock.cc index e9844b71..0e65005b 100644 --- a/absl/base/internal/cycleclock.cc +++ b/absl/base/internal/cycleclock.cc @@ -28,6 +28,7 @@ #include "absl/base/internal/unscaledcycleclock.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { #if ABSL_USE_UNSCALED_CYCLECLOCK @@ -102,4 +103,5 @@ double CycleClock::Frequency() { #endif } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/cycleclock.h b/absl/base/internal/cycleclock.h index 794564e1..a18b5844 100644 --- a/absl/base/internal/cycleclock.h +++ b/absl/base/internal/cycleclock.h @@ -44,7 +44,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // ----------------------------------------------------------------------------- @@ -85,6 +88,7 @@ class CycleClockSource { }; } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_CYCLECLOCK_H_ diff --git a/absl/base/internal/direct_mmap.h b/absl/base/internal/direct_mmap.h index 0401ddfa..5618867b 100644 --- a/absl/base/internal/direct_mmap.h +++ b/absl/base/internal/direct_mmap.h @@ -62,6 +62,7 @@ extern "C" void* __mmap2(void*, size_t, int, int, int, size_t); #endif // __BIONIC__ namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // Platform specific logic extracted from @@ -128,6 +129,7 @@ inline int DirectMunmap(void* start, size_t length) { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #else // !__linux__ @@ -136,6 +138,7 @@ inline int DirectMunmap(void* start, size_t length) { // actual mmap()/munmap() methods. namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd, @@ -148,6 +151,7 @@ inline int DirectMunmap(void* start, size_t length) { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // __linux__ diff --git a/absl/base/internal/endian.h b/absl/base/internal/endian.h index 8233cb52..9677530e 100644 --- a/absl/base/internal/endian.h +++ b/absl/base/internal/endian.h @@ -31,6 +31,7 @@ #include "absl/base/port.h" namespace absl { +ABSL_NAMESPACE_BEGIN // Use compiler byte-swapping intrinsics if they are available. 32-bit // and 64-bit versions are available in Clang and GCC as of GCC 4.3.0. @@ -259,6 +260,7 @@ inline void Store64(void *p, uint64_t v) { } // namespace big_endian +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_ENDIAN_H_ diff --git a/absl/base/internal/endian_test.cc b/absl/base/internal/endian_test.cc index 98a099e4..aa6b8496 100644 --- a/absl/base/internal/endian_test.cc +++ b/absl/base/internal/endian_test.cc @@ -24,6 +24,7 @@ #include "absl/base/config.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { const uint64_t kInitialNumber{0x0123456789abcdef}; @@ -260,4 +261,5 @@ TEST(EndianessTest, big_endian) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/exponential_biased.cc b/absl/base/internal/exponential_biased.cc index 7786c303..1b30c061 100644 --- a/absl/base/internal/exponential_biased.cc +++ b/absl/base/internal/exponential_biased.cc @@ -25,6 +25,7 @@ #include "absl/base/optimization.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // The algorithm generates a random number between 0 and 1 and applies the @@ -88,4 +89,5 @@ void ExponentialBiased::Initialize() { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/exponential_biased.h b/absl/base/internal/exponential_biased.h index 6701e695..94f79a33 100644 --- a/absl/base/internal/exponential_biased.h +++ b/absl/base/internal/exponential_biased.h @@ -17,9 +17,11 @@ #include +#include "absl/base/config.h" #include "absl/base/macros.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // ExponentialBiased provides a small and fast random number generator for a @@ -122,6 +124,7 @@ inline uint64_t ExponentialBiased::NextRandom(uint64_t rnd) { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_ diff --git a/absl/base/internal/exponential_biased_test.cc b/absl/base/internal/exponential_biased_test.cc index af003239..90a482d2 100644 --- a/absl/base/internal/exponential_biased_test.cc +++ b/absl/base/internal/exponential_biased_test.cc @@ -27,6 +27,7 @@ using ::testing::Ge; namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { MATCHER_P2(IsBetween, a, b, @@ -194,4 +195,5 @@ TEST(ExponentialBiasedTest, InitializationModes) { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/hide_ptr.h b/absl/base/internal/hide_ptr.h index cf8f4080..1dba8090 100644 --- a/absl/base/internal/hide_ptr.h +++ b/absl/base/internal/hide_ptr.h @@ -17,7 +17,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // Arbitrary value with high bits set. Xor'ing with it is unlikely @@ -42,6 +45,7 @@ inline T* UnhidePtr(uintptr_t hidden) { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_HIDE_PTR_H_ diff --git a/absl/base/internal/identity.h b/absl/base/internal/identity.h index 086447c6..a3154ed7 100644 --- a/absl/base/internal/identity.h +++ b/absl/base/internal/identity.h @@ -16,7 +16,10 @@ #ifndef ABSL_BASE_INTERNAL_IDENTITY_H_ #define ABSL_BASE_INTERNAL_IDENTITY_H_ +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace internal { template @@ -28,6 +31,7 @@ template using identity_t = typename identity::type; } // namespace internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_IDENTITY_H_ diff --git a/absl/base/internal/inline_variable_testing.h b/absl/base/internal/inline_variable_testing.h index 15dc481e..3856b9f8 100644 --- a/absl/base/internal/inline_variable_testing.h +++ b/absl/base/internal/inline_variable_testing.h @@ -18,6 +18,7 @@ #include "absl/base/internal/inline_variable.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace inline_variable_testing_internal { struct Foo { @@ -39,6 +40,7 @@ const int& get_int_a(); const int& get_int_b(); } // namespace inline_variable_testing_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INLINE_VARIABLE_TESTING_H_ diff --git a/absl/base/internal/invoke.h b/absl/base/internal/invoke.h index 44f13302..c4eceebd 100644 --- a/absl/base/internal/invoke.h +++ b/absl/base/internal/invoke.h @@ -45,6 +45,7 @@ // top of this file for the API documentation. namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // The five classes below each implement one of the clauses from the definition @@ -180,6 +181,7 @@ InvokeT Invoke(F&& f, Args&&... args) { std::forward(args)...); } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_INVOKE_H_ diff --git a/absl/base/internal/low_level_alloc.cc b/absl/base/internal/low_level_alloc.cc index a0638f9e..225abc24 100644 --- a/absl/base/internal/low_level_alloc.cc +++ b/absl/base/internal/low_level_alloc.cc @@ -63,6 +63,7 @@ #endif // __APPLE__ namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // A first-fit allocator with amortized logarithmic free() time. @@ -612,6 +613,7 @@ void *LowLevelAlloc::AllocWithArena(size_t request, Arena *arena) { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_LOW_LEVEL_ALLOC_MISSING diff --git a/absl/base/internal/low_level_alloc.h b/absl/base/internal/low_level_alloc.h index c98cdb30..db91951c 100644 --- a/absl/base/internal/low_level_alloc.h +++ b/absl/base/internal/low_level_alloc.h @@ -55,6 +55,7 @@ #include "absl/base/port.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { class LowLevelAlloc { @@ -119,6 +120,7 @@ class LowLevelAlloc { }; } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_ diff --git a/absl/base/internal/low_level_alloc_test.cc b/absl/base/internal/low_level_alloc_test.cc index 34a080cb..7abbbf9c 100644 --- a/absl/base/internal/low_level_alloc_test.cc +++ b/absl/base/internal/low_level_alloc_test.cc @@ -22,6 +22,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { namespace { @@ -149,6 +150,7 @@ static struct BeforeMain { } // namespace } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl int main(int argc, char *argv[]) { diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 0fcc8d3b..961cc981 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -28,6 +28,7 @@ extern "C" bool __google_disable_rescheduling(void); extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -100,6 +101,7 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ diff --git a/absl/base/internal/periodic_sampler.cc b/absl/base/internal/periodic_sampler.cc index 87c3c85a..520dabba 100644 --- a/absl/base/internal/periodic_sampler.cc +++ b/absl/base/internal/periodic_sampler.cc @@ -19,6 +19,7 @@ #include "absl/base/internal/exponential_biased.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { int64_t PeriodicSamplerBase::GetExponentialBiased(int period) noexcept { @@ -48,4 +49,5 @@ bool PeriodicSamplerBase::SubtleConfirmSample() noexcept { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/periodic_sampler.h b/absl/base/internal/periodic_sampler.h index 23879742..f8a86796 100644 --- a/absl/base/internal/periodic_sampler.h +++ b/absl/base/internal/periodic_sampler.h @@ -23,6 +23,7 @@ #include "absl/base/optimization.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // PeriodicSamplerBase provides the basic period sampler implementation. @@ -204,6 +205,7 @@ template std::atomic PeriodicSampler::period_(default_period); } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_ diff --git a/absl/base/internal/periodic_sampler_benchmark.cc b/absl/base/internal/periodic_sampler_benchmark.cc index 03759632..5ad469ce 100644 --- a/absl/base/internal/periodic_sampler_benchmark.cc +++ b/absl/base/internal/periodic_sampler_benchmark.cc @@ -16,6 +16,7 @@ #include "absl/base/internal/periodic_sampler.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { namespace { @@ -74,4 +75,5 @@ BENCHMARK(BM_PeriodicSampler_Disabled); } // namespace } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/periodic_sampler_test.cc b/absl/base/internal/periodic_sampler_test.cc index 29f4d24d..3b301e37 100644 --- a/absl/base/internal/periodic_sampler_test.cc +++ b/absl/base/internal/periodic_sampler_test.cc @@ -22,6 +22,7 @@ #include "absl/base/macros.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { namespace { @@ -172,4 +173,5 @@ TEST(PeriodicSamplerTest, SetGlobalPeriod) { } // namespace } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc index d20bf34e..d79c5486 100644 --- a/absl/base/internal/raw_logging.cc +++ b/absl/base/internal/raw_logging.cc @@ -182,6 +182,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line, } // namespace namespace absl { +ABSL_NAMESPACE_BEGIN namespace raw_logging_internal { void SafeWriteToStderr(const char *s, size_t len) { #if defined(ABSL_HAVE_SYSCALL_WRITE) @@ -232,4 +233,5 @@ void RegisterInternalLogFunction(InternalLogFunction func) { } } // namespace raw_logging_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h index 49c8dfbf..12145c48 100644 --- a/absl/base/internal/raw_logging.h +++ b/absl/base/internal/raw_logging.h @@ -93,6 +93,7 @@ ::absl::NormalizeLogSeverity(severity) namespace absl { +ABSL_NAMESPACE_BEGIN namespace raw_logging_internal { // Helper function to implement ABSL_RAW_LOG @@ -172,6 +173,7 @@ extern base_internal::AtomicHook internal_log_function; void RegisterInternalLogFunction(InternalLogFunction func); } // namespace raw_logging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_RAW_LOGGING_H_ diff --git a/absl/base/internal/scheduling_mode.h b/absl/base/internal/scheduling_mode.h index d5b4b7fd..8be5ab6d 100644 --- a/absl/base/internal/scheduling_mode.h +++ b/absl/base/internal/scheduling_mode.h @@ -18,7 +18,10 @@ #ifndef ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_ #define ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_ +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // Used to describe how a thread may be scheduled. Typically associated with @@ -49,6 +52,7 @@ enum SchedulingMode { }; } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_ diff --git a/absl/base/internal/scoped_set_env.cc b/absl/base/internal/scoped_set_env.cc index 3ac3f68d..8a934cb5 100644 --- a/absl/base/internal/scoped_set_env.cc +++ b/absl/base/internal/scoped_set_env.cc @@ -23,6 +23,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { namespace { @@ -76,4 +77,5 @@ ScopedSetEnv::~ScopedSetEnv() { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/scoped_set_env.h b/absl/base/internal/scoped_set_env.h index 855b22fd..19ec7b5d 100644 --- a/absl/base/internal/scoped_set_env.h +++ b/absl/base/internal/scoped_set_env.h @@ -19,7 +19,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { class ScopedSetEnv { @@ -36,6 +39,7 @@ class ScopedSetEnv { }; } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_ diff --git a/absl/base/internal/spinlock.cc b/absl/base/internal/spinlock.cc index 7354438f..8dd8dab9 100644 --- a/absl/base/internal/spinlock.cc +++ b/absl/base/internal/spinlock.cc @@ -54,6 +54,7 @@ // holder to acquire the lock. There may be outstanding waiter(s). namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { ABSL_CONST_INIT static base_internal::AtomicHook *w, uint32_t value, int loop, int SpinLockSuggestedDelayNS(int loop); } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl // In some build configurations we pass --detect-odr-violations to the diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc index 68d4266b..7945322f 100644 --- a/absl/base/internal/sysinfo.cc +++ b/absl/base/internal/sysinfo.cc @@ -55,6 +55,7 @@ #include "absl/base/internal/unscaledcycleclock.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { static once_flag init_system_info_once; @@ -409,4 +410,5 @@ pid_t GetTID() { #endif } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/sysinfo.h b/absl/base/internal/sysinfo.h index 93356d80..7246d5dd 100644 --- a/absl/base/internal/sysinfo.h +++ b/absl/base/internal/sysinfo.h @@ -33,6 +33,7 @@ #include "absl/base/port.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // Nominal core processor cycles per second of each processor. This is _not_ @@ -59,6 +60,7 @@ using pid_t = uint32_t; pid_t GetTID(); } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_SYSINFO_H_ diff --git a/absl/base/internal/sysinfo_test.cc b/absl/base/internal/sysinfo_test.cc index 82bbcc2b..cdec9b6a 100644 --- a/absl/base/internal/sysinfo_test.cc +++ b/absl/base/internal/sysinfo_test.cc @@ -28,6 +28,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { namespace { @@ -95,4 +96,5 @@ TEST(SysinfoTest, LinuxGetTID) { } // namespace } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc index 0ea159c5..6a28f246 100644 --- a/absl/base/internal/thread_identity.cc +++ b/absl/base/internal/thread_identity.cc @@ -28,6 +28,7 @@ #include "absl/base/internal/spinlock.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { #if ABSL_THREAD_IDENTITY_MODE != ABSL_THREAD_IDENTITY_MODE_USE_CPP11 @@ -135,4 +136,5 @@ ThreadIdentity* CurrentThreadIdentityIfPresent() { #endif } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h index 7cbce9cc..a1aa45ff 100644 --- a/absl/base/internal/thread_identity.h +++ b/absl/base/internal/thread_identity.h @@ -33,6 +33,7 @@ #include "absl/base/internal/per_thread_tls.h" namespace absl { +ABSL_NAMESPACE_BEGIN struct SynchLocksHeld; struct SynchWaitParams; @@ -243,6 +244,7 @@ inline ThreadIdentity* CurrentThreadIdentityIfPresent() { #endif } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_ diff --git a/absl/base/internal/thread_identity_test.cc b/absl/base/internal/thread_identity_test.cc index 13bfbe3b..3685779c 100644 --- a/absl/base/internal/thread_identity_test.cc +++ b/absl/base/internal/thread_identity_test.cc @@ -25,6 +25,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { namespace { @@ -123,4 +124,5 @@ TEST(ThreadIdentityTest, ReusedThreadIdentityMutexTest) { } // namespace } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/throw_delegate.cc b/absl/base/internal/throw_delegate.cc index 8e928b8a..c055f75d 100644 --- a/absl/base/internal/throw_delegate.cc +++ b/absl/base/internal/throw_delegate.cc @@ -22,6 +22,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { namespace { @@ -103,4 +104,5 @@ void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); } void ThrowStdBadAlloc() { Throw(std::bad_alloc()); } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/throw_delegate.h b/absl/base/internal/throw_delegate.h index 03c700b5..075f5272 100644 --- a/absl/base/internal/throw_delegate.h +++ b/absl/base/internal/throw_delegate.h @@ -19,7 +19,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // Helper functions that allow throwing exceptions consistently from anywhere. @@ -66,6 +69,7 @@ namespace base_internal { // [[noreturn]] void ThrowStdBadArrayNewLength(); } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_THROW_DELEGATE_H_ diff --git a/absl/base/internal/unaligned_access.h b/absl/base/internal/unaligned_access.h index 2cf7c1d4..6be56c86 100644 --- a/absl/base/internal/unaligned_access.h +++ b/absl/base/internal/unaligned_access.h @@ -18,9 +18,11 @@ #define ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_ #include + #include #include "absl/base/attributes.h" +#include "absl/base/config.h" // unaligned APIs @@ -56,6 +58,7 @@ void __sanitizer_unaligned_store64(void *p, uint64_t v); } // extern "C" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { inline uint16_t UnalignedLoad16(const void *p) { @@ -83,6 +86,7 @@ inline void UnalignedStore64(void *p, uint64_t v) { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \ @@ -102,6 +106,7 @@ inline void UnalignedStore64(void *p, uint64_t v) { #else namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { inline uint16_t UnalignedLoad16(const void *p) { @@ -129,6 +134,7 @@ inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); } inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \ diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc index 593762bc..a32936ae 100644 --- a/absl/base/internal/unscaledcycleclock.cc +++ b/absl/base/internal/unscaledcycleclock.cc @@ -27,6 +27,7 @@ #include "absl/base/internal/sysinfo.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { #if defined(__i386__) @@ -96,6 +97,7 @@ double UnscaledCycleClock::Frequency() { #endif } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USE_UNSCALED_CYCLECLOCK diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h index 2d361e96..cdce9bf8 100644 --- a/absl/base/internal/unscaledcycleclock.h +++ b/absl/base/internal/unscaledcycleclock.h @@ -86,6 +86,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { class UnscaledCycleClockWrapperForGetCurrentTime; } // namespace time_internal @@ -115,6 +116,7 @@ class UnscaledCycleClock { }; } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USE_UNSCALED_CYCLECLOCK diff --git a/absl/base/invoke_test.cc b/absl/base/invoke_test.cc index 9074443b..6aa613c9 100644 --- a/absl/base/invoke_test.cc +++ b/absl/base/invoke_test.cc @@ -25,6 +25,7 @@ #include "absl/strings/str_cat.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { namespace { @@ -218,4 +219,5 @@ TEST(InvokeTest, SfinaeFriendly) { } // namespace } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/log_severity.cc b/absl/base/log_severity.cc index 02a2a485..72312afd 100644 --- a/absl/base/log_severity.cc +++ b/absl/base/log_severity.cc @@ -17,9 +17,11 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN std::ostream& operator<<(std::ostream& os, absl::LogSeverity s) { if (s == absl::NormalizeLogSeverity(s)) return os << absl::LogSeverityName(s); return os << "absl::LogSeverity(" << static_cast(s) << ")"; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h index f5dc7d26..e247c4a9 100644 --- a/absl/base/log_severity.h +++ b/absl/base/log_severity.h @@ -19,8 +19,10 @@ #include #include "absl/base/attributes.h" +#include "absl/base/config.h" namespace absl { +ABSL_NAMESPACE_BEGIN // Four severity levels are defined. Logging APIs should terminate the program // when a message is logged at severity `kFatal`; the other levels have no @@ -79,6 +81,7 @@ constexpr absl::LogSeverity NormalizeLogSeverity(int s) { // unspecified; do not rely on it. std::ostream& operator<<(std::ostream& os, absl::LogSeverity s); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_ diff --git a/absl/base/macros.h b/absl/base/macros.h index d414dcac..7565f022 100644 --- a/absl/base/macros.h +++ b/absl/base/macros.h @@ -44,12 +44,14 @@ (sizeof(::absl::macros_internal::ArraySizeHelper(array))) namespace absl { +ABSL_NAMESPACE_BEGIN namespace macros_internal { // Note: this internal template function declaration is used by ABSL_ARRAYSIZE. // The function doesn't need a definition, as we only use its type. template auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; } // namespace macros_internal +ABSL_NAMESPACE_END } // namespace absl // kLinkerInitialized @@ -73,11 +75,13 @@ auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; // // Invocation // static MyClass my_global(absl::base_internal::kLinkerInitialized); namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { enum LinkerInitialized { kLinkerInitialized = 0, }; } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl // ABSL_FALLTHROUGH_INTENDED diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc index 84fc4dac..08f61ba8 100644 --- a/absl/base/spinlock_test_common.cc +++ b/absl/base/spinlock_test_common.cc @@ -36,6 +36,7 @@ constexpr int32_t kNumThreads = 10; constexpr int32_t kIters = 1000; namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // This is defined outside of anonymous namespace so that it can be @@ -266,4 +267,5 @@ TEST(SpinLockWithThreads, DoesNotDeadlock) { } // namespace } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h index f98af9f9..5f51c0c2 100644 --- a/absl/base/thread_annotations.h +++ b/absl/base/thread_annotations.h @@ -34,6 +34,7 @@ #ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_ #define ABSL_BASE_THREAD_ANNOTATIONS_H_ +#include "absl/base/config.h" // TODO(mbonadei): Remove after the backward compatibility period. #include "absl/base/internal/thread_annotations.h" // IWYU pragma: export @@ -256,6 +257,7 @@ #define ABSL_TS_UNCHECKED_READ(x) absl::base_internal::ts_unchecked_read(x) namespace absl { +ABSL_NAMESPACE_BEGIN namespace base_internal { // Takes a reference to a guarded data member, and returns an unguarded @@ -272,6 +274,7 @@ inline T& ts_unchecked_read(T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS { } } // namespace base_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_THREAD_ANNOTATIONS_H_ diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc index 181c35c6..dc12e32f 100644 --- a/absl/flags/internal/usage.cc +++ b/absl/flags/internal/usage.cc @@ -200,7 +200,7 @@ void FlagHelpHumanReadable(const flags_internal::CommandLineFlag& flag, FlagHelpPrettyPrinter printer(80, out); // Max line length is 80. // Flag name. - printer.Write(absl::StrCat("-", flag.Name())); + printer.Write(absl::StrCat("--", flag.Name())); // Flag help. printer.Write(absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true); diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc index d15e4484..1e9ffdf7 100644 --- a/absl/flags/internal/usage_test.cc +++ b/absl/flags/internal/usage_test.cc @@ -111,7 +111,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) { flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); EXPECT_EQ( test_buf.str(), - R"( -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); + R"( --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); default: 101; )"); } @@ -123,7 +123,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) { flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); EXPECT_EQ( test_buf.str(), - R"( -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); + R"( --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); default: false; )"); } @@ -135,7 +135,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) { flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); EXPECT_EQ( test_buf.str(), - R"( -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); + R"( --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); default: 1.03; )"); } @@ -147,7 +147,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) { flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); EXPECT_EQ( test_buf.str(), - R"( -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); + R"( --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); default: 1000000000000004; )"); } @@ -159,7 +159,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) { flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable); EXPECT_EQ( test_buf.str(), - R"( -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); + R"( --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); default: UDT{}; )"); } @@ -171,17 +171,17 @@ TEST_F(UsageReportingTest, TestFlagsHelpHRF) { R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: - -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); + --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); default: 101; - -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); + --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); default: false; - -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); + --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); default: 1.03; - -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); + --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); default: 1000000000000004; - -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); + --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); default: UDT{}; - -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. + --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. Some more help. Even more long long long long long long long long long long long long help @@ -247,17 +247,17 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpshort) { R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: - -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); + --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); default: 101; - -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); + --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); default: false; - -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); + --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); default: 1.03; - -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); + --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); default: 1000000000000004; - -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); + --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); default: UDT{}; - -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. + --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. Some more help. Even more long long long long long long long long long long long long help @@ -276,17 +276,17 @@ TEST_F(UsageReportingTest, TestUsageFlag_help) { R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: - -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); + --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); default: 101; - -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); + --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); default: false; - -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); + --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); default: 1.03; - -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); + --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); default: 1000000000000004; - -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); + --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); default: UDT{}; - -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. + --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. Some more help. Even more long long long long long long long long long long long long help @@ -307,17 +307,17 @@ TEST_F(UsageReportingTest, TestUsageFlag_helppackage) { R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: - -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); + --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); default: 101; - -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); + --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); default: false; - -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); + --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); default: 1.03; - -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); + --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); default: 1000000000000004; - -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); + --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); default: UDT{}; - -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. + --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. Some more help. Even more long long long long long long long long long long long long help @@ -372,17 +372,17 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpon) { R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: - -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); + --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); default: 101; - -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); + --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message); default: false; - -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); + --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message); default: 1.03; - -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); + --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message); default: 1000000000000004; - -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); + --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message); default: UDT{}; - -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. + --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message. Some more help. Even more long long long long long long long long long long long long help diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index 79416cc8..a209a927 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -18,8 +18,6 @@ #include "absl/strings/internal/str_format/extension.h" #include "absl/strings/string_view.h" -class CordReader; - namespace absl { class Cord; @@ -67,8 +65,7 @@ ConvertResult FormatConvertImpl(const char* v, FormatSinkImpl* sink); template ::value>::type* = nullptr, - class AbslCordReader = ::CordReader> + std::is_same::value>::type* = nullptr> ConvertResult FormatConvertImpl(const AbslCord& value, ConversionSpec conv, FormatSinkImpl* sink) { @@ -90,11 +87,17 @@ ConvertResult FormatConvertImpl(const AbslCord& value, if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' '); - string_view piece; - for (AbslCordReader reader(value); - to_write > 0 && reader.ReadFragment(&piece); to_write -= piece.size()) { - if (piece.size() > to_write) piece.remove_suffix(piece.size() - to_write); + for (string_view piece : value.Chunks()) { + if (piece.size() > to_write) { + piece.remove_suffix(piece.size() - to_write); + to_write = 0; + } else { + to_write -= piece.size(); + } sink->Append(piece); + if (to_write == 0) { + break; + } } if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' '); diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h index 5e15ca40..7a0d6f50 100644 --- a/absl/strings/numbers.h +++ b/absl/strings/numbers.h @@ -54,18 +54,20 @@ namespace absl { // SimpleAtoi() // -// Converts the given string into an integer value, returning `true` if -// successful. The string must reflect a base-10 integer (optionally followed or -// preceded by ASCII whitespace) whose value falls within the range of the -// integer type. If any errors are encountered, this function returns `false`, -// leaving `out` in an unspecified state. +// Converts the given string (optionally followed or preceded by ASCII +// whitespace) into an integer value, returning `true` if successful. The string +// must reflect a base-10 integer whose value falls within the range of the +// integer type (optionally preceded by a `+` or `-`). If any errors are +// encountered, this function returns `false`, leaving `out` in an unspecified +// state. template ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out); // SimpleAtof() // // Converts the given string (optionally followed or preceded by ASCII -// whitespace) into a float, which may be rounded on overflow or underflow. +// whitespace) into a float, which may be rounded on overflow or underflow, +// returning `true` if successful. // See https://en.cppreference.com/w/c/string/byte/strtof for details about the // allowed formats for `str`, except SimpleAtof() is locale-independent and will // always use the "C" locale. If any errors are encountered, this function @@ -75,7 +77,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out); // SimpleAtod() // // Converts the given string (optionally followed or preceded by ASCII -// whitespace) into a double, which may be rounded on overflow or underflow. +// whitespace) into a double, which may be rounded on overflow or underflow, +// returning `true` if successful. // See https://en.cppreference.com/w/c/string/byte/strtof for details about the // allowed formats for `str`, except SimpleAtod is locale-independent and will // always use the "C" locale. If any errors are encountered, this function -- cgit v1.2.3 From a8b03d90e0afe03fefa16d4a871ece344a5d52ad Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 4 Jun 2020 14:05:55 -0700 Subject: Export of internal Abseil changes -- 5b9d5ce21074c0541432555d383d1b9c5898b553 by Gennadiy Rozental : Convert FlagSaver into public API PiperOrigin-RevId: 314799739 -- 5f796c9862b1177f161f4b10fe1a84698ebbb5cf by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 314786474 -- 67f2ae0ac5ae73bcd9d57a058ac4fea8fc1243ba by Gennadiy Rozental : Makes sure stacktrace_generic is only used with glibc. Fixes #701 PiperOrigin-RevId: 314726944 -- efb1ef3636b0698b79d3ee3590f12c4dff32a3cb by Samuel Benzaquen : Take the bits into account when reserving the space for the operation, not just the exponent. PiperOrigin-RevId: 314622744 GitOrigin-RevId: 5b9d5ce21074c0541432555d383d1b9c5898b553 Change-Id: I080a5e333e2dc1545b5aa0417882f7ac7116a20c --- absl/base/internal/low_level_scheduling.h | 5 +++ absl/debugging/internal/stacktrace_config.h | 2 +- absl/flags/commandlineflag_test.cc | 4 +-- absl/flags/flag_test.cc | 2 +- absl/flags/internal/registry.h | 25 -------------- absl/flags/internal/usage_test.cc | 2 +- absl/flags/parse_test.cc | 2 +- absl/flags/reflection.cc | 21 +++--------- absl/flags/reflection.h | 38 ++++++++++++++++++++++ absl/flags/reflection_test.cc | 4 +-- absl/strings/internal/str_format/convert_test.cc | 6 ++++ .../internal/str_format/float_conversion.cc | 12 +++---- absl/synchronization/mutex.cc | 7 ++++ 13 files changed, 75 insertions(+), 55 deletions(-) (limited to 'absl/base/internal/low_level_scheduling.h') diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 961cc981..7c52d48c 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -29,6 +29,9 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN +class CondVar; +class Mutex; + namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -77,6 +80,8 @@ class SchedulingGuard { }; // Access to SchedulingGuard is explicitly white-listed. + friend class absl::CondVar; + friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h index 8caa97c0..d5cc1740 100644 --- a/absl/debugging/internal/stacktrace_config.h +++ b/absl/debugging/internal/stacktrace_config.h @@ -61,7 +61,7 @@ # elif defined(__aarch64__) #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_aarch64-inl.inc" -# elif defined(__arm__) +#elif defined(__arm__) && defined(__GLIBC__) // Note: When using glibc this may require -funwind-tables to function properly. #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_generic-inl.inc" diff --git a/absl/flags/commandlineflag_test.cc b/absl/flags/commandlineflag_test.cc index cc8eae91..c5afff61 100644 --- a/absl/flags/commandlineflag_test.cc +++ b/absl/flags/commandlineflag_test.cc @@ -47,7 +47,7 @@ class CommandLineFlagTest : public testing::Test { absl::SetFlagsUsageConfig(default_config); } - void SetUp() override { flag_saver_ = absl::make_unique(); } + void SetUp() override { flag_saver_ = absl::make_unique(); } void TearDown() override { flag_saver_.reset(); } private: @@ -60,7 +60,7 @@ class CommandLineFlagTest : public testing::Test { return std::string(fname); } - std::unique_ptr flag_saver_; + std::unique_ptr flag_saver_; }; TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) { diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc index 0c88e24a..2eb2ba71 100644 --- a/absl/flags/flag_test.cc +++ b/absl/flags/flag_test.cc @@ -81,7 +81,7 @@ class FlagTest : public testing::Test { #endif return std::string(fname); } - flags::FlagSaver flag_saver_; + absl::FlagSaver flag_saver_; }; struct S1 { diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h index 1e655a3e..c72eebe2 100644 --- a/absl/flags/internal/registry.h +++ b/absl/flags/internal/registry.h @@ -89,31 +89,6 @@ inline bool RetiredFlag(const char* flag_name) { return flags_internal::Retire(flag_name, base_internal::FastTypeId()); } -//----------------------------------------------------------------------------- -// Saves the states (value, default value, whether the user has set -// the flag, registered validators, etc) of all flags, and restores -// them when the FlagSaver is destroyed. -// -// This class is thread-safe. However, its destructor writes to -// exactly the set of flags that have changed value during its -// lifetime, so concurrent _direct_ access to those flags -// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe. - -class FlagSaver { - public: - FlagSaver(); - ~FlagSaver(); - - FlagSaver(const FlagSaver&) = delete; - void operator=(const FlagSaver&) = delete; - - // Prevents saver from restoring the saved state of flags. - void Ignore(); - - private: - class FlagSaverImpl* impl_; // we use pimpl here to keep API steady -}; - } // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc index 46f85b55..6e583fbe 100644 --- a/absl/flags/internal/usage_test.cc +++ b/absl/flags/internal/usage_test.cc @@ -89,7 +89,7 @@ class UsageReportingTest : public testing::Test { } private: - flags::FlagSaver flag_saver_; + absl::FlagSaver flag_saver_; }; // -------------------------------------------------------------------- diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc index 1ab87690..67ae8aad 100644 --- a/absl/flags/parse_test.cc +++ b/absl/flags/parse_test.cc @@ -208,7 +208,7 @@ using testing::ElementsAreArray; class ParseTest : public testing::Test { private: - flags::FlagSaver flag_saver_; + absl::FlagSaver flag_saver_; }; // -------------------------------------------------------------------- diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc index 02bb6c2e..5fc945f2 100644 --- a/absl/flags/reflection.cc +++ b/absl/flags/reflection.cc @@ -65,7 +65,8 @@ class FlagRegistry { static FlagRegistry& GlobalRegistry(); // returns a singleton registry private: - friend class FlagSaverImpl; // reads all the flags in order to copy them + friend class flags_internal::FlagSaverImpl; // reads all the flags in order + // to copy them friend void ForEachFlagUnlocked( std::function visitor); @@ -249,15 +250,6 @@ bool Retire(const char* name, FlagFastTypeId type_id) { // -------------------------------------------------------------------- -// FlagSaver -// FlagSaverImpl -// This class stores the states of all flags at construct time, -// and restores all flags to that state at destruct time. -// Its major implementation challenge is that it never modifies -// pointers in the 'main' registry, so global FLAG_* vars always -// point to the right place. -// -------------------------------------------------------------------- - class FlagSaverImpl { public: FlagSaverImpl() = default; @@ -288,11 +280,10 @@ class FlagSaverImpl { backup_registry_; }; -FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); } +} // namespace flags_internal -void FlagSaver::Ignore() { - delete impl_; - impl_ = nullptr; +FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) { + impl_->SaveFromRegistry(); } FlagSaver::~FlagSaver() { @@ -304,8 +295,6 @@ FlagSaver::~FlagSaver() { // -------------------------------------------------------------------- -} // namespace flags_internal - CommandLineFlag* FindCommandLineFlag(absl::string_view name) { if (name.empty()) return nullptr; flags_internal::FlagRegistry& registry = diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h index e8e24f68..045f9784 100644 --- a/absl/flags/reflection.h +++ b/absl/flags/reflection.h @@ -31,6 +31,9 @@ namespace absl { ABSL_NAMESPACE_BEGIN +namespace flags_internal { +class FlagSaverImpl; +} // namespace flags_internal // FindCommandLineFlag() // @@ -39,6 +42,41 @@ ABSL_NAMESPACE_BEGIN // 'retired' flag is specified. CommandLineFlag* FindCommandLineFlag(absl::string_view name); +//------------------------------------------------------------------------------ +// FlagSaver +//------------------------------------------------------------------------------ +// +// A FlagSaver object stores the state of flags in the scope where the FlagSaver +// is defined, allowing modification of those flags within that scope and +// automatic restoration of the flags to their previous state upon leaving the +// scope. +// +// A FlagSaver can be used within tests to temporarily change the test +// environment and restore the test case to its previous state. +// +// Example: +// +// void MyFunc() { +// absl::FlagSaver fs; +// ... +// absl::SetFlag(FLAGS_myFlag, otherValue); +// ... +// } // scope of FlagSaver left, flags return to previous state +// +// This class is thread-safe. + +class FlagSaver { + public: + FlagSaver(); + ~FlagSaver(); + + FlagSaver(const FlagSaver&) = delete; + void operator=(const FlagSaver&) = delete; + + private: + flags_internal::FlagSaverImpl* impl_; +}; + //----------------------------------------------------------------------------- ABSL_NAMESPACE_END diff --git a/absl/flags/reflection_test.cc b/absl/flags/reflection_test.cc index 2a137bf7..9781e597 100644 --- a/absl/flags/reflection_test.cc +++ b/absl/flags/reflection_test.cc @@ -34,11 +34,11 @@ namespace flags = absl::flags_internal; class ReflectionTest : public testing::Test { protected: - void SetUp() override { flag_saver_ = absl::make_unique(); } + void SetUp() override { flag_saver_ = absl::make_unique(); } void TearDown() override { flag_saver_.reset(); } private: - std::unique_ptr flag_saver_; + std::unique_ptr flag_saver_; }; // -------------------------------------------------------------------- diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 20c6229f..0e8535c2 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -764,6 +764,12 @@ TEST_F(FormatConvertTest, LongDouble) { } } + // Regression tests + // + // Using a string literal because not all platforms support hex literals or it + // might be out of range. + doubles.push_back(std::strtold("-0xf.ffffffb5feafffbp-16324L", nullptr)); + for (const char *fmt : kFormats) { for (char f : {'f', 'F', // 'g', 'G', // diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index a761a5a5..10e46954 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -224,13 +224,13 @@ class FractionalDigitGenerator { // This function will allocate enough stack space to perform the conversion. static void RunConversion( uint128 v, int exp, absl::FunctionRef f) { + using Limits = std::numeric_limits; assert(-exp < 0); - assert(-exp >= std::numeric_limits::min_exponent - 128); - static_assert( - StackArray::kMaxCapacity >= - (128 - std::numeric_limits::min_exponent + 31) / 32, - ""); - StackArray::RunWithCapacity((exp + 31) / 32, + assert(-exp >= Limits::min_exponent - 128); + static_assert(StackArray::kMaxCapacity >= + (Limits::digits + 128 - Limits::min_exponent + 31) / 32, + ""); + StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32, [=](absl::Span input) { f(FractionalDigitGenerator(input, v, exp)); }); diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 1f8a696e..36c93d5f 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -58,6 +58,7 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; +using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -1108,6 +1109,7 @@ void Mutex::TryRemove(PerThreadSynch *s) { // on the mutex queue. In this case, remove "s" from the queue and return // true, otherwise return false. ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) { if (!DecrementSynchSem(this, s, s->waitp->timeout)) { // After a timeout, we go into a spin loop until we remove ourselves @@ -1897,6 +1899,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -2016,6 +2019,7 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2331,6 +2335,7 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2429,6 +2434,7 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2589,6 +2595,7 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { + SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; -- cgit v1.2.3 From 2eba343b51e0923cd3fb919a6abd6120590fc059 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 9 Jun 2020 08:17:12 -0700 Subject: Export of internal Abseil changes -- baf626d27ff1547776745f3b601cc42f703d4bdf by Greg Falcon : Import of CCTZ from GitHub. PiperOrigin-RevId: 315486679 -- 39d4e7f9214c5a74e4ee4b8a7f4af26479925029 by Gennadiy Rozental : Avoid order dependant test cases. PiperOrigin-RevId: 315327948 -- 8feb187703a28bb0c5cfc5dd6091e3faa90a8e61 by Gennadiy Rozental : Avoid order dependant test cases. PiperOrigin-RevId: 315317018 -- cffd8fddad15908ec9de7f21f65b20528972e3fa by Gennadiy Rozental : Avoid order dependant test cases. PiperOrigin-RevId: 315311587 -- 48997a0ceb231b75c14eb4b1eb3b66af69e49f42 by Tom Manshreck : Nit: remove extra "the" PiperOrigin-RevId: 314959763 -- 9516f44a4b5d3055427c95e80c8c04a6321e4221 by Gennadiy Rozental : Import of CCTZ from GitHub. PiperOrigin-RevId: 314925147 -- 4f8691d74a4eb42ed03ef29c9588a01b78829941 by Abseil Team : Uninclude util/bits/bits.h PiperOrigin-RevId: 314858384 -- 02b42a8ec5e5561b29b4e5f93cc1482c3c72ef2d by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 314855667 -- 146013d69dabafbe2030e23ced7b741d9e8d417c by Gennadiy Rozental : Uninclude util/bits/bits.h PiperOrigin-RevId: 314838927 GitOrigin-RevId: baf626d27ff1547776745f3b601cc42f703d4bdf Change-Id: I2602286fb13cf35a88bdd80fe0b44974d4388d46 --- absl/base/internal/low_level_scheduling.h | 5 - absl/flags/commandlineflag_test.cc | 12 +- absl/flags/internal/program_name_test.cc | 4 +- absl/flags/parse_test.cc | 4 + absl/strings/str_format.h | 2 +- absl/synchronization/mutex.cc | 7 -- absl/time/internal/cctz/src/time_zone_format.cc | 124 +++++++++++++++++---- .../internal/cctz/src/time_zone_format_test.cc | 88 +++++++++++++++ absl/time/internal/cctz/src/time_zone_impl.cc | 34 +++--- 9 files changed, 215 insertions(+), 65 deletions(-) (limited to 'absl/base/internal/low_level_scheduling.h') diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 7c52d48c..961cc981 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -29,9 +29,6 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN -class CondVar; -class Mutex; - namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -80,8 +77,6 @@ class SchedulingGuard { }; // Access to SchedulingGuard is explicitly white-listed. - friend class absl::CondVar; - friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; diff --git a/absl/flags/commandlineflag_test.cc b/absl/flags/commandlineflag_test.cc index c5afff61..585db4ba 100644 --- a/absl/flags/commandlineflag_test.cc +++ b/absl/flags/commandlineflag_test.cc @@ -34,6 +34,10 @@ ABSL_FLAG(std::string, string_flag, "dflt", absl::StrCat("string_flag", " help")); ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help"); +// These are only used to test default values. +ABSL_FLAG(int, int_flag2, 201, ""); +ABSL_FLAG(std::string, string_flag2, "dflt", ""); + namespace { namespace flags = absl::flags_internal; @@ -94,15 +98,15 @@ TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) { // -------------------------------------------------------------------- TEST_F(CommandLineFlagTest, TestValueAccessMethods) { - absl::SetFlag(&FLAGS_int_flag, 301); - auto* flag_01 = absl::FindCommandLineFlag("int_flag"); + absl::SetFlag(&FLAGS_int_flag2, 301); + auto* flag_01 = absl::FindCommandLineFlag("int_flag2"); ASSERT_TRUE(flag_01); EXPECT_EQ(flag_01->CurrentValue(), "301"); EXPECT_EQ(flag_01->DefaultValue(), "201"); - absl::SetFlag(&FLAGS_string_flag, "new_str_value"); - auto* flag_02 = absl::FindCommandLineFlag("string_flag"); + absl::SetFlag(&FLAGS_string_flag2, "new_str_value"); + auto* flag_02 = absl::FindCommandLineFlag("string_flag2"); ASSERT_TRUE(flag_02); EXPECT_EQ(flag_02->CurrentValue(), "new_str_value"); diff --git a/absl/flags/internal/program_name_test.cc b/absl/flags/internal/program_name_test.cc index 269142f2..aff9f631 100644 --- a/absl/flags/internal/program_name_test.cc +++ b/absl/flags/internal/program_name_test.cc @@ -25,7 +25,7 @@ namespace { namespace flags = absl::flags_internal; -TEST(FlagsPathUtilTest, TestInitialProgamName) { +TEST(FlagsPathUtilTest, TestProgamNameInterfaces) { flags::SetProgramInvocationName("absl/flags/program_name_test"); std::string program_name = flags::ProgramInvocationName(); for (char& c : program_name) @@ -43,9 +43,7 @@ TEST(FlagsPathUtilTest, TestInitialProgamName) { EXPECT_TRUE(absl::EndsWith(program_name, expect_name)) << program_name; EXPECT_EQ(flags::ShortProgramInvocationName(), expect_basename); -} -TEST(FlagsPathUtilTest, TestProgamNameInterfaces) { flags::SetProgramInvocationName("a/my_test"); EXPECT_EQ(flags::ProgramInvocationName(), "a/my_test"); diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc index 67ae8aad..d35a6e47 100644 --- a/absl/flags/parse_test.cc +++ b/absl/flags/parse_test.cc @@ -637,6 +637,10 @@ TEST_F(ParseTest, TestFlagfileInFlagfile) { "--flagfile=$0/parse_test.ff2", }; + GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}, + {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}}, + flagfile_flag); + const char* in_args1[] = { "testbin", GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}}, diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h index f833a80a..36bd84a3 100644 --- a/absl/strings/str_format.h +++ b/absl/strings/str_format.h @@ -19,7 +19,7 @@ // // The `str_format` library is a typesafe replacement for the family of // `printf()` string formatting routines within the `` standard library -// header. Like the `printf` family, the `str_format` uses a "format string" to +// header. Like the `printf` family, `str_format` uses a "format string" to // perform argument substitutions based on types. See the `FormatSpec` section // below for format string documentation. // diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 36c93d5f..1f8a696e 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -58,7 +58,6 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; -using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -1109,7 +1108,6 @@ void Mutex::TryRemove(PerThreadSynch *s) { // on the mutex queue. In this case, remove "s" from the queue and return // true, otherwise return false. ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) { - SchedulingGuard::ScopedDisable disable_rescheduling; while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) { if (!DecrementSynchSem(this, s, s->waitp->timeout)) { // After a timeout, we go into a spin loop until we remove ourselves @@ -1899,7 +1897,6 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { - SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -2019,7 +2016,6 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { - SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2335,7 +2331,6 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { - SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2434,7 +2429,6 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { - SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2595,7 +2589,6 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { - SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc index a4428632..2e02233c 100644 --- a/absl/time/internal/cctz/src/time_zone_format.cc +++ b/absl/time/internal/cctz/src/time_zone_format.cc @@ -67,6 +67,48 @@ char* strptime(const char* s, const char* fmt, std::tm* tm) { } #endif +// Convert a cctz::weekday to a tm_wday value (0-6, Sunday = 0). +int ToTmWday(weekday wd) { + switch (wd) { + case weekday::sunday: + return 0; + case weekday::monday: + return 1; + case weekday::tuesday: + return 2; + case weekday::wednesday: + return 3; + case weekday::thursday: + return 4; + case weekday::friday: + return 5; + case weekday::saturday: + return 6; + } + return 0; /*NOTREACHED*/ +} + +// Convert a tm_wday value (0-6, Sunday = 0) to a cctz::weekday. +weekday FromTmWday(int tm_wday) { + switch (tm_wday) { + case 0: + return weekday::sunday; + case 1: + return weekday::monday; + case 2: + return weekday::tuesday; + case 3: + return weekday::wednesday; + case 4: + return weekday::thursday; + case 5: + return weekday::friday; + case 6: + return weekday::saturday; + } + return weekday::sunday; /*NOTREACHED*/ +} + std::tm ToTM(const time_zone::absolute_lookup& al) { std::tm tm{}; tm.tm_sec = al.cs.second(); @@ -84,34 +126,19 @@ std::tm ToTM(const time_zone::absolute_lookup& al) { tm.tm_year = static_cast(al.cs.year() - 1900); } - switch (get_weekday(al.cs)) { - case weekday::sunday: - tm.tm_wday = 0; - break; - case weekday::monday: - tm.tm_wday = 1; - break; - case weekday::tuesday: - tm.tm_wday = 2; - break; - case weekday::wednesday: - tm.tm_wday = 3; - break; - case weekday::thursday: - tm.tm_wday = 4; - break; - case weekday::friday: - tm.tm_wday = 5; - break; - case weekday::saturday: - tm.tm_wday = 6; - break; - } + tm.tm_wday = ToTmWday(get_weekday(al.cs)); tm.tm_yday = get_yearday(al.cs) - 1; tm.tm_isdst = al.is_dst ? 1 : 0; return tm; } +// Returns the week of the year [0:53] given a civil day and the day on +// which weeks are defined to start. +int ToWeek(const civil_day& cd, weekday week_start) { + const civil_day d(cd.year() % 400, cd.month(), cd.day()); + return static_cast((d - prev_weekday(civil_year(d), week_start)) / 7); +} + const char kDigits[] = "0123456789"; // Formats a 64-bit integer in the given field width. Note that it is up @@ -355,7 +382,7 @@ std::string format(const std::string& format, const time_point& tp, if (cur == end || (cur - percent) % 2 == 0) continue; // Simple specifiers that we handle ourselves. - if (strchr("YmdeHMSzZs%", *cur)) { + if (strchr("YmdeUuWwHMSzZs%", *cur)) { if (cur - 1 != pending) { FormatTM(&result, std::string(pending, cur - 1), tm); } @@ -376,6 +403,22 @@ std::string format(const std::string& format, const time_point& tp, if (*cur == 'e' && *bp == '0') *bp = ' '; // for Windows result.append(bp, static_cast(ep - bp)); break; + case 'U': + bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::sunday)); + result.append(bp, static_cast(ep - bp)); + break; + case 'u': + bp = Format64(ep, 0, tm.tm_wday ? tm.tm_wday : 7); + result.append(bp, static_cast(ep - bp)); + break; + case 'W': + bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::monday)); + result.append(bp, static_cast(ep - bp)); + break; + case 'w': + bp = Format64(ep, 0, tm.tm_wday); + result.append(bp, static_cast(ep - bp)); + break; case 'H': bp = Format02d(ep, al.cs.hour()); result.append(bp, static_cast(ep - bp)); @@ -610,6 +653,17 @@ const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) { return dp; } +// Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday, +// and the day on which weeks are defined to start. +void FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) { + const civil_year y(*year % 400); + civil_day cd = prev_weekday(y, week_start); // week 0 + cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7); + *year += cd.year() - y.year(); + tm->tm_mon = cd.month() - 1; + tm->tm_mday = cd.day(); +} + } // namespace // Uses strptime(3) to parse the given input. Supports the same extended @@ -659,6 +713,8 @@ bool parse(const std::string& format, const std::string& input, const char* fmt = format.c_str(); // NUL terminated bool twelve_hour = false; bool afternoon = false; + int week_num = -1; + weekday week_start = weekday::sunday; bool saw_percent_s = false; std::int_fast64_t percent_s = 0; @@ -697,10 +753,27 @@ bool parse(const std::string& format, const std::string& input, case 'm': data = ParseInt(data, 2, 1, 12, &tm.tm_mon); if (data != nullptr) tm.tm_mon -= 1; + week_num = -1; continue; case 'd': case 'e': data = ParseInt(data, 2, 1, 31, &tm.tm_mday); + week_num = -1; + continue; + case 'U': + data = ParseInt(data, 0, 0, 53, &week_num); + week_start = weekday::sunday; + continue; + case 'W': + data = ParseInt(data, 0, 0, 53, &week_num); + week_start = weekday::monday; + continue; + case 'u': + data = ParseInt(data, 0, 1, 7, &tm.tm_wday); + if (data != nullptr) tm.tm_wday %= 7; + continue; + case 'w': + data = ParseInt(data, 0, 0, 6, &tm.tm_wday); continue; case 'H': data = ParseInt(data, 2, 0, 23, &tm.tm_hour); @@ -891,6 +964,9 @@ bool parse(const std::string& format, const std::string& input, year += 1900; } + // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number. + if (week_num != -1) FromWeek(week_num, week_start, &year, &tm); + const int month = tm.tm_mon + 1; civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc index 13a4227e..e625a839 100644 --- a/absl/time/internal/cctz/src/time_zone_format_test.cc +++ b/absl/time/internal/cctz/src/time_zone_format_test.cc @@ -679,6 +679,34 @@ TEST(Format, RFC1123Format) { // locale specific EXPECT_EQ("28 Jun 1977 09:08:07 -0700", format(RFC1123_no_wday, tp, tz)); } +TEST(Format, Week) { + const time_zone utc = utc_time_zone(); + + auto tp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("2017-01-7", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2017-00-0", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc); + EXPECT_EQ("2017-53-7", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2017-52-0", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("2018-00-1", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2018-01-1", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc); + EXPECT_EQ("2018-52-1", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2018-53-1", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("2019-00-2", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2019-00-2", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); + EXPECT_EQ("2019-52-2", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2019-52-2", format("%Y-%W-%w", tp, utc)); +} + // // Testing parse() // @@ -1395,6 +1423,66 @@ TEST(Parse, RFC3339Format) { EXPECT_EQ(tp, tp4); } +TEST(Parse, Week) { + const time_zone utc = utc_time_zone(); + time_point tp; + + auto exp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2017-01-7", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2017-00-0", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2017-53-7", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2017-52-0", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2018-00-1", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2018-01-1", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2018-52-1", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2018-53-1", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2019-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2019-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2019-52-2", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2019-52-2", utc, &tp)); + EXPECT_EQ(exp, tp); +} + +TEST(Parse, WeekYearShift) { + // %U/%W conversions with week values in {0, 52, 53} can slip + // into the previous/following calendar years. + const time_zone utc = utc_time_zone(); + time_point tp; + + auto exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2020-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2020-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2021, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2020-52-5", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp)); + EXPECT_EQ(exp, tp); +} + TEST(Parse, MaxRange) { const time_zone utc = utc_time_zone(); time_point tp; diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc index 030ae0e1..f34e3aec 100644 --- a/absl/time/internal/cctz/src/time_zone_impl.cc +++ b/absl/time/internal/cctz/src/time_zone_impl.cc @@ -15,6 +15,7 @@ #include "time_zone_impl.h" #include +#include #include #include #include @@ -48,17 +49,16 @@ std::mutex& TimeZoneMutex() { time_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); } bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { - const time_zone::Impl* const utc_impl = UTCImpl(); + const Impl* const utc_impl = UTCImpl(); - // First check for UTC (which is never a key in time_zone_map). + // Check for UTC (which is never a key in time_zone_map). auto offset = seconds::zero(); if (FixedOffsetFromName(name, &offset) && offset == seconds::zero()) { *tz = time_zone(utc_impl); return true; } - // Then check, under a shared lock, whether the time zone has already - // been loaded. This is the common path. TODO: Move to shared_mutex. + // Check whether the time zone has already been loaded. { std::lock_guard lock(TimeZoneMutex()); if (time_zone_map != nullptr) { @@ -70,20 +70,15 @@ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { } } - // Now check again, under an exclusive lock. + // Load the new time zone (outside the lock). + std::unique_ptr new_impl(new Impl(name)); + + // Add the new time zone to the map. std::lock_guard lock(TimeZoneMutex()); if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName; const Impl*& impl = (*time_zone_map)[name]; - if (impl == nullptr) { - // The first thread in loads the new time zone. - Impl* new_impl = new Impl(name); - new_impl->zone_ = TimeZoneIf::Load(new_impl->name_); - if (new_impl->zone_ == nullptr) { - delete new_impl; // free the nascent Impl - impl = utc_impl; // and fallback to UTC - } else { - impl = new_impl; // install new time zone - } + if (impl == nullptr) { // this thread won any load race + impl = new_impl->zone_ ? new_impl.release() : utc_impl; } *tz = time_zone(impl); return impl != utc_impl; @@ -104,14 +99,11 @@ void time_zone::Impl::ClearTimeZoneMapTestOnly() { } } -time_zone::Impl::Impl(const std::string& name) : name_(name) {} +time_zone::Impl::Impl(const std::string& name) + : name_(name), zone_(TimeZoneIf::Load(name_)) {} const time_zone::Impl* time_zone::Impl::UTCImpl() { - static Impl* utc_impl = [] { - Impl* impl = new Impl("UTC"); - impl->zone_ = TimeZoneIf::Load(impl->name_); // never fails - return impl; - }(); + static const Impl* utc_impl = new Impl("UTC"); // never fails return utc_impl; } -- cgit v1.2.3 From b86fff162e15ad8ee534c25e58bf522330e8376d Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 24 Jun 2020 12:46:11 -0700 Subject: Export of internal Abseil changes -- 517dc7eba9878290fc93c6523dc6d6e2c49b8c1e by Abseil Team : Handle 'nan' in HumanReadableInt::ToInt64. PiperOrigin-RevId: 318121226 -- 4fa6103b46dbc1375d416810dba591ab4f4898d1 by Abseil Team : Promote `float`s to `double`s before formatting. This will bring StrFormat behavior more in line with that of sprintf. PiperOrigin-RevId: 318091841 -- e4083a4b64b077d8520ccd8e0ca90da24f4ea24d by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 318069900 -- ab24f60127db089bccaf5fb7d2d1967c76f34768 by Greg Falcon : Inclusive language fix: Stop using blacklist/whitelist terminology in Abseil. PiperOrigin-RevId: 317925379 -- 52b56a27a773ea7c10ea8fd456ed606b9d778947 by Abseil Team : Add test for floats and label tests for double properly. PiperOrigin-RevId: 317916380 -- 0f405960ab5b34d673244fda8bb9141c8f5c1a4f by Abseil Team : Remove the static initialization of global variables used by absl::Mutex as requested by Chromium PiperOrigin-RevId: 317911430 -- ce8cb49d8f4f68950fd111682657ba57d5a09ca0 by Abseil Team : Internal Change PiperOrigin-RevId: 317864956 -- a781948e09fb8406d21a494b2fa4f78edaf9c2ea by Abseil Team : Swap ABSL_DLL / ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES order to fix clang-cl builds. PiperOrigin-RevId: 317858053 -- 4ba197f0dd2cbf8f9b96cebffd878c8847d6ce8d by Gennadiy Rozental : Migrate use of annotation macros to ABSL namespaced names PiperOrigin-RevId: 317792057 GitOrigin-RevId: 517dc7eba9878290fc93c6523dc6d6e2c49b8c1e Change-Id: I1a0c04d01adbdc5106b68fd69c97c31f822e11dc --- absl/base/internal/low_level_alloc.cc | 2 +- absl/base/internal/low_level_scheduling.h | 7 +- absl/base/internal/raw_logging.cc | 4 +- absl/base/internal/raw_logging.h | 2 +- absl/base/internal/unscaledcycleclock.h | 6 +- absl/container/fixed_array.h | 16 ++- absl/debugging/symbolize_elf.inc | 4 +- absl/strings/internal/str_format/convert_test.cc | 158 ++++++++++++++------- .../internal/str_format/float_conversion.cc | 2 +- absl/strings/numbers_test.cc | 6 + absl/synchronization/internal/per_thread_sem.h | 2 +- absl/synchronization/mutex.cc | 68 +++++---- absl/types/BUILD.bazel | 1 - 13 files changed, 182 insertions(+), 96 deletions(-) (limited to 'absl/base/internal/low_level_scheduling.h') diff --git a/absl/base/internal/low_level_alloc.cc b/absl/base/internal/low_level_alloc.cc index 1bf94438..229ab916 100644 --- a/absl/base/internal/low_level_alloc.cc +++ b/absl/base/internal/low_level_alloc.cc @@ -598,7 +598,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { section.Leave(); result = &s->levels; } - ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request); + ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request); return result; } diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 961cc981..31261298 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -29,6 +29,9 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN +class CondVar; +class Mutex; + namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -76,7 +79,9 @@ class SchedulingGuard { bool disabled; }; - // Access to SchedulingGuard is explicitly white-listed. + // Access to SchedulingGuard is explicitly permitted. + friend class absl::CondVar; + friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc index 40cea550..ae8754c6 100644 --- a/absl/base/internal/raw_logging.cc +++ b/absl/base/internal/raw_logging.cc @@ -69,7 +69,7 @@ // TODO(gfalcon): We want raw-logging to work on as many platforms as possible. // Explicitly #error out when not ABSL_LOW_LEVEL_WRITE_SUPPORTED, except for a -// whitelisted set of platforms for which we expect not to be able to raw log. +// selected set of platforms for which we expect not to be able to raw log. ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook< absl::raw_logging_internal::LogPrefixHook> @@ -227,7 +227,7 @@ bool RawLoggingFullySupported() { #endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED } -ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES +ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL absl::base_internal::AtomicHook internal_log_function(DefaultInternalLog); diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h index 418d6c85..51551baf 100644 --- a/absl/base/internal/raw_logging.h +++ b/absl/base/internal/raw_logging.h @@ -170,7 +170,7 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity, const char* file, int line, const std::string& message); -ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES extern base_internal::AtomicHook< +ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook< InternalLogFunction> internal_log_function; diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h index cdce9bf8..82f2c87a 100644 --- a/absl/base/internal/unscaledcycleclock.h +++ b/absl/base/internal/unscaledcycleclock.h @@ -15,8 +15,8 @@ // UnscaledCycleClock // An UnscaledCycleClock yields the value and frequency of a cycle counter // that increments at a rate that is approximately constant. -// This class is for internal / whitelisted use only, you should consider -// using CycleClock instead. +// This class is for internal use only, you should consider using CycleClock +// instead. // // Notes: // The cycle counter frequency is not necessarily the core clock frequency. @@ -109,7 +109,7 @@ class UnscaledCycleClock { // value. static double Frequency(); - // Whitelisted friends. + // Allowed users friend class base_internal::CycleClock; friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime; friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency; diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index adf0dc80..e74802a4 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h @@ -428,9 +428,9 @@ class FixedArray { #endif // ADDRESS_SANITIZER private: - ADDRESS_SANITIZER_REDZONE(redzone_begin_); + ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_); alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])]; - ADDRESS_SANITIZER_REDZONE(redzone_end_); + ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_); }; class EmptyInlinedStorage { @@ -505,8 +505,10 @@ void FixedArray::NonEmptyInlinedStorage::AnnotateConstruct( typename FixedArray::size_type n) { #ifdef ADDRESS_SANITIZER if (!n) return; - ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n); - ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), RedzoneBegin()); + ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), + data() + n); + ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), + RedzoneBegin()); #endif // ADDRESS_SANITIZER static_cast(n); // Mark used when not in asan mode } @@ -516,8 +518,10 @@ void FixedArray::NonEmptyInlinedStorage::AnnotateDestruct( typename FixedArray::size_type n) { #ifdef ADDRESS_SANITIZER if (!n) return; - ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd()); - ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), data()); + ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, + RedzoneEnd()); + ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), + data()); #endif // ADDRESS_SANITIZER static_cast(n); // Mark used when not in asan mode } diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index c05424e0..ed77159e 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc @@ -1455,7 +1455,7 @@ bool GetFileMappingHint(const void **start, const void **end, uint64_t *offset, bool Symbolize(const void *pc, char *out, int out_size) { // Symbolization is very slow under tsan. - ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); SAFE_ASSERT(out_size >= 0); debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer(); const char *name = s->GetSymbol(pc); @@ -1474,7 +1474,7 @@ bool Symbolize(const void *pc, char *out, int out_size) { } } debugging_internal::FreeSymbolizer(s); - ANNOTATE_IGNORE_READS_AND_WRITES_END(); + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END(); return ok; } diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 0e8535c2..e37d0546 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -474,6 +474,57 @@ TEST_F(FormatConvertTest, Uint128) { } } +template +void TestWithMultipleFormatsHelper(const std::vector &floats) { + // Reserve the space to ensure we don't allocate memory in the output itself. + std::string str_format_result; + str_format_result.reserve(1 << 20); + std::string string_printf_result; + string_printf_result.reserve(1 << 20); + + const char *const kFormats[] = { + "%", "%.3", "%8.5", "%500", "%.5000", "%.60", "%.30", "%03", + "%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; + + for (const char *fmt : kFormats) { + for (char f : {'f', 'F', // + 'g', 'G', // + 'a', 'A', // + 'e', 'E'}) { + 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 (Floating d : floats) { + int i = -10; + FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; + UntypedFormatSpecImpl format(fmt_str); + + string_printf_result.clear(); + StrAppend(&string_printf_result, fmt_str.c_str(), d, i); + str_format_result.clear(); + + { + AppendPack(&str_format_result, format, absl::MakeSpan(args)); + } + + if (string_printf_result != str_format_result) { + // We use ASSERT_EQ here because failures are usually correlated and a + // bug would print way too many failed expectations causing the test + // to time out. + ASSERT_EQ(string_printf_result, str_format_result) + << fmt_str << " " << StrPrint("%.18g", d) << " " + << StrPrint("%a", d) << " " << StrPrint("%.50f", d); + } + } + } + } +} + TEST_F(FormatConvertTest, Float) { #ifdef _MSC_VER // MSVC has a different rounding policy than us so we can't test our @@ -481,9 +532,62 @@ TEST_F(FormatConvertTest, Float) { return; #endif // _MSC_VER - const char *const kFormats[] = { - "%", "%.3", "%8.5", "%500", "%.5000", "%.60", "%.30", "%03", - "%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; + std::vector floats = {0.0f, + -0.0f, + .9999999f, + 9999999.f, + std::numeric_limits::max(), + -std::numeric_limits::max(), + std::numeric_limits::min(), + -std::numeric_limits::min(), + std::numeric_limits::lowest(), + -std::numeric_limits::lowest(), + std::numeric_limits::epsilon(), + std::numeric_limits::epsilon() + 1.0f, + std::numeric_limits::infinity(), + -std::numeric_limits::infinity()}; + + // Some regression tests. + floats.push_back(0.999999989f); + + if (std::numeric_limits::has_denorm != std::denorm_absent) { + floats.push_back(std::numeric_limits::denorm_min()); + floats.push_back(-std::numeric_limits::denorm_min()); + } + + for (float base : + {1.f, 12.f, 123.f, 1234.f, 12345.f, 123456.f, 1234567.f, 12345678.f, + 123456789.f, 1234567890.f, 12345678901.f, 12345678.f, 12345678.f}) { + for (int exp = -123; exp <= 123; ++exp) { + for (int sign : {1, -1}) { + floats.push_back(sign * std::ldexp(base, exp)); + } + } + } + + for (int exp = -300; exp <= 300; ++exp) { + const float all_ones_mantissa = 0xffffff; + floats.push_back(std::ldexp(all_ones_mantissa, exp)); + } + + // Remove duplicates to speed up the logic below. + std::sort(floats.begin(), floats.end()); + floats.erase(std::unique(floats.begin(), floats.end()), floats.end()); + +#ifndef __APPLE__ + // Apple formats NaN differently (+nan) vs. (nan) + floats.push_back(std::nan("")); +#endif + + TestWithMultipleFormatsHelper(floats); +} + +TEST_F(FormatConvertTest, Double) { +#ifdef _MSC_VER + // MSVC has a different rounding policy than us so we can't test our + // implementation against the native one there. + return; +#endif // _MSC_VER std::vector doubles = {0.0, -0.0, @@ -554,52 +658,10 @@ TEST_F(FormatConvertTest, Float) { doubles.push_back(std::nan("")); #endif - // Reserve the space to ensure we don't allocate memory in the output itself. - std::string str_format_result; - str_format_result.reserve(1 << 20); - std::string string_printf_result; - string_printf_result.reserve(1 << 20); - - for (const char *fmt : kFormats) { - for (char f : {'f', 'F', // - 'g', 'G', // - 'a', 'A', // - 'e', 'E'}) { - 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) { - int i = -10; - FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; - UntypedFormatSpecImpl format(fmt_str); - - string_printf_result.clear(); - StrAppend(&string_printf_result, fmt_str.c_str(), d, i); - str_format_result.clear(); - - { - AppendPack(&str_format_result, format, absl::MakeSpan(args)); - } - - if (string_printf_result != str_format_result) { - // We use ASSERT_EQ here because failures are usually correlated and a - // bug would print way too many failed expectations causing the test - // to time out. - ASSERT_EQ(string_printf_result, str_format_result) - << fmt_str << " " << StrPrint("%.18g", d) << " " - << StrPrint("%a", d) << " " << StrPrint("%.1080f", d); - } - } - } - } + TestWithMultipleFormatsHelper(doubles); } -TEST_F(FormatConvertTest, FloatRound) { +TEST_F(FormatConvertTest, DoubleRound) { std::string s; const auto format = [&](const char *fmt, double d) -> std::string & { s.clear(); @@ -797,7 +859,7 @@ TEST_F(FormatConvertTest, LongDouble) { } } -TEST_F(FormatConvertTest, IntAsFloat) { +TEST_F(FormatConvertTest, IntAsDouble) { const int kMin = std::numeric_limits::min(); const int kMax = std::numeric_limits::max(); const int ia[] = { diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 10e46954..39fc5f60 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -1131,7 +1131,7 @@ bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv, bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink) { - return FloatToSink(v, conv, sink); + return FloatToSink(static_cast(v), conv, sink); } bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv, diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc index 7db85e75..c2f03b63 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc @@ -359,6 +359,12 @@ TEST(NumbersTest, Atoi) { VerifySimpleAtoiGood(42, 42); } +TEST(NumbersTest, Atod) { + double d; + EXPECT_TRUE(absl::SimpleAtod("nan", &d)); + EXPECT_TRUE(std::isnan(d)); +} + TEST(NumbersTest, Atoenum) { enum E01 { E01_zero = 0, diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h index 8ab43915..2228b6e8 100644 --- a/absl/synchronization/internal/per_thread_sem.h +++ b/absl/synchronization/internal/per_thread_sem.h @@ -78,7 +78,7 @@ class PerThreadSem { // !t.has_timeout() => Wait(t) will return true. static inline bool Wait(KernelTimeout t); - // White-listed callers. + // Permitted callers. friend class PerThreadSemTest; friend class absl::Mutex; friend absl::base_internal::ThreadIdentity* CreateThreadIdentity(); diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 62fa8e9c..05f5c041 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -39,7 +39,6 @@ #include // NOLINT(build/c++11) #include "absl/base/attributes.h" -#include "absl/base/call_once.h" #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/atomic_hook.h" @@ -59,6 +58,7 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; +using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -86,6 +86,28 @@ ABSL_CONST_INIT std::atomic synch_deadlock_detection( kDeadlockDetectionDefault); ABSL_CONST_INIT std::atomic synch_check_invariants(false); +// ------------------------------------------ spinlock support + +// Make sure read-only globals used in the Mutex code are contained on the +// same cacheline and cacheline aligned to eliminate any false sharing with +// other globals from this and other modules. +static struct MutexGlobals { + MutexGlobals() { + // Find machine-specific data needed for Delay() and + // TryAcquireWithSpinning(). This runs in the global constructor + // sequence, and before that zeros are safe values. + num_cpus = absl::base_internal::NumCPUs(); + spinloop_iterations = num_cpus > 1 ? 1500 : 0; + } + int num_cpus; + int spinloop_iterations; + // Pad this struct to a full cacheline to prevent false sharing. + char padding[ABSL_CACHELINE_SIZE - 2 * sizeof(int)]; +} ABSL_CACHELINE_ALIGNED mutex_globals; +static_assert( + sizeof(MutexGlobals) == ABSL_CACHELINE_SIZE, + "MutexGlobals must occupy an entire cacheline to prevent false sharing"); + ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook submit_profile_data; @@ -122,22 +144,7 @@ void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)) { symbolizer.Store(fn); } -struct ABSL_CACHELINE_ALIGNED MutexGlobals { - absl::once_flag once; - int num_cpus = 0; - int spinloop_iterations = 0; -}; - -static const MutexGlobals& GetMutexGlobals() { - ABSL_CONST_INIT static MutexGlobals data; - absl::base_internal::LowLevelCallOnce(&data.once, [&]() { - data.num_cpus = absl::base_internal::NumCPUs(); - data.spinloop_iterations = data.num_cpus > 1 ? 1500 : 0; - }); - return data; -} - -// Spinlock delay on iteration c. Returns new c. +// spinlock delay on iteration c. Returns new c. namespace { enum DelayMode { AGGRESSIVE, GENTLE }; }; @@ -147,25 +154,22 @@ static int Delay(int32_t c, DelayMode mode) { // gentle then spin only a few times before yielding. Aggressive spinning is // used to ensure that an Unlock() call, which must get the spin lock for // any thread to make progress gets it without undue delay. - const int32_t limit = - GetMutexGlobals().num_cpus > 1 ? (mode == AGGRESSIVE ? 5000 : 250) : 0; + int32_t limit = (mutex_globals.num_cpus > 1) ? + ((mode == AGGRESSIVE) ? 5000 : 250) : 0; if (c < limit) { - // Spin. - c++; + c++; // spin } else { ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0); - if (c == limit) { - // Yield once. + if (c == limit) { // yield once AbslInternalMutexYield(); c++; - } else { - // Then wait. + } else { // then wait absl::SleepFor(absl::Microseconds(10)); c = 0; } ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0); } - return c; + return (c); } // --------------------------Generic atomic ops @@ -1051,6 +1055,7 @@ static PerThreadSynch *DequeueAllWakeable(PerThreadSynch *head, // Try to remove thread s from the list of waiters on this mutex. // Does nothing if s is not on the waiter list. void Mutex::TryRemove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); // acquire spinlock & lock if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait && @@ -1434,7 +1439,7 @@ void Mutex::AssertNotHeld() const { // Attempt to acquire *mu, and return whether successful. The implementation // may spin for a short while if the lock cannot be acquired immediately. static bool TryAcquireWithSpinning(std::atomic* mu) { - int c = GetMutexGlobals().spinloop_iterations; + int c = mutex_globals.spinloop_iterations; do { // do/while somewhat faster on AMD intptr_t v = mu->load(std::memory_order_relaxed); if ((v & (kMuReader|kMuEvent)) != 0) { @@ -1811,9 +1816,9 @@ static inline bool EvalConditionIgnored(Mutex *mu, const Condition *cond) { // So we "divert" (which un-ignores both memory accesses and synchronization) // and then separately turn on ignores of memory accesses. ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0); - ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); bool res = cond->Eval(); - ANNOTATE_IGNORE_READS_AND_WRITES_END(); + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END(); ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); static_cast(mu); // Prevent unused param warning in non-TSAN builds. return res; @@ -1894,6 +1899,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -2013,6 +2019,7 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2328,6 +2335,7 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2426,6 +2434,7 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2586,6 +2595,7 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { + SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index de71c734..102affaf 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel @@ -12,7 +12,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load( -- cgit v1.2.3 From 81f34df8347a73c617f244f49cb916238857dc34 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 30 Jun 2020 13:08:50 -0700 Subject: Export of internal Abseil changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -- 739f9fb80212c21c015fec473e9e29803a156ef9 by Derek Mauro : Define FlagStateInterface::~FlagStateInterface() in the translation unit in which it is actually declared Fixes #717 PiperOrigin-RevId: 319083605 -- 913ef1f23113268b22d636d3ae3b992862efdb1a by Derek Mauro : Fix ABSL_LOCK_RETURNED statement PiperOrigin-RevId: 319078667 -- a43b1413da1770d638147c73e7e1693cfaf869c7 by Derek Mauro : Fix redeclaration ‘absl::Cord::InlineRep::kMaxInline’, which differs in ‘constexpr’ Fixes #725 PiperOrigin-RevId: 319060910 -- 1ad7d491a80f6c9de78a6fc20f09b7765d224503 by Abseil Team : Make absl SpinLock trivially destructible when possible PiperOrigin-RevId: 319049456 -- 659ecad3578dfa669854a82279fa590002bdb37f by Derek Mauro : Remove the static initialization of global variables used by absl::Mutex as requested by Chromium PiperOrigin-RevId: 319031204 -- 609c491d8bb4f8bb3b44c5a4c0bee51c583df24c by Abseil Team : Add implementation of %a and %A to absl::StrFormat. Prior to this it just fell back to sprintf. PiperOrigin-RevId: 318888039 -- 5e8ae6392bcd135248aac14c4b9f2a5116868678 by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 318857077 -- 4a2578e33e8442954e29e5f0380ddfcf0f033f0d by Greg Falcon : Change of enum constants to accommodate internal change. PiperOrigin-RevId: 318844716 -- 4b578b102816260c213675759f4c15911735578a by Abseil Team : Internal change PiperOrigin-RevId: 318704453 -- 0ee82fd24d548b260c9229fa1f54571dae1dfa24 by Gennadiy Rozental : Allow lookup of retired flags. At the moment we issue warning on attempt to find a retired flag. This way we can't even check if flag is retired without issuing the warning. With this change we will only issue the warning if one tries to access any functionality of retired flag but it's name "is retired" status, and type. PiperOrigin-RevId: 318605017 -- 3e35fe9b4c79f636fa328c59e2aabb93e29b7c99 by Abseil Team : Fix error return from InstallSymbolDecorator(). PiperOrigin-RevId: 318490405 -- ae46063f3eb2998cb961f62a359d932e5908a4bc by Abseil Team : Do not make copies of iterated collection elements into the loop variable. PiperOrigin-RevId: 318423139 -- d06a075a12aab5f6ab98474677ce50d588b21de3 by Abseil Team : add missing word making the error code better English PiperOrigin-RevId: 318335052 GitOrigin-RevId: 739f9fb80212c21c015fec473e9e29803a156ef9 Change-Id: Id77a0a4b1959036b00555deef40e82d51884fbc1 --- absl/base/internal/low_level_scheduling.h | 5 - absl/base/internal/spinlock.h | 7 + absl/base/spinlock_test_common.cc | 5 + .../internal/hash_function_defaults_test.cc | 4 +- absl/debugging/symbolize_elf.inc | 2 +- absl/flags/BUILD.bazel | 3 + absl/flags/CMakeLists.txt | 2 + absl/flags/commandlineflag.cc | 4 - absl/flags/commandlineflag.h | 4 + absl/flags/internal/commandlineflag.cc | 26 ++ absl/flags/internal/flag.h | 3 +- absl/flags/internal/usage.cc | 4 +- absl/flags/parse.cc | 7 +- absl/flags/reflection.cc | 48 ++-- absl/random/BUILD.bazel | 1 + absl/strings/BUILD.bazel | 1 + absl/strings/CMakeLists.txt | 1 + absl/strings/cord.cc | 2 +- absl/strings/internal/str_format/convert_test.cc | 230 ++++++++++++++++- .../internal/str_format/float_conversion.cc | 281 ++++++++++++++++++++- absl/strings/str_cat.cc | 8 +- absl/synchronization/mutex.cc | 64 ++--- 22 files changed, 618 insertions(+), 94 deletions(-) create mode 100644 absl/flags/internal/commandlineflag.cc (limited to 'absl/base/internal/low_level_scheduling.h') diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 31261298..ed0b4bfa 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -29,9 +29,6 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN -class CondVar; -class Mutex; - namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -80,8 +77,6 @@ class SchedulingGuard { }; // Access to SchedulingGuard is explicitly permitted. - friend class absl::CondVar; - friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h index 2222398b..e6ac9e64 100644 --- a/absl/base/internal/spinlock.h +++ b/absl/base/internal/spinlock.h @@ -64,7 +64,14 @@ class ABSL_LOCKABLE SpinLock { constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode) : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {} + // For global SpinLock instances prefer trivial destructor when possible. + // Default but non-trivial destructor in some build configurations causes an + // extra static initializer. +#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE ~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); } +#else + ~SpinLock() = default; +#endif // Acquire this SpinLock. inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc index b68c51a1..b33c54ba 100644 --- a/absl/base/spinlock_test_common.cc +++ b/absl/base/spinlock_test_common.cc @@ -20,6 +20,7 @@ #include #include #include // NOLINT(build/c++11) +#include #include #include "gtest/gtest.h" @@ -103,6 +104,10 @@ static void ThreadedTest(SpinLock* spinlock) { } } +#ifndef THREAD_SANITIZER +static_assert(std::is_trivially_destructible(), ""); +#endif + TEST(SpinLock, StackNonCooperativeDisablesScheduling) { SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY); spinlock.Lock(); diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc index 2d05a0b7..59576b8e 100644 --- a/absl/container/internal/hash_function_defaults_test.cc +++ b/absl/container/internal/hash_function_defaults_test.cc @@ -337,11 +337,11 @@ ABSL_NAMESPACE_END } // namespace absl enum Hash : size_t { - kStd = 0x2, // std::hash + kStd = 0x1, // std::hash #ifdef _MSC_VER kExtension = kStd, // In MSVC, std::hash == ::hash #else // _MSC_VER - kExtension = 0x4, // ::hash (GCC extension) + kExtension = 0x2, // ::hash (GCC extension) #endif // _MSC_VER }; diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index ed77159e..328869f1 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc @@ -1376,7 +1376,7 @@ int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) { if (!g_decorators_mu.TryLock()) { // Someone else is using decorators. Get out. - return false; + return -2; } int ret = ticket; if (g_num_decorators >= kMaxDecorators) { diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index 006911fd..524e7027 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -106,6 +106,9 @@ cc_library( cc_library( name = "commandlineflag_internal", + srcs = [ + "internal/commandlineflag.cc", + ], hdrs = [ "internal/commandlineflag.h", ], diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt index ef75db8e..343774de 100644 --- a/absl/flags/CMakeLists.txt +++ b/absl/flags/CMakeLists.txt @@ -95,6 +95,8 @@ absl_cc_library( absl_cc_library( NAME flags_commandlineflag_internal + SRCS + "internal/commandlineflag.cc" HDRS "internal/commandlineflag.h" COPTS diff --git a/absl/flags/commandlineflag.cc b/absl/flags/commandlineflag.cc index 217b2d87..9f3b4a5a 100644 --- a/absl/flags/commandlineflag.cc +++ b/absl/flags/commandlineflag.cc @@ -30,9 +30,5 @@ bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) { flags_internal::kProgrammaticChange, *error); } -namespace flags_internal { -FlagStateInterface::~FlagStateInterface() {} -} // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl - diff --git a/absl/flags/commandlineflag.h b/absl/flags/commandlineflag.h index 7e21d05d..f2fa0897 100644 --- a/absl/flags/commandlineflag.h +++ b/absl/flags/commandlineflag.h @@ -108,6 +108,10 @@ class CommandLineFlag { U u; Read(&u.value); + // allow retired flags to be "read", so we can report invalid access. + if (IsRetired()) { + return absl::nullopt; + } return std::move(u.value); } diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc new file mode 100644 index 00000000..4482955c --- /dev/null +++ b/absl/flags/internal/commandlineflag.cc @@ -0,0 +1,26 @@ +// +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/flags/internal/commandlineflag.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace flags_internal { + +FlagStateInterface::~FlagStateInterface() {} + +} // namespace flags_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 2cc44e00..89e43ad7 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -482,7 +482,8 @@ class FlagImpl final : public CommandLineFlag { friend class FlagState; // Ensures that `data_guard_` is initialized and returns it. - absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED((absl::Mutex*)&data_guard_); + absl::Mutex* DataGuard() const + ABSL_LOCK_RETURNED(reinterpret_cast(data_guard_)); // Returns heap allocated value of type T initialized with default value. std::unique_ptr MakeInitValue() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc index 35b6427b..0805df31 100644 --- a/absl/flags/internal/usage.cc +++ b/absl/flags/internal/usage.cc @@ -250,14 +250,14 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb, matching_flags; flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) { - std::string flag_filename = flag.Filename(); - // Ignore retired flags. if (flag.IsRetired()) return; // If the flag has been stripped, pretend that it doesn't exist. if (flag.Help() == flags_internal::kStrippedFlagHelp) return; + std::string flag_filename = flag.Filename(); + // Make sure flag satisfies the filter if (!filter_cb || !filter_cb(flag_filename)) return; diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc index e2c88ff8..4f4bb3d5 100644 --- a/absl/flags/parse.cc +++ b/absl/flags/parse.cc @@ -729,12 +729,13 @@ std::vector ParseCommandLineImpl(int argc, char* argv[], } // 100. Set the located flag to a new new value, unless it is retired. - // Setting retired flag fails, but we ignoring it here. - if (flag->IsRetired()) continue; - + // Setting retired flag fails, but we ignoring it here while also reporting + // access to retired flag. std::string error; if (!flags_internal::PrivateHandleAccessor::ParseFrom( *flag, value, SET_FLAGS_VALUE, kCommandLine, error)) { + if (flag->IsRetired()) continue; + flags_internal::ReportUsageError(error, true); success = false; } else { diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc index 5fc945f2..02b7c06a 100644 --- a/absl/flags/reflection.cc +++ b/absl/flags/reflection.cc @@ -88,12 +88,6 @@ CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) { if (i == flags_.end()) { return nullptr; } - - if (i->second->IsRetired()) { - flags_internal::ReportUsageError( - absl::StrCat("Accessing retired flag '", name, "'"), false); - } - return i->second; } @@ -155,7 +149,7 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag) { } else { flags_internal::ReportUsageError( absl::StrCat( - "Something wrong with flag '", flag.Name(), "' in file '", + "Something is wrong with flag '", flag.Name(), "' in file '", flag.Filename(), "'. One possibility: file '", flag.Filename(), "' is being linked both statically and dynamically into this " "executable. e.g. some files listed as srcs to a test and also " @@ -206,16 +200,34 @@ class RetiredFlagObj final : public CommandLineFlag { private: absl::string_view Name() const override { return name_; } - std::string Filename() const override { return "RETIRED"; } + std::string Filename() const override { + OnAccess(); + return "RETIRED"; + } FlagFastTypeId TypeId() const override { return type_id_; } - std::string Help() const override { return ""; } + std::string Help() const override { + OnAccess(); + return ""; + } bool IsRetired() const override { return true; } - bool IsSpecifiedOnCommandLine() const override { return false; } - std::string DefaultValue() const override { return ""; } - std::string CurrentValue() const override { return ""; } + bool IsSpecifiedOnCommandLine() const override { + OnAccess(); + return false; + } + std::string DefaultValue() const override { + OnAccess(); + return ""; + } + std::string CurrentValue() const override { + OnAccess(); + return ""; + } // Any input is valid - bool ValidateInputValue(absl::string_view) const override { return true; } + bool ValidateInputValue(absl::string_view) const override { + OnAccess(); + return true; + } std::unique_ptr SaveState() override { return nullptr; @@ -223,12 +235,18 @@ class RetiredFlagObj final : public CommandLineFlag { bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode, flags_internal::ValueSource, std::string&) override { + OnAccess(); return false; } - void CheckDefaultValueParsingRoundtrip() const override {} + void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); } - void Read(void*) const override {} + void Read(void*) const override { OnAccess(); } + + void OnAccess() const { + flags_internal::ReportUsageError( + absl::StrCat("Accessing retired flag '", name_, "'"), false); + } // Data members const char* const name_; diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel index 694331c2..81e150e6 100644 --- a/absl/random/BUILD.bazel +++ b/absl/random/BUILD.bazel @@ -199,6 +199,7 @@ cc_test( cc_test( name = "distributions_test", size = "small", + timeout = "moderate", srcs = [ "distributions_test.cc", ], diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 8220896d..ef412639 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -720,6 +720,7 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":str_format_internal", + ":strings", "//absl/base:raw_logging_internal", "//absl/types:optional", "@com_google_googletest//:gtest_main", diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index c0ea0c8e..d7237231 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -475,6 +475,7 @@ absl_cc_test( COPTS ${ABSL_TEST_COPTS} DEPS + absl::strings absl::str_format_internal absl::raw_logging_internal absl::int128 diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc index 68f53987..8ecffc4b 100644 --- a/absl/strings/cord.cc +++ b/absl/strings/cord.cc @@ -495,7 +495,7 @@ static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) { // This will trigger LNK2005 in MSVC. #ifndef COMPILER_MSVC -const unsigned char Cord::InlineRep::kMaxInline; +constexpr unsigned char Cord::InlineRep::kMaxInline; #endif // COMPILER_MSVC inline void Cord::InlineRep::set_data(const char* data, size_t n, diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index e37d0546..488d4cd4 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -12,6 +12,7 @@ #include "gtest/gtest.h" #include "absl/base/internal/raw_logging.h" #include "absl/strings/internal/str_format/bind.h" +#include "absl/strings/match.h" #include "absl/types/optional.h" namespace absl { @@ -19,6 +20,13 @@ ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { +struct NativePrintfTraits { + bool hex_float_has_glibc_rounding; + bool hex_float_prefers_denormal_repr; + bool hex_float_uses_minimal_precision_when_not_specified; + bool hex_float_optimizes_leading_digit_bit_count; +}; + template size_t ArraySize(T (&)[N]) { return N; @@ -118,6 +126,63 @@ std::string StrPrint(const char *format, ...) { return result; } +NativePrintfTraits VerifyNativeImplementationImpl() { + NativePrintfTraits result; + + // >>> hex_float_has_glibc_rounding. To have glibc's rounding behavior we need + // to meet three requirements: + // + // - The threshold for rounding up is 8 (for e.g. MSVC uses 9). + // - If the digits lower than than the 8 are non-zero then we round up. + // - If the digits lower than the 8 are all zero then we round toward even. + // + // The numbers below represent all the cases covering {below,at,above} the + // threshold (8) with both {zero,non-zero} lower bits and both {even,odd} + // preceding digits. + const double d0079 = 65657.0; // 0x1.0079p+16 + const double d0179 = 65913.0; // 0x1.0179p+16 + const double d0080 = 65664.0; // 0x1.0080p+16 + const double d0180 = 65920.0; // 0x1.0180p+16 + const double d0081 = 65665.0; // 0x1.0081p+16 + const double d0181 = 65921.0; // 0x1.0181p+16 + result.hex_float_has_glibc_rounding = + StartsWith(StrPrint("%.2a", d0079), "0x1.00") && + StartsWith(StrPrint("%.2a", d0179), "0x1.01") && + StartsWith(StrPrint("%.2a", d0080), "0x1.00") && + StartsWith(StrPrint("%.2a", d0180), "0x1.02") && + StartsWith(StrPrint("%.2a", d0081), "0x1.01") && + StartsWith(StrPrint("%.2a", d0181), "0x1.02"); + + // >>> hex_float_prefers_denormal_repr. Formatting `denormal` on glibc yields + // "0x0.0000000000001p-1022", whereas on std libs that don't use denormal + // representation it would either be 0x1p-1074 or 0x1.0000000000000-1074. + const double denormal = std::numeric_limits::denorm_min(); + result.hex_float_prefers_denormal_repr = + StartsWith(StrPrint("%a", denormal), "0x0.0000000000001"); + + // >>> hex_float_uses_minimal_precision_when_not_specified. Some (non-glibc) + // libs will format the following as "0x1.0079000000000p+16". + result.hex_float_uses_minimal_precision_when_not_specified = + (StrPrint("%a", d0079) == "0x1.0079p+16"); + + // >>> hex_float_optimizes_leading_digit_bit_count. The number 1.5, when + // formatted by glibc should yield "0x1.8p+0" for `double` and "0xcp-3" for + // `long double`, i.e., number of bits in the leading digit is adapted to the + // number of bits in the mantissa. + const double d_15 = 1.5; + const long double ld_15 = 1.5; + result.hex_float_optimizes_leading_digit_bit_count = + StartsWith(StrPrint("%a", d_15), "0x1.8") && + StartsWith(StrPrint("%La", ld_15), "0xc"); + + return result; +} + +const NativePrintfTraits &VerifyNativeImplementation() { + static NativePrintfTraits native_traits = VerifyNativeImplementationImpl(); + return native_traits; +} + class FormatConvertTest : public ::testing::Test { }; template @@ -476,6 +541,7 @@ TEST_F(FormatConvertTest, Uint128) { template void TestWithMultipleFormatsHelper(const std::vector &floats) { + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); // Reserve the space to ensure we don't allocate memory in the output itself. std::string str_format_result; str_format_result.reserve(1 << 20); @@ -493,13 +559,23 @@ void TestWithMultipleFormatsHelper(const std::vector &floats) { 'e', 'E'}) { std::string fmt_str = std::string(fmt) + f; - if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { + if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' && + f != 'a' && f != 'A') { // This particular test takes way too long with snprintf. // Disable for the case we are not implementing natively. continue; } + if ((f == 'a' || f == 'A') && + !native_traits.hex_float_has_glibc_rounding) { + continue; + } + for (Floating d : floats) { + if (!native_traits.hex_float_prefers_denormal_repr && + (f == 'a' || f == 'A') && std::fpclassify(d) == FP_SUBNORMAL) { + continue; + } int i = -10; FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; UntypedFormatSpecImpl format(fmt_str); @@ -766,6 +842,111 @@ TEST_F(FormatConvertTest, DoubleRound) { "1837869002408041296803276054561138153076171875"); } +TEST_F(FormatConvertTest, DoubleRoundA) { + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); + std::string s; + const auto format = [&](const char *fmt, double d) -> std::string & { + s.clear(); + FormatArgImpl args[1] = {FormatArgImpl(d)}; + AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); + if (native_traits.hex_float_has_glibc_rounding) { + EXPECT_EQ(StrPrint(fmt, d), s); + } + return s; + }; + + // 0x1.00018000p+100 + const double on_boundary_odd = 1267679614447900152596896153600.0; + EXPECT_EQ(format("%.0a", on_boundary_odd), "0x1p+100"); + EXPECT_EQ(format("%.1a", on_boundary_odd), "0x1.0p+100"); + EXPECT_EQ(format("%.2a", on_boundary_odd), "0x1.00p+100"); + EXPECT_EQ(format("%.3a", on_boundary_odd), "0x1.000p+100"); + EXPECT_EQ(format("%.4a", on_boundary_odd), "0x1.0002p+100"); // round + EXPECT_EQ(format("%.5a", on_boundary_odd), "0x1.00018p+100"); + EXPECT_EQ(format("%.6a", on_boundary_odd), "0x1.000180p+100"); + + // 0x1.00028000p-2 + const double on_boundary_even = 0.250009536743164062500; + EXPECT_EQ(format("%.0a", on_boundary_even), "0x1p-2"); + EXPECT_EQ(format("%.1a", on_boundary_even), "0x1.0p-2"); + EXPECT_EQ(format("%.2a", on_boundary_even), "0x1.00p-2"); + EXPECT_EQ(format("%.3a", on_boundary_even), "0x1.000p-2"); + EXPECT_EQ(format("%.4a", on_boundary_even), "0x1.0002p-2"); // no round + EXPECT_EQ(format("%.5a", on_boundary_even), "0x1.00028p-2"); + EXPECT_EQ(format("%.6a", on_boundary_even), "0x1.000280p-2"); + + // 0x1.00018001p+1 + const double slightly_over = 2.00004577683284878730773925781250; + EXPECT_EQ(format("%.0a", slightly_over), "0x1p+1"); + EXPECT_EQ(format("%.1a", slightly_over), "0x1.0p+1"); + EXPECT_EQ(format("%.2a", slightly_over), "0x1.00p+1"); + EXPECT_EQ(format("%.3a", slightly_over), "0x1.000p+1"); + EXPECT_EQ(format("%.4a", slightly_over), "0x1.0002p+1"); + EXPECT_EQ(format("%.5a", slightly_over), "0x1.00018p+1"); + EXPECT_EQ(format("%.6a", slightly_over), "0x1.000180p+1"); + + // 0x1.00017fffp+0 + const double slightly_under = 1.000022887950763106346130371093750; + EXPECT_EQ(format("%.0a", slightly_under), "0x1p+0"); + EXPECT_EQ(format("%.1a", slightly_under), "0x1.0p+0"); + EXPECT_EQ(format("%.2a", slightly_under), "0x1.00p+0"); + EXPECT_EQ(format("%.3a", slightly_under), "0x1.000p+0"); + EXPECT_EQ(format("%.4a", slightly_under), "0x1.0001p+0"); + EXPECT_EQ(format("%.5a", slightly_under), "0x1.00018p+0"); + EXPECT_EQ(format("%.6a", slightly_under), "0x1.000180p+0"); + EXPECT_EQ(format("%.7a", slightly_under), "0x1.0001800p+0"); + + // 0x1.1b3829ac28058p+3 + const double hex_value = 8.85060580848964661981881363317370414733886718750; + EXPECT_EQ(format("%.0a", hex_value), "0x1p+3"); + EXPECT_EQ(format("%.1a", hex_value), "0x1.2p+3"); + EXPECT_EQ(format("%.2a", hex_value), "0x1.1bp+3"); + EXPECT_EQ(format("%.3a", hex_value), "0x1.1b4p+3"); + EXPECT_EQ(format("%.4a", hex_value), "0x1.1b38p+3"); + EXPECT_EQ(format("%.5a", hex_value), "0x1.1b383p+3"); + EXPECT_EQ(format("%.6a", hex_value), "0x1.1b382ap+3"); + EXPECT_EQ(format("%.7a", hex_value), "0x1.1b3829bp+3"); + EXPECT_EQ(format("%.8a", hex_value), "0x1.1b3829acp+3"); + EXPECT_EQ(format("%.9a", hex_value), "0x1.1b3829ac3p+3"); + EXPECT_EQ(format("%.10a", hex_value), "0x1.1b3829ac28p+3"); + EXPECT_EQ(format("%.11a", hex_value), "0x1.1b3829ac280p+3"); + EXPECT_EQ(format("%.12a", hex_value), "0x1.1b3829ac2806p+3"); + EXPECT_EQ(format("%.13a", hex_value), "0x1.1b3829ac28058p+3"); + EXPECT_EQ(format("%.14a", hex_value), "0x1.1b3829ac280580p+3"); + EXPECT_EQ(format("%.15a", hex_value), "0x1.1b3829ac2805800p+3"); + EXPECT_EQ(format("%.16a", hex_value), "0x1.1b3829ac28058000p+3"); + EXPECT_EQ(format("%.17a", hex_value), "0x1.1b3829ac280580000p+3"); + EXPECT_EQ(format("%.18a", hex_value), "0x1.1b3829ac2805800000p+3"); + EXPECT_EQ(format("%.19a", hex_value), "0x1.1b3829ac28058000000p+3"); + EXPECT_EQ(format("%.20a", hex_value), "0x1.1b3829ac280580000000p+3"); + EXPECT_EQ(format("%.21a", hex_value), "0x1.1b3829ac2805800000000p+3"); + + // 0x1.0818283848586p+3 + const double hex_value2 = 8.2529488658208371987257123691961169242858886718750; + EXPECT_EQ(format("%.0a", hex_value2), "0x1p+3"); + EXPECT_EQ(format("%.1a", hex_value2), "0x1.1p+3"); + EXPECT_EQ(format("%.2a", hex_value2), "0x1.08p+3"); + EXPECT_EQ(format("%.3a", hex_value2), "0x1.082p+3"); + EXPECT_EQ(format("%.4a", hex_value2), "0x1.0818p+3"); + EXPECT_EQ(format("%.5a", hex_value2), "0x1.08183p+3"); + EXPECT_EQ(format("%.6a", hex_value2), "0x1.081828p+3"); + EXPECT_EQ(format("%.7a", hex_value2), "0x1.0818284p+3"); + EXPECT_EQ(format("%.8a", hex_value2), "0x1.08182838p+3"); + EXPECT_EQ(format("%.9a", hex_value2), "0x1.081828385p+3"); + EXPECT_EQ(format("%.10a", hex_value2), "0x1.0818283848p+3"); + EXPECT_EQ(format("%.11a", hex_value2), "0x1.08182838486p+3"); + EXPECT_EQ(format("%.12a", hex_value2), "0x1.081828384858p+3"); + EXPECT_EQ(format("%.13a", hex_value2), "0x1.0818283848586p+3"); + EXPECT_EQ(format("%.14a", hex_value2), "0x1.08182838485860p+3"); + EXPECT_EQ(format("%.15a", hex_value2), "0x1.081828384858600p+3"); + EXPECT_EQ(format("%.16a", hex_value2), "0x1.0818283848586000p+3"); + EXPECT_EQ(format("%.17a", hex_value2), "0x1.08182838485860000p+3"); + EXPECT_EQ(format("%.18a", hex_value2), "0x1.081828384858600000p+3"); + EXPECT_EQ(format("%.19a", hex_value2), "0x1.0818283848586000000p+3"); + EXPECT_EQ(format("%.20a", hex_value2), "0x1.08182838485860000000p+3"); + EXPECT_EQ(format("%.21a", hex_value2), "0x1.081828384858600000000p+3"); +} + // We don't actually store the results. This is just to exercise the rest of the // machinery. struct NullSink { @@ -797,6 +978,7 @@ TEST_F(FormatConvertTest, LongDouble) { // implementation against the native one there. return; #endif // _MSC_VER + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000", "%.60", "%+", "% ", "%-10"}; @@ -839,12 +1021,20 @@ TEST_F(FormatConvertTest, LongDouble) { 'e', 'E'}) { std::string fmt_str = std::string(fmt) + 'L' + f; - if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { + if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' && + f != 'a' && f != 'A') { // This particular test takes way too long with snprintf. // Disable for the case we are not implementing natively. continue; } + if (f == 'a' || f == 'A') { + if (!native_traits.hex_float_has_glibc_rounding || + !native_traits.hex_float_optimizes_leading_digit_bit_count) { + continue; + } + } + for (auto d : doubles) { FormatArgImpl arg(d); UntypedFormatSpecImpl format(fmt_str); @@ -860,6 +1050,7 @@ TEST_F(FormatConvertTest, LongDouble) { } TEST_F(FormatConvertTest, IntAsDouble) { + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); const int kMin = std::numeric_limits::min(); const int kMax = std::numeric_limits::max(); const int ia[] = { @@ -875,14 +1066,16 @@ TEST_F(FormatConvertTest, IntAsDouble) { const char *fmt; }; const double dx = static_cast(fx); - const Expectation kExpect[] = { - { __LINE__, StrPrint("%f", dx), "%f" }, - { __LINE__, StrPrint("%12f", dx), "%12f" }, - { __LINE__, StrPrint("%.12f", dx), "%.12f" }, - { __LINE__, StrPrint("%12a", dx), "%12a" }, - { __LINE__, StrPrint("%.12a", dx), "%.12a" }, + std::vector expect = { + {__LINE__, StrPrint("%f", dx), "%f"}, + {__LINE__, StrPrint("%12f", dx), "%12f"}, + {__LINE__, StrPrint("%.12f", dx), "%.12f"}, + {__LINE__, StrPrint("%.12a", dx), "%.12a"}, }; - for (const Expectation &e : kExpect) { + if (native_traits.hex_float_uses_minimal_precision_when_not_specified) { + expect.push_back({__LINE__, StrPrint("%12a", dx), "%12a"}); + } + for (const Expectation &e : expect) { SCOPED_TRACE(e.line); SCOPED_TRACE(e.fmt); UntypedFormatSpecImpl format(e.fmt); @@ -927,6 +1120,25 @@ TEST_F(FormatConvertTest, ExpectedFailures) { EXPECT_TRUE(FormatFails("%*d", "")); } +// Sanity check to make sure that we are testing what we think we're testing on +// e.g. the x86_64+glibc platform. +TEST_F(FormatConvertTest, GlibcHasCorrectTraits) { +#if !defined(__GLIBC__) || !defined(__x86_64__) + return; +#endif + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); + // If one of the following tests break then it is either because the above PP + // macro guards failed to exclude a new platform (likely) or because something + // has changed in the implemention of glibc sprintf float formatting behavior. + // If the latter, then the code that computes these flags needs to be + // revisited and/or possibly the StrFormat implementation. + EXPECT_TRUE(native_traits.hex_float_has_glibc_rounding); + EXPECT_TRUE(native_traits.hex_float_prefers_denormal_repr); + EXPECT_TRUE( + native_traits.hex_float_uses_minimal_precision_when_not_specified); + EXPECT_TRUE(native_traits.hex_float_optimizes_leading_digit_bit_count); +} + } // namespace } // namespace str_format_internal ABSL_NAMESPACE_END diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 39fc5f60..6eb7b9fc 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -15,6 +15,7 @@ #include "absl/functional/function_ref.h" #include "absl/meta/type_traits.h" #include "absl/numeric/int128.h" +#include "absl/strings/numbers.h" #include "absl/types/optional.h" #include "absl/types/span.h" @@ -453,26 +454,31 @@ Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) { } } -void FinalPrint(absl::string_view data, int trailing_zeros, - const FormatState &state) { +void FinalPrint(const FormatState &state, absl::string_view data, + int padding_offset, int trailing_zeros, + absl::string_view data_postfix) { if (state.conv.width() < 0) { // No width specified. Fast-path. if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); state.sink->Append(data); state.sink->Append(trailing_zeros, '0'); + state.sink->Append(data_postfix); return; } - auto padding = - ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + data.size() + - static_cast(trailing_zeros), - state); + auto padding = ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + + data.size() + data_postfix.size() + + static_cast(trailing_zeros), + state); state.sink->Append(padding.left_spaces, ' '); if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); + // Padding in general needs to be inserted somewhere in the middle of `data`. + state.sink->Append(data.substr(0, padding_offset)); state.sink->Append(padding.zeros, '0'); - state.sink->Append(data); + state.sink->Append(data.substr(padding_offset)); state.sink->Append(trailing_zeros, '0'); + state.sink->Append(data_postfix); state.sink->Append(padding.right_spaces, ' '); } @@ -525,10 +531,11 @@ void FormatFFast(Int v, int exp, const FormatState &state) { // In `alt` mode (flag #) we keep the `.` even if there are no fractional // digits. In non-alt mode, we strip it. if (!state.ShouldPrintDot()) --size; - FinalPrint(absl::string_view(integral_digits_start, size), + FinalPrint(state, absl::string_view(integral_digits_start, size), + /*padding_offset=*/0, static_cast(state.precision - (fractional_digits_end - fractional_digits_start)), - state); + /*data_postfix=*/""); } // Slow %f formatter for when the shifted value does not fit in a uint128, and @@ -655,6 +662,257 @@ void FormatF(Int mantissa, int exp, const FormatState &state) { return FormatFFast(mantissa, exp, state); } +// Grab the group of four bits (nibble) from `n`. E.g., nibble 1 corresponds to +// bits 4-7. +template +uint8_t GetNibble(Int n, int nibble_index) { + constexpr Int mask_low_nibble = Int{0xf}; + int shift = nibble_index * 4; + n &= mask_low_nibble << shift; + return static_cast((n >> shift) & 0xf); +} + +// Add one to the given nibble, applying carry to higher nibbles. Returns true +// if overflow, false otherwise. +template +bool IncrementNibble(int nibble_index, Int *n) { + constexpr int kShift = sizeof(Int) * 8 - 1; + constexpr int kNumNibbles = sizeof(Int) * 8 / 4; + Int before = *n >> kShift; + // Here we essentially want to take the number 1 and move it into the requsted + // nibble, then add it to *n to effectively increment the nibble. However, + // ASan will complain if we try to shift the 1 beyond the limits of the Int, + // i.e., if the nibble_index is out of range. So therefore we check for this + // and if we are out of range we just add 0 which leaves *n unchanged, which + // seems like the reasonable thing to do in that case. + *n += + ((nibble_index * 4 >= sizeof(Int) * 8) ? 0 + : (Int{1} << (nibble_index * 4))); + Int after = *n >> kShift; + return (before && !after) || (nibble_index >= kNumNibbles); +} + +// Return a mask with 1's in the given nibble and all lower nibbles. +template +Int MaskUpToNibbleInclusive(int nibble_index) { + constexpr int kNumNibbles = sizeof(Int) * 8 / 4; + static const Int ones = ~Int{0}; + return ones >> std::max(0, 4 * (kNumNibbles - nibble_index - 1)); +} + +// Return a mask with 1's below the given nibble. +template +Int MaskUpToNibbleExclusive(int nibble_index) { + return nibble_index <= 0 ? 0 : MaskUpToNibbleInclusive(nibble_index - 1); +} + +template +Int MoveToNibble(uint8_t nibble, int nibble_index) { + return Int{nibble} << (4 * nibble_index); +} + +// Given mantissa size, find optimal # of mantissa bits to put in initial digit. +// +// In the hex representation we keep a single hex digit to the left of the dot. +// However, the question as to how many bits of the mantissa should be put into +// that hex digit in theory is arbitrary, but in practice it is optimal to +// choose based on the size of the mantissa. E.g., for a `double`, there are 53 +// mantissa bits, so that means that we should put 1 bit to the left of the dot, +// thereby leaving 52 bits to the right, which is evenly divisible by four and +// thus all fractional digits represent actual precision. For a `long double`, +// on the other hand, there are 64 bits of mantissa, thus we can use all four +// bits for the initial hex digit and still have a number left over (60) that is +// a multiple of four. Once again, the goal is to have all fractional digits +// represent real precision. +template +constexpr int HexFloatLeadingDigitSizeInBits() { + return std::numeric_limits::digits % 4 > 0 + ? std::numeric_limits::digits % 4 + : 4; +} + +// This function captures the rounding behavior of glibc for hex float +// representations. E.g. when rounding 0x1.ab800000 to a precision of .2 +// ("%.2a") glibc will round up because it rounds toward the even number (since +// 0xb is an odd number, it will round up to 0xc). However, when rounding at a +// point that is not followed by 800000..., it disregards the parity and rounds +// up if > 8 and rounds down if < 8. +template +bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed) { + // If the last nibble (hex digit) to be displayed is the lowest on in the + // mantissa then that means that we don't have any further nibbles to inform + // rounding, so don't round. + if (final_nibble_displayed <= 0) { + return false; + } + int rounding_nibble_idx = final_nibble_displayed - 1; + constexpr int kTotalNibbles = sizeof(Int) * 8 / 4; + assert(final_nibble_displayed <= kTotalNibbles); + Int mantissa_up_to_rounding_nibble_inclusive = + mantissa & MaskUpToNibbleInclusive(rounding_nibble_idx); + Int eight = MoveToNibble(8, rounding_nibble_idx); + if (mantissa_up_to_rounding_nibble_inclusive != eight) { + return mantissa_up_to_rounding_nibble_inclusive > eight; + } + // Nibble in question == 8. + uint8_t should_round_at_8 = + (final_nibble_displayed >= kTotalNibbles) + ? true + : (GetNibble(mantissa, final_nibble_displayed) % 2 == 1); + return should_round_at_8; +} + +// Stores values associated with a Float type needed by the FormatA +// implementation in order to avoid templatizing that function by the Float +// type. +struct HexFloatTypeParams { + template + explicit HexFloatTypeParams(Float) + : min_exponent(std::numeric_limits::min_exponent - 1), + leading_digit_size_bits(HexFloatLeadingDigitSizeInBits()) { + assert(leading_digit_size_bits >= 1 && leading_digit_size_bits <= 4); + } + + int min_exponent; + int leading_digit_size_bits; +}; + +// Hex Float Rounding. First check if we need to round; if so, then we do that +// by manipulating (incrementing) the mantissa, that way we can later print the +// mantissa digits by iterating through them in the same way regardless of +// whether a rounding happened. +template +void FormatARound(bool precision_specified, const FormatState &state, + uint8_t *leading, Int *mantissa, int *exp) { + constexpr int kTotalNibbles = sizeof(Int) * 8 / 4; + // Index of the last nibble that we could display given precision. + int final_nibble_displayed = + precision_specified ? std::max(0, (kTotalNibbles - state.precision)) : 0; + if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed)) { + // Need to round up. + bool overflow = IncrementNibble(final_nibble_displayed, mantissa); + *leading += (overflow ? 1 : 0); + if (ABSL_PREDICT_FALSE(*leading > 15)) { + // We have overflowed the leading digit. This would mean that we would + // need two hex digits to the left of the dot, which is not allowed. So + // adjust the mantissa and exponent so that the result is always 1.0eXXX. + *leading = 1; + *mantissa = 0; + *exp += 4; + } + } + // Now that we have handled a possible round-up we can go ahead and zero out + // all the nibbles of the mantissa that we won't need. + if (precision_specified) { + *mantissa &= ~MaskUpToNibbleExclusive(final_nibble_displayed); + } +} + +template +void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading, + Int *mantissa, int *exp) { + constexpr int kIntBits = sizeof(Int) * 8; + static const Int kHighIntBit = Int{1} << (kIntBits - 1); + const int kLeadDigitBitsCount = float_traits.leading_digit_size_bits; + // Normalize mantissa so that highest bit set is in MSB position, unless we + // get interrupted by the exponent threshold. + while (*mantissa && !(*mantissa & kHighIntBit)) { + if (ABSL_PREDICT_FALSE(*exp - 1 < float_traits.min_exponent)) { + *mantissa >>= (float_traits.min_exponent - *exp); + *exp = float_traits.min_exponent; + return; + } + *mantissa <<= 1; + --*exp; + } + // Extract bits for leading digit then shift them away leaving the + // fractional part. + *leading = + static_cast(*mantissa >> (kIntBits - kLeadDigitBitsCount)); + *exp -= (*mantissa != 0) ? kLeadDigitBitsCount : *exp; + *mantissa <<= kLeadDigitBitsCount; +} + +template +void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp, + bool uppercase, const FormatState &state) { + // Int properties. + constexpr int kIntBits = sizeof(Int) * 8; + constexpr int kTotalNibbles = sizeof(Int) * 8 / 4; + // Did the user specify a precision explicitly? + const bool precision_specified = state.conv.precision() >= 0; + + // ========== Normalize/Denormalize ========== + exp += kIntBits; // make all digits fractional digits. + // This holds the (up to four) bits of leading digit, i.e., the '1' in the + // number 0x1.e6fp+2. It's always > 0 unless number is zero or denormal. + uint8_t leading = 0; + FormatANormalize(float_traits, &leading, &mantissa, &exp); + + // =============== Rounding ================== + // Check if we need to round; if so, then we do that by manipulating + // (incrementing) the mantissa before beginning to print characters. + FormatARound(precision_specified, state, &leading, &mantissa, &exp); + + // ============= Format Result =============== + // This buffer holds the "0x1.ab1de3" portion of "0x1.ab1de3pe+2". Compute the + // size with long double which is the largest of the floats. + constexpr size_t kBufSizeForHexFloatRepr = + 2 // 0x + + std::numeric_limits::digits / 4 // number of hex digits + + 1 // round up + + 1; // "." (dot) + char digits_buffer[kBufSizeForHexFloatRepr]; + char *digits_iter = digits_buffer; + const char *const digits = + static_cast("0123456789ABCDEF0123456789abcdef") + + (uppercase ? 0 : 16); + + // =============== Hex Prefix ================ + *digits_iter++ = '0'; + *digits_iter++ = uppercase ? 'X' : 'x'; + + // ========== Non-Fractional Digit =========== + *digits_iter++ = digits[leading]; + + // ================== Dot ==================== + // There are three reasons we might need a dot. Keep in mind that, at this + // point, the mantissa holds only the fractional part. + if ((precision_specified && state.precision > 0) || + (!precision_specified && mantissa > 0) || state.conv.has_alt_flag()) { + *digits_iter++ = '.'; + } + + // ============ Fractional Digits ============ + int digits_emitted = 0; + while (mantissa > 0) { + *digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)]; + mantissa <<= 4; + ++digits_emitted; + } + int trailing_zeros = + precision_specified ? state.precision - digits_emitted : 0; + assert(trailing_zeros >= 0); + auto digits_result = string_view(digits_buffer, digits_iter - digits_buffer); + + // =============== Exponent ================== + constexpr size_t kBufSizeForExpDecRepr = + numbers_internal::kFastToBufferSize // requred for FastIntToBuffer + + 1 // 'p' or 'P' + + 1; // '+' or '-' + char exp_buffer[kBufSizeForExpDecRepr]; + exp_buffer[0] = uppercase ? 'P' : 'p'; + exp_buffer[1] = exp >= 0 ? '+' : '-'; + numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2); + + // ============ Assemble Result ============== + FinalPrint(state, // + digits_result, // 0xN.NNN... + 2, // offset in `data` to start padding if needed. + trailing_zeros, // num remaining mantissa padding zeros + exp_buffer); // exponent +} + char *CopyStringTo(absl::string_view v, char *out) { std::memcpy(out, v.data(), v.size()); return out + v.size(); @@ -1103,7 +1361,10 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv, } } else if (c == FormatConversionCharInternal::a || c == FormatConversionCharInternal::A) { - return FallbackToSnprintf(v, conv, sink); + bool uppercase = (c == FormatConversionCharInternal::A); + FormatA(HexFloatTypeParams(Float{}), decomposed.mantissa, + decomposed.exponent, uppercase, {sign_char, precision, conv, sink}); + return true; } else { return false; } diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc index d9afe2f3..dd5d25b0 100644 --- a/absl/strings/str_cat.cc +++ b/absl/strings/str_cat.cc @@ -141,12 +141,12 @@ namespace strings_internal { std::string CatPieces(std::initializer_list pieces) { std::string result; size_t total_size = 0; - for (const absl::string_view piece : pieces) total_size += piece.size(); + for (const absl::string_view& piece : pieces) total_size += piece.size(); strings_internal::STLStringResizeUninitialized(&result, total_size); char* const begin = &result[0]; char* out = begin; - for (const absl::string_view piece : pieces) { + for (const absl::string_view& piece : pieces) { const size_t this_size = piece.size(); if (this_size != 0) { memcpy(out, piece.data(), this_size); @@ -170,7 +170,7 @@ void AppendPieces(std::string* dest, std::initializer_list pieces) { size_t old_size = dest->size(); size_t total_size = old_size; - for (const absl::string_view piece : pieces) { + for (const absl::string_view& piece : pieces) { ASSERT_NO_OVERLAP(*dest, piece); total_size += piece.size(); } @@ -178,7 +178,7 @@ void AppendPieces(std::string* dest, char* const begin = &(*dest)[0]; char* out = begin + old_size; - for (const absl::string_view piece : pieces) { + for (const absl::string_view& piece : pieces) { const size_t this_size = piece.size(); if (this_size != 0) { memcpy(out, piece.data(), this_size); diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 05f5c041..c7968f06 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -39,6 +39,7 @@ #include // NOLINT(build/c++11) #include "absl/base/attributes.h" +#include "absl/base/call_once.h" #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/atomic_hook.h" @@ -58,7 +59,6 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; -using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -86,28 +86,6 @@ ABSL_CONST_INIT std::atomic synch_deadlock_detection( kDeadlockDetectionDefault); ABSL_CONST_INIT std::atomic synch_check_invariants(false); -// ------------------------------------------ spinlock support - -// Make sure read-only globals used in the Mutex code are contained on the -// same cacheline and cacheline aligned to eliminate any false sharing with -// other globals from this and other modules. -static struct MutexGlobals { - MutexGlobals() { - // Find machine-specific data needed for Delay() and - // TryAcquireWithSpinning(). This runs in the global constructor - // sequence, and before that zeros are safe values. - num_cpus = absl::base_internal::NumCPUs(); - spinloop_iterations = num_cpus > 1 ? 1500 : 0; - } - int num_cpus; - int spinloop_iterations; - // Pad this struct to a full cacheline to prevent false sharing. - char padding[ABSL_CACHELINE_SIZE - 2 * sizeof(int)]; -} ABSL_CACHELINE_ALIGNED mutex_globals; -static_assert( - sizeof(MutexGlobals) == ABSL_CACHELINE_SIZE, - "MutexGlobals must occupy an entire cacheline to prevent false sharing"); - ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook submit_profile_data; @@ -144,7 +122,22 @@ void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)) { symbolizer.Store(fn); } -// spinlock delay on iteration c. Returns new c. +struct ABSL_CACHELINE_ALIGNED MutexGlobals { + absl::once_flag once; + int num_cpus = 0; + int spinloop_iterations = 0; +}; + +static const MutexGlobals& GetMutexGlobals() { + ABSL_CONST_INIT static MutexGlobals data; + absl::base_internal::LowLevelCallOnce(&data.once, [&]() { + data.num_cpus = absl::base_internal::NumCPUs(); + data.spinloop_iterations = data.num_cpus > 1 ? 1500 : 0; + }); + return data; +} + +// Spinlock delay on iteration c. Returns new c. namespace { enum DelayMode { AGGRESSIVE, GENTLE }; }; @@ -154,22 +147,25 @@ static int Delay(int32_t c, DelayMode mode) { // gentle then spin only a few times before yielding. Aggressive spinning is // used to ensure that an Unlock() call, which must get the spin lock for // any thread to make progress gets it without undue delay. - int32_t limit = (mutex_globals.num_cpus > 1) ? - ((mode == AGGRESSIVE) ? 5000 : 250) : 0; + const int32_t limit = + GetMutexGlobals().num_cpus > 1 ? (mode == AGGRESSIVE ? 5000 : 250) : 0; if (c < limit) { - c++; // spin + // Spin. + c++; } else { ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0); - if (c == limit) { // yield once + if (c == limit) { + // Yield once. AbslInternalMutexYield(); c++; - } else { // then wait + } else { + // Then wait. absl::SleepFor(absl::Microseconds(10)); c = 0; } ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0); } - return (c); + return c; } // --------------------------Generic atomic ops @@ -1055,7 +1051,6 @@ static PerThreadSynch *DequeueAllWakeable(PerThreadSynch *head, // Try to remove thread s from the list of waiters on this mutex. // Does nothing if s is not on the waiter list. void Mutex::TryRemove(PerThreadSynch *s) { - SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); // acquire spinlock & lock if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait && @@ -1439,7 +1434,7 @@ void Mutex::AssertNotHeld() const { // Attempt to acquire *mu, and return whether successful. The implementation // may spin for a short while if the lock cannot be acquired immediately. static bool TryAcquireWithSpinning(std::atomic* mu) { - int c = mutex_globals.spinloop_iterations; + int c = GetMutexGlobals().spinloop_iterations; do { // do/while somewhat faster on AMD intptr_t v = mu->load(std::memory_order_relaxed); if ((v & (kMuReader|kMuEvent)) != 0) { @@ -1899,7 +1894,6 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { - SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -2019,7 +2013,6 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { - SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2335,7 +2328,6 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { - SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2434,7 +2426,6 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { - SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2595,7 +2586,6 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { - SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; -- cgit v1.2.3 From 55c04eb9203a93db1c0816adddf3182b45da5384 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 13 Jul 2020 12:10:09 -0700 Subject: Export of internal Abseil changes -- 69b3ab092ee0fef3d27f589e709280c341f006c6 by Greg Falcon : Import of CCTZ from GitHub. PiperOrigin-RevId: 321005878 -- 3a4038cd0cea6455453a7ae82f2de7e91d7e2bc1 by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 320994821 -- f9d9a93782924df6ffc351a271c239ca4bdff3c8 by Derek Mauro : Update Linux latest toolchains, most notably to GCC 10.1 This create a new "hybrid" docker image that includes the latest versions of both GCC and LLVM. Since the LLVM build targets Debian 10, but Debian 10 uses an older version of libstdc++ that doesn't have full C++20 support, the easiest solution is to use the GCC/Debian 10 base image from DockerHub and copy LLVM into it. This also includes fixes to get the build working with the new toolchains. PiperOrigin-RevId: 320991795 -- 43129cd66dc4439b36d85030800a3929f20d9f86 by Abseil Team : Rollback import of CCTZ from GitHub (breaks MSAN tests) - e87b391f0d10ae9c3d2e70e4a3633337d2c5e643 handle "slim" TZif files in TimeZoneInfo::ExtendTransitio... by Bradley White <14679271+devbww@users.noreply.github.com> PiperOrigin-RevId: 320978767 -- 2a343a55f297d433c1521920f0bd20ddd2dc71e8 by Derek Mauro : Use ABSL_HAVE_ATTRIBUTE in thread_annotations.h PiperOrigin-RevId: 320956378 -- f6f3e8333c9ef6e6441586be6587bbfb1c8c8127 by Gennadiy Rozental : Import of CCTZ from GitHub. PiperOrigin-RevId: 320952592 -- 3cc2bcce3533ac1233c0536232b07eea45fe8ed0 by Derek Mauro : Internal change PiperOrigin-RevId: 320862698 -- 4e22066476744609e42c475b55e3cbd874f04c39 by Gennadiy Rozental : Internal change PiperOrigin-RevId: 320461277 GitOrigin-RevId: 69b3ab092ee0fef3d27f589e709280c341f006c6 Change-Id: I36f547711e7078d52f2e0a1ff3f4c903056a2b9e --- WORKSPACE | 6 +- absl/BUILD.bazel | 5 +- absl/base/internal/low_level_scheduling.h | 28 +++ absl/base/thread_annotations.h | 128 ++++++---- .../container/fixed_array_exception_safety_test.cc | 3 +- absl/strings/internal/str_format/convert_test.cc | 3 +- absl/synchronization/mutex.cc | 33 ++- absl/time/internal/cctz/src/time_zone_info.cc | 257 +++++++++++---------- absl/time/internal/cctz/src/time_zone_info.h | 9 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 3 +- ci/linux_docker_containers.sh | 4 +- 11 files changed, 291 insertions(+), 188 deletions(-) (limited to 'absl/base/internal/low_level_scheduling.h') diff --git a/WORKSPACE b/WORKSPACE index 1a1da6c5..96338199 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -20,9 +20,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # GoogleTest/GoogleMock framework. Used by most unit-tests. http_archive( name = "com_google_googletest", - urls = ["https://github.com/google/googletest/archive/011959aafddcd30611003de96cfd8d7a7685c700.zip"], # 2020-05-14T00:36:05Z - strip_prefix = "googletest-011959aafddcd30611003de96cfd8d7a7685c700", - sha256 = "6a5d7d63cd6e0ad2a7130471105a3b83799a7a2b14ef7ec8d742b54f01a4833c", + urls = ["https://github.com/google/googletest/archive/8567b09290fe402cf01923e2131c5635b8ed851b.zip"], # 2020-06-12T22:24:28Z + strip_prefix = "googletest-8567b09290fe402cf01923e2131c5635b8ed851b", + sha256 = "9a8a166eb6a56c7b3d7b19dc2c946fe4778fd6f21c7a12368ad3b836d8f1be48", ) # Google benchmark. diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel index e45d15a5..1019ab5e 100644 --- a/absl/BUILD.bazel +++ b/absl/BUILD.bazel @@ -61,5 +61,8 @@ config_setting( config_setting( name = "wasm", - values = {"cpu": "wasm32"}, + values = { + "cpu": "wasm32", + }, + visibility = [":__subpackages__"], ) diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index ed0b4bfa..6ef79fbf 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -18,6 +18,7 @@ #ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ #define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ +#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/scheduling_mode.h" #include "absl/base/macros.h" @@ -29,6 +30,13 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN +class CondVar; +class Mutex; + +namespace synchronization_internal { +int MutexDelay(int32_t c, int mode); +} // namespace synchronization_internal + namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -76,9 +84,23 @@ class SchedulingGuard { bool disabled; }; + // A scoped helper to enable rescheduling temporarily. + // REQUIRES: destructor must run in same thread as constructor. + class ScopedEnable { + public: + ScopedEnable(); + ~ScopedEnable(); + + private: + int scheduling_disabled_depth_; + }; + // Access to SchedulingGuard is explicitly permitted. + friend class absl::CondVar; + friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; + friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode); SchedulingGuard(const SchedulingGuard&) = delete; SchedulingGuard& operator=(const SchedulingGuard&) = delete; @@ -100,6 +122,12 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) { return; } +inline SchedulingGuard::ScopedEnable::ScopedEnable() + : scheduling_disabled_depth_(0) {} +inline SchedulingGuard::ScopedEnable::~ScopedEnable() { + ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning"); +} + } // namespace base_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h index 6a7112df..e23fff1d 100644 --- a/absl/base/thread_annotations.h +++ b/absl/base/thread_annotations.h @@ -39,12 +39,6 @@ // TODO(mbonadei): Remove after the backward compatibility period. #include "absl/base/internal/thread_annotations.h" // IWYU pragma: export -#if defined(__clang__) -#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x)) -#else -#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) // no-op -#endif - // ABSL_GUARDED_BY() // // Documents if a shared field or global variable needs to be protected by a @@ -62,8 +56,11 @@ // int p1_ ABSL_GUARDED_BY(mu_); // ... // }; -#define ABSL_GUARDED_BY(x) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(guarded_by(x)) +#if ABSL_HAVE_ATTRIBUTE(guarded_by) +#define ABSL_GUARDED_BY(x) __attribute__((guarded_by(x))) +#else +#define ABSL_GUARDED_BY(x) +#endif // ABSL_PT_GUARDED_BY() // @@ -85,8 +82,11 @@ // // `q_`, guarded by `mu1_`, points to a shared memory location that is // // guarded by `mu2_`: // int *q_ ABSL_GUARDED_BY(mu1_) ABSL_PT_GUARDED_BY(mu2_); -#define ABSL_PT_GUARDED_BY(x) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(pt_guarded_by(x)) +#if ABSL_HAVE_ATTRIBUTE(pt_guarded_by) +#define ABSL_PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x))) +#else +#define ABSL_PT_GUARDED_BY(x) +#endif // ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE() // @@ -103,11 +103,17 @@ // // Mutex m1_; // Mutex m2_ ABSL_ACQUIRED_AFTER(m1_); -#define ABSL_ACQUIRED_AFTER(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_after(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(acquired_after) +#define ABSL_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) +#else +#define ABSL_ACQUIRED_AFTER(...) +#endif -#define ABSL_ACQUIRED_BEFORE(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_before(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(acquired_before) +#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) +#else +#define ABSL_ACQUIRED_BEFORE(...) +#endif // ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED() // @@ -132,20 +138,30 @@ // // void foo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... } // void bar() const ABSL_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... } -#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \ - exclusive_locks_required(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required) +#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \ + __attribute__((exclusive_locks_required(__VA_ARGS__))) +#else +#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) +#endif +#if ABSL_HAVE_ATTRIBUTE(shared_locks_required) #define ABSL_SHARED_LOCKS_REQUIRED(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_locks_required(__VA_ARGS__)) + __attribute__((shared_locks_required(__VA_ARGS__))) +#else +#define ABSL_SHARED_LOCKS_REQUIRED(...) +#endif // ABSL_LOCKS_EXCLUDED() // // Documents the locks acquired in the body of the function. These locks // cannot be held when calling this function (as Abseil's `Mutex` locks are // non-reentrant). -#define ABSL_LOCKS_EXCLUDED(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(locks_excluded(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(locks_excluded) +#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) +#else +#define ABSL_LOCKS_EXCLUDED(...) +#endif // ABSL_LOCK_RETURNED() // @@ -153,8 +169,7 @@ // a public getter method that returns a pointer to a private mutex should // be annotated with ABSL_LOCK_RETURNED. #if ABSL_HAVE_ATTRIBUTE(lock_returned) -#define ABSL_LOCK_RETURNED(x) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lock_returned(x)) +#define ABSL_LOCK_RETURNED(x) __attribute__((lock_returned(x))) #else #define ABSL_LOCK_RETURNED(x) #endif @@ -162,7 +177,11 @@ // ABSL_LOCKABLE // // Documents if a class/type is a lockable type (such as the `Mutex` class). -#define ABSL_LOCKABLE ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lockable) +#if ABSL_HAVE_ATTRIBUTE(lockable) +#define ABSL_LOCKABLE __attribute__((lockable)) +#else +#define ABSL_LOCKABLE +#endif // ABSL_SCOPED_LOCKABLE // @@ -171,30 +190,43 @@ // acquired, and the destructor should use `UNLOCK_FUNCTION()` with no // arguments; the analysis will assume that the destructor unlocks whatever the // constructor locked. -#define ABSL_SCOPED_LOCKABLE \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(scoped_lockable) +#if ABSL_HAVE_ATTRIBUTE(scoped_lockable) +#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable)) +#else +#define ABSL_SCOPED_LOCKABLE +#endif // ABSL_EXCLUSIVE_LOCK_FUNCTION() // // Documents functions that acquire a lock in the body of a function, and do // not release it. -#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \ - exclusive_lock_function(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(exclusive_lock_function) +#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \ + __attribute__((exclusive_lock_function(__VA_ARGS__))) +#else +#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) +#endif // ABSL_SHARED_LOCK_FUNCTION() // // Documents functions that acquire a shared (reader) lock in the body of a // function, and do not release it. +#if ABSL_HAVE_ATTRIBUTE(shared_lock_function) #define ABSL_SHARED_LOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_lock_function(__VA_ARGS__)) + __attribute__((shared_lock_function(__VA_ARGS__))) +#else +#define ABSL_SHARED_LOCK_FUNCTION(...) +#endif // ABSL_UNLOCK_FUNCTION() // // Documents functions that expect a lock to be held on entry to the function, // and release it in the body of the function. -#define ABSL_UNLOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(unlock_function(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(unlock_function) +#define ABSL_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) +#else +#define ABSL_UNLOCK_FUNCTION(...) +#endif // ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION() // @@ -204,31 +236,49 @@ // success, or `false` for functions that return `false` on success. The second // argument specifies the mutex that is locked on success. If unspecified, this // mutex is assumed to be `this`. +#if ABSL_HAVE_ATTRIBUTE(exclusive_trylock_function) #define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \ - exclusive_trylock_function(__VA_ARGS__)) + __attribute__((exclusive_trylock_function(__VA_ARGS__))) +#else +#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) +#endif -#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \ - shared_trylock_function(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(shared_trylock_function) +#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \ + __attribute__((shared_trylock_function(__VA_ARGS__))) +#else +#define ABSL_SHARED_TRYLOCK_FUNCTION(...) +#endif // ABSL_ASSERT_EXCLUSIVE_LOCK() / ABSL_ASSERT_SHARED_LOCK() // // Documents functions that dynamically check to see if a lock is held, and fail // if it is not held. +#if ABSL_HAVE_ATTRIBUTE(assert_exclusive_lock) #define ABSL_ASSERT_EXCLUSIVE_LOCK(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_exclusive_lock(__VA_ARGS__)) + __attribute__((assert_exclusive_lock(__VA_ARGS__))) +#else +#define ABSL_ASSERT_EXCLUSIVE_LOCK(...) +#endif +#if ABSL_HAVE_ATTRIBUTE(assert_shared_lock) #define ABSL_ASSERT_SHARED_LOCK(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_shared_lock(__VA_ARGS__)) + __attribute__((assert_shared_lock(__VA_ARGS__))) +#else +#define ABSL_ASSERT_SHARED_LOCK(...) +#endif // ABSL_NO_THREAD_SAFETY_ANALYSIS // // Turns off thread safety checking within the body of a particular function. // This annotation is used to mark functions that are known to be correct, but // the locking behavior is more complicated than the analyzer can handle. +#if ABSL_HAVE_ATTRIBUTE(no_thread_safety_analysis) #define ABSL_NO_THREAD_SAFETY_ANALYSIS \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(no_thread_safety_analysis) + __attribute__((no_thread_safety_analysis)) +#else +#define ABSL_NO_THREAD_SAFETY_ANALYSIS +#endif //------------------------------------------------------------------------------ // Tool-Supplied Annotations diff --git a/absl/container/fixed_array_exception_safety_test.cc b/absl/container/fixed_array_exception_safety_test.cc index a5bb009d..e5f59299 100644 --- a/absl/container/fixed_array_exception_safety_test.cc +++ b/absl/container/fixed_array_exception_safety_test.cc @@ -150,8 +150,7 @@ TEST(FixedArrayExceptionSafety, InitListConstructorWithAlloc) { template testing::AssertionResult ReadMemory(FixedArrT* fixed_arr) { - // Marked volatile to prevent optimization. Used for running asan tests. - volatile int sum = 0; + int sum = 0; for (const auto& thrower : *fixed_arr) { sum += thrower.Get(); } diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 5ee5fbc9..634ee78b 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -1155,7 +1155,8 @@ TEST_F(FormatConvertTest, IntAsDouble) { {__LINE__, StrPrint("%.12a", dx), "%.12a"}, }; if (native_traits.hex_float_uses_minimal_precision_when_not_specified) { - expect.push_back({__LINE__, StrPrint("%12a", dx), "%12a"}); + Expectation ex = {__LINE__, StrPrint("%12a", dx), "%12a"}; + expect.push_back(ex); } for (const Expectation &e : expect) { SCOPED_TRACE(e.line); diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index c7968f06..aafeb674 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -59,6 +59,7 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; +using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -141,7 +142,9 @@ static const MutexGlobals& GetMutexGlobals() { namespace { enum DelayMode { AGGRESSIVE, GENTLE }; }; -static int Delay(int32_t c, DelayMode mode) { + +namespace synchronization_internal { +int MutexDelay(int32_t c, int mode) { // If this a uniprocessor, only yield/sleep. Otherwise, if the mode is // aggressive then spin many times before yielding. If the mode is // gentle then spin only a few times before yielding. Aggressive spinning is @@ -153,6 +156,7 @@ static int Delay(int32_t c, DelayMode mode) { // Spin. c++; } else { + SchedulingGuard::ScopedEnable enable_rescheduling; ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0); if (c == limit) { // Yield once. @@ -167,6 +171,7 @@ static int Delay(int32_t c, DelayMode mode) { } return c; } +} // namespace synchronization_internal // --------------------------Generic atomic ops // Ensure that "(*pv & bits) == bits" by doing an atomic update of "*pv" to @@ -1051,6 +1056,7 @@ static PerThreadSynch *DequeueAllWakeable(PerThreadSynch *head, // Try to remove thread s from the list of waiters on this mutex. // Does nothing if s is not on the waiter list. void Mutex::TryRemove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); // acquire spinlock & lock if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait && @@ -1115,7 +1121,7 @@ ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) { this->TryRemove(s); int c = 0; while (s->next != nullptr) { - c = Delay(c, GENTLE); + c = synchronization_internal::MutexDelay(c, GENTLE); this->TryRemove(s); } if (kDebugMode) { @@ -1894,6 +1900,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -1995,7 +2002,8 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { ABSL_RAW_CHECK( waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors, "detected illegal recursion into Mutex code"); - c = Delay(c, GENTLE); // delay, then try again + // delay, then try again + c = synchronization_internal::MutexDelay(c, GENTLE); } ABSL_RAW_CHECK( waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors, @@ -2013,6 +2021,7 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2289,7 +2298,8 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { mu_.store(nv, std::memory_order_release); break; // out of for(;;)-loop } - c = Delay(c, AGGRESSIVE); // aggressive here; no one can proceed till we do + // aggressive here; no one can proceed till we do + c = synchronization_internal::MutexDelay(c, AGGRESSIVE); } // end of for(;;)-loop if (wake_list != kPerThreadSynchNull) { @@ -2328,6 +2338,7 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2377,7 +2388,7 @@ void Mutex::Fer(PerThreadSynch *w) { return; } } - c = Delay(c, GENTLE); + c = synchronization_internal::MutexDelay(c, GENTLE); } } @@ -2426,6 +2437,7 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2454,7 +2466,8 @@ void CondVar::Remove(PerThreadSynch *s) { std::memory_order_release); return; } else { - c = Delay(c, GENTLE); // try again after a delay + // try again after a delay + c = synchronization_internal::MutexDelay(c, GENTLE); } } } @@ -2487,7 +2500,7 @@ static void CondVarEnqueue(SynchWaitParams *waitp) { !cv_word->compare_exchange_weak(v, v | kCvSpin, std::memory_order_acquire, std::memory_order_relaxed)) { - c = Delay(c, GENTLE); + c = synchronization_internal::MutexDelay(c, GENTLE); v = cv_word->load(std::memory_order_relaxed); } ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, "waiting when shouldn't be"); @@ -2586,6 +2599,7 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { + SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; @@ -2618,7 +2632,7 @@ void CondVar::Signal() { ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); return; } else { - c = Delay(c, GENTLE); + c = synchronization_internal::MutexDelay(c, GENTLE); } } ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); @@ -2655,7 +2669,8 @@ void CondVar::SignalAll () { ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); return; } else { - c = Delay(c, GENTLE); // try again after a delay + // try again after a delay + c = synchronization_internal::MutexDelay(c, GENTLE); } } ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index 665fb424..7ccda113 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -83,6 +82,27 @@ const std::int_least32_t kSecsPerYear[2] = { 366 * kSecsPerDay, }; +// Convert a cctz::weekday to a POSIX TZ weekday number (0==Sun, ..., 6=Sat). +inline int ToPosixWeekday(weekday wd) { + switch (wd) { + case weekday::sunday: + return 0; + case weekday::monday: + return 1; + case weekday::tuesday: + return 2; + case weekday::wednesday: + return 3; + case weekday::thursday: + return 4; + case weekday::friday: + return 5; + case weekday::saturday: + return 6; + } + return 0; /*NOTREACHED*/ +} + // Single-byte, unsigned numeric values are encoded directly. inline std::uint_fast8_t Decode8(const char* cp) { return static_cast(*cp) & 0xff; @@ -188,15 +208,13 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { tt.is_dst = false; tt.abbr_index = 0; - // We temporarily add some redundant, contemporary (2013 through 2023) + // We temporarily add some redundant, contemporary (2015 through 2025) // transitions for performance reasons. See TimeZoneInfo::LocalTime(). // TODO: Fix the performance issue and remove the extra transitions. transitions_.clear(); transitions_.reserve(12); for (const std::int_fast64_t unix_time : { - -(1LL << 59), // BIG_BANG - 1356998400LL, // 2013-01-01T00:00:00+00:00 - 1388534400LL, // 2014-01-01T00:00:00+00:00 + -(1LL << 59), // a "first half" transition 1420070400LL, // 2015-01-01T00:00:00+00:00 1451606400LL, // 2016-01-01T00:00:00+00:00 1483228800LL, // 2017-01-01T00:00:00+00:00 @@ -206,7 +224,8 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { 1609459200LL, // 2021-01-01T00:00:00+00:00 1640995200LL, // 2022-01-01T00:00:00+00:00 1672531200LL, // 2023-01-01T00:00:00+00:00 - 2147483647LL, // 2^31 - 1 + 1704067200LL, // 2024-01-01T00:00:00+00:00 + 1735689600LL, // 2025-01-01T00:00:00+00:00 }) { Transition& tr(*transitions_.emplace(transitions_.end())); tr.unix_time = unix_time; @@ -217,8 +236,8 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { default_transition_type_ = 0; abbreviations_ = FixedOffsetToAbbr(offset); - abbreviations_.append(1, '\0'); // add NUL - future_spec_.clear(); // never needed for a fixed-offset zone + abbreviations_.append(1, '\0'); + future_spec_.clear(); // never needed for a fixed-offset zone extended_ = false; tt.civil_max = LocalTime(seconds::max().count(), tt).cs; @@ -259,21 +278,6 @@ std::size_t TimeZoneInfo::Header::DataLength(std::size_t time_len) const { return len; } -// Check that the TransitionType has the expected offset/is_dst/abbreviation. -void TimeZoneInfo::CheckTransition(const std::string& name, - const TransitionType& tt, - std::int_fast32_t offset, bool is_dst, - const std::string& abbr) const { - if (tt.utc_offset != offset || tt.is_dst != is_dst || - &abbreviations_[tt.abbr_index] != abbr) { - std::clog << name << ": Transition" - << " offset=" << tt.utc_offset << "/" - << (tt.is_dst ? "DST" : "STD") - << "/abbr=" << &abbreviations_[tt.abbr_index] - << " does not match POSIX spec '" << future_spec_ << "'\n"; - } -} - // zic(8) can generate no-op transitions when a zone changes rules at an // instant when there is actually no discontinuity. So we check whether // two transitions have equivalent types (same offset/is_dst/abbr). @@ -282,117 +286,108 @@ bool TimeZoneInfo::EquivTransitions(std::uint_fast8_t tt1_index, if (tt1_index == tt2_index) return true; const TransitionType& tt1(transition_types_[tt1_index]); const TransitionType& tt2(transition_types_[tt2_index]); - if (tt1.is_dst != tt2.is_dst) return false; if (tt1.utc_offset != tt2.utc_offset) return false; + if (tt1.is_dst != tt2.is_dst) return false; if (tt1.abbr_index != tt2.abbr_index) return false; return true; } +// Find/make a transition type with these attributes. +bool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, + const std::string& abbr, + std::uint_fast8_t* index) { + std::size_t type_index = 0; + std::size_t abbr_index = abbreviations_.size(); + for (; type_index != transition_types_.size(); ++type_index) { + const TransitionType& tt(transition_types_[type_index]); + const char* tt_abbr = &abbreviations_[tt.abbr_index]; + if (tt_abbr == abbr) abbr_index = tt.abbr_index; + if (tt.utc_offset == utc_offset && tt.is_dst == is_dst) { + if (abbr_index == tt.abbr_index) break; // reuse + } + } + if (type_index > 255 || abbr_index > 255) { + // No index space (8 bits) available for a new type or abbreviation. + return false; + } + if (type_index == transition_types_.size()) { + TransitionType& tt(*transition_types_.emplace(transition_types_.end())); + tt.utc_offset = static_cast(utc_offset); + tt.is_dst = is_dst; + if (abbr_index == abbreviations_.size()) { + abbreviations_.append(abbr); + abbreviations_.append(1, '\0'); + } + tt.abbr_index = static_cast(abbr_index); + } + *index = static_cast(type_index); + return true; +} + // Use the POSIX-TZ-environment-variable-style string to handle times // in years after the last transition stored in the zoneinfo data. -void TimeZoneInfo::ExtendTransitions(const std::string& name, - const Header& hdr) { +bool TimeZoneInfo::ExtendTransitions() { extended_ = false; - bool extending = !future_spec_.empty(); + if (future_spec_.empty()) return true; // last transition prevails PosixTimeZone posix; - if (extending && !ParsePosixSpec(future_spec_, &posix)) { - std::clog << name << ": Failed to parse '" << future_spec_ << "'\n"; - extending = false; - } - - if (extending && posix.dst_abbr.empty()) { // std only - // The future specification should match the last/default transition, - // and that means that handling the future will fall out naturally. - std::uint_fast8_t index = default_transition_type_; - if (hdr.timecnt != 0) index = transitions_[hdr.timecnt - 1].type_index; - const TransitionType& tt(transition_types_[index]); - CheckTransition(name, tt, posix.std_offset, false, posix.std_abbr); - extending = false; - } - - if (extending && hdr.timecnt < 2) { - std::clog << name << ": Too few transitions for POSIX spec\n"; - extending = false; - } - - if (!extending) { - // Ensure that there is always a transition in the second half of the - // time line (the BIG_BANG transition is in the first half) so that the - // signed difference between a civil_second and the civil_second of its - // previous transition is always representable, without overflow. - const Transition& last(transitions_.back()); - if (last.unix_time < 0) { - const std::uint_fast8_t type_index = last.type_index; - Transition& tr(*transitions_.emplace(transitions_.end())); - tr.unix_time = 2147483647; // 2038-01-19T03:14:07+00:00 - tr.type_index = type_index; - } - return; // last transition wins + if (!ParsePosixSpec(future_spec_, &posix)) return false; + + // Find transition type for the future std specification. + std::uint_fast8_t std_ti; + if (!GetTransitionType(posix.std_offset, false, posix.std_abbr, &std_ti)) + return false; + + if (posix.dst_abbr.empty()) { // std only + // The future specification should match the last transition, and + // that means that handling the future will fall out naturally. + return EquivTransitions(transitions_.back().type_index, std_ti); } + // Find transition type for the future dst specification. + std::uint_fast8_t dst_ti; + if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti)) + return false; + // Extend the transitions for an additional 400 years using the // future specification. Years beyond those can be handled by // mapping back to a cycle-equivalent year within that range. - // zic(8) should probably do this so that we don't have to. - // TODO: Reduce the extension by the number of compatible - // transitions already in place. - transitions_.reserve(hdr.timecnt + 400 * 2 + 1); - transitions_.resize(hdr.timecnt + 400 * 2); + // We may need two additional transitions for the current year. + transitions_.reserve(transitions_.size() + 400 * 2 + 2); extended_ = true; - // The future specification should match the last two transitions, - // and those transitions should have different is_dst flags. Note - // that nothing says the UTC offset used by the is_dst transition - // must be greater than that used by the !is_dst transition. (See - // Europe/Dublin, for example.) - const Transition* tr0 = &transitions_[hdr.timecnt - 1]; - const Transition* tr1 = &transitions_[hdr.timecnt - 2]; - const TransitionType* tt0 = &transition_types_[tr0->type_index]; - const TransitionType* tt1 = &transition_types_[tr1->type_index]; - const TransitionType& dst(tt0->is_dst ? *tt0 : *tt1); - const TransitionType& std(tt0->is_dst ? *tt1 : *tt0); - CheckTransition(name, dst, posix.dst_offset, true, posix.dst_abbr); - CheckTransition(name, std, posix.std_offset, false, posix.std_abbr); - - // Add the transitions to tr1 and back to tr0 for each extra year. - last_year_ = LocalTime(tr0->unix_time, *tt0).cs.year(); + const Transition& last(transitions_.back()); + const std::int_fast64_t last_time = last.unix_time; + const TransitionType& last_tt(transition_types_[last.type_index]); + last_year_ = LocalTime(last_time, last_tt).cs.year(); bool leap_year = IsLeap(last_year_); - const civil_day jan1(last_year_, 1, 1); - std::int_fast64_t jan1_time = civil_second(jan1) - civil_second(); - int jan1_weekday = (static_cast(get_weekday(jan1)) + 1) % 7; - Transition* tr = &transitions_[hdr.timecnt]; // next trans to fill - if (LocalTime(tr1->unix_time, *tt1).cs.year() != last_year_) { - // Add a single extra transition to align to a calendar year. - transitions_.resize(transitions_.size() + 1); - assert(tr == &transitions_[hdr.timecnt]); // no reallocation - const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start); - std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1); - tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset; - tr++->type_index = tr1->type_index; - tr0 = &transitions_[hdr.timecnt]; - tr1 = &transitions_[hdr.timecnt - 1]; - tt0 = &transition_types_[tr0->type_index]; - tt1 = &transition_types_[tr1->type_index]; - } - const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start); - const PosixTransition& pt0(tt0->is_dst ? posix.dst_start : posix.dst_end); - for (const year_t limit = last_year_ + 400; last_year_ < limit;) { - last_year_ += 1; // an additional year of generated transitions + const civil_second jan1(last_year_); + std::int_fast64_t jan1_time = jan1 - civil_second(); + int jan1_weekday = ToPosixWeekday(get_weekday(jan1)); + + Transition dst = {0, dst_ti, civil_second(), civil_second()}; + Transition std = {0, std_ti, civil_second(), civil_second()}; + for (const year_t limit = last_year_ + 400;; ++last_year_) { + auto dst_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_start); + auto std_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_end); + dst.unix_time = jan1_time + dst_trans_off - posix.std_offset; + std.unix_time = jan1_time + std_trans_off - posix.dst_offset; + const auto* ta = dst.unix_time < std.unix_time ? &dst : &std; + const auto* tb = dst.unix_time < std.unix_time ? &std : &dst; + if (last_time < tb->unix_time) { + if (last_time < ta->unix_time) transitions_.push_back(*ta); + transitions_.push_back(*tb); + } + if (last_year_ == limit) break; jan1_time += kSecsPerYear[leap_year]; jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7; - leap_year = !leap_year && IsLeap(last_year_); - std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1); - tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset; - tr++->type_index = tr1->type_index; - std::int_fast64_t tr0_offset = TransOffset(leap_year, jan1_weekday, pt0); - tr->unix_time = jan1_time + tr0_offset - tt1->utc_offset; - tr++->type_index = tr0->type_index; - } - assert(tr == &transitions_[0] + transitions_.size()); + leap_year = !leap_year && IsLeap(last_year_ + 1); + } + + return true; } -bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { +bool TimeZoneInfo::Load(ZoneInfoSource* zip) { // Read and validate the header. tzhead tzh; if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; @@ -430,7 +425,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { const char* bp = tbuf.data(); // Decode and validate the transitions. - transitions_.reserve(hdr.timecnt + 2); // We might add a couple. + transitions_.reserve(hdr.timecnt + 2); transitions_.resize(hdr.timecnt); for (std::size_t i = 0; i != hdr.timecnt; ++i) { transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp); @@ -449,6 +444,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { } // Decode and validate the transition types. + transition_types_.reserve(hdr.typecnt + 2); transition_types_.resize(hdr.typecnt); for (std::size_t i = 0; i != hdr.typecnt; ++i) { transition_types_[i].utc_offset = @@ -475,6 +471,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { } // Copy all the abbreviations. + abbreviations_.reserve(hdr.charcnt + 10); abbreviations_.assign(bp, hdr.charcnt); bp += hdr.charcnt; @@ -525,19 +522,29 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { transitions_.resize(hdr.timecnt); // Ensure that there is always a transition in the first half of the - // time line (the second half is handled in ExtendTransitions()) so that - // the signed difference between a civil_second and the civil_second of - // its previous transition is always representable, without overflow. - // A contemporary zic will usually have already done this for us. + // time line (the second half is handled below) so that the signed + // difference between a civil_second and the civil_second of its + // previous transition is always representable, without overflow. if (transitions_.empty() || transitions_.front().unix_time >= 0) { Transition& tr(*transitions_.emplace(transitions_.begin())); - tr.unix_time = -(1LL << 59); // see tz/zic.c "BIG_BANG" + tr.unix_time = -(1LL << 59); // -18267312070-10-26T17:01:52+00:00 tr.type_index = default_transition_type_; - hdr.timecnt += 1; } // Extend the transitions using the future specification. - ExtendTransitions(name, hdr); + if (!ExtendTransitions()) return false; + + // Ensure that there is always a transition in the second half of the + // time line (the first half is handled above) so that the signed + // difference between a civil_second and the civil_second of its + // previous transition is always representable, without overflow. + const Transition& last(transitions_.back()); + if (last.unix_time < 0) { + const std::uint_fast8_t type_index = last.type_index; + Transition& tr(*transitions_.emplace(transitions_.end())); + tr.unix_time = 2147483647; // 2038-01-19T03:14:07+00:00 + tr.type_index = type_index; + } // Compute the local civil time for each transition and the preceding // second. These will be used for reverse conversions in MakeTime(). @@ -723,7 +730,7 @@ bool TimeZoneInfo::Load(const std::string& name) { if (auto zip = AndroidZoneInfoSource::Open(name)) return zip; return nullptr; }); - return zip != nullptr && Load(name, zip.get()); + return zip != nullptr && Load(zip.get()); } // BreakTime() translation for a particular transition type. @@ -897,8 +904,8 @@ bool TimeZoneInfo::NextTransition(const time_point& tp, const Transition* begin = &transitions_[0]; const Transition* end = begin + transitions_.size(); if (begin->unix_time <= -(1LL << 59)) { - // Do not report the BIG_BANG found in recent zoneinfo data as it is - // really a sentinel, not a transition. See tz/zic.c. + // Do not report the BIG_BANG found in some zoneinfo data as it is + // really a sentinel, not a transition. See pre-2018f tz/zic.c. ++begin; } std::int_fast64_t unix_time = ToUnixSeconds(tp); @@ -923,8 +930,8 @@ bool TimeZoneInfo::PrevTransition(const time_point& tp, const Transition* begin = &transitions_[0]; const Transition* end = begin + transitions_.size(); if (begin->unix_time <= -(1LL << 59)) { - // Do not report the BIG_BANG found in recent zoneinfo data as it is - // really a sentinel, not a transition. See tz/zic.c. + // Do not report the BIG_BANG found in some zoneinfo data as it is + // really a sentinel, not a transition. See pre-2018f tz/zic.c. ++begin; } std::int_fast64_t unix_time = ToUnixSeconds(tp); diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h index 2a10c06c..068e34be 100644 --- a/absl/time/internal/cctz/src/time_zone_info.h +++ b/absl/time/internal/cctz/src/time_zone_info.h @@ -95,15 +95,14 @@ class TimeZoneInfo : public TimeZoneIf { std::size_t DataLength(std::size_t time_len) const; }; - void CheckTransition(const std::string& name, const TransitionType& tt, - std::int_fast32_t offset, bool is_dst, - const std::string& abbr) const; + bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, + const std::string& abbr, std::uint_fast8_t* index); bool EquivTransitions(std::uint_fast8_t tt1_index, std::uint_fast8_t tt2_index) const; - void ExtendTransitions(const std::string& name, const Header& hdr); + bool ExtendTransitions(); bool ResetToBuiltinUTC(const seconds& offset); - bool Load(const std::string& name, ZoneInfoSource* zip); + bool Load(ZoneInfoSource* zip); // Helpers for BreakTime() and MakeTime(). time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 0192ee49..4e490676 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -71,15 +71,16 @@ for std in ${STD}; do -e CC="/opt/llvm/clang/bin/clang" \ -e BAZEL_COMPILER="llvm" \ -e BAZEL_CXXOPTS="-std=${std}" \ - -e CPLUS_INCLUDE_PATH="/usr/include/c++/8" \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ /usr/local/bin/bazel test ... \ --compilation_mode="${compilation_mode}" \ + --copt="--gcc-toolchain=/usr/local" \ --copt="${exceptions_mode}" \ --copt=-Werror \ --define="absl=1" \ --keep_going \ + --linkopt="--gcc-toolchain=/usr/local" \ --show_timestamps \ --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ diff --git a/ci/linux_docker_containers.sh b/ci/linux_docker_containers.sh index b652071f..483ce2a2 100644 --- a/ci/linux_docker_containers.sh +++ b/ci/linux_docker_containers.sh @@ -16,6 +16,6 @@ # Test scripts should source this file to get the identifiers. readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20191016" -readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200706" -readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20200319" +readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20200710" +readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20200710" readonly LINUX_GCC_49_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018" -- cgit v1.2.3 From 2e5f2bcfd9adef0a40cbfdc7d92e24e97dad8776 Mon Sep 17 00:00:00 2001 From: Kohei Otsuka <13173186+rjhcnf@users.noreply.github.com> Date: Thu, 5 Nov 2020 18:13:58 +0100 Subject: moved deleted functions to public for better compiler errors. (#828) * Update low_level_scheduling.h * Update low_level_scheduling.h * Update low_level_scheduling.h * Update low_level_scheduling.h --- absl/base/internal/low_level_scheduling.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'absl/base/internal/low_level_scheduling.h') diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 6ef79fbf..9baccc06 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -61,6 +61,8 @@ class SchedulingGuard { public: // Returns true iff the calling thread may be cooperatively rescheduled. static bool ReschedulingIsAllowed(); + SchedulingGuard(const SchedulingGuard&) = delete; + SchedulingGuard& operator=(const SchedulingGuard&) = delete; private: // Disable cooperative rescheduling of the calling thread. It may still @@ -101,9 +103,6 @@ class SchedulingGuard { friend class SchedulingHelper; friend class SpinLock; friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode); - - SchedulingGuard(const SchedulingGuard&) = delete; - SchedulingGuard& operator=(const SchedulingGuard&) = delete; }; //------------------------------------------------------------------------------ -- cgit v1.2.3