summaryrefslogtreecommitdiff
path: root/abseil-cpp/absl/base
diff options
context:
space:
mode:
Diffstat (limited to 'abseil-cpp/absl/base')
-rw-r--r--abseil-cpp/absl/base/BUILD.bazel193
-rw-r--r--abseil-cpp/absl/base/CMakeLists.txt209
-rw-r--r--abseil-cpp/absl/base/attributes.h267
-rw-r--r--abseil-cpp/absl/base/call_once.h13
-rw-r--r--abseil-cpp/absl/base/casts.h123
-rw-r--r--abseil-cpp/absl/base/config.h457
-rw-r--r--abseil-cpp/absl/base/dynamic_annotations.h86
-rw-r--r--abseil-cpp/absl/base/exception_safety_testing_test.cc12
-rw-r--r--abseil-cpp/absl/base/internal/atomic_hook_test_helper.h6
-rw-r--r--abseil-cpp/absl/base/internal/bits.h219
-rw-r--r--abseil-cpp/absl/base/internal/bits_test.cc97
-rw-r--r--abseil-cpp/absl/base/internal/cycleclock.cc54
-rw-r--r--abseil-cpp/absl/base/internal/cycleclock.h54
-rw-r--r--abseil-cpp/absl/base/internal/cycleclock_config.h55
-rw-r--r--abseil-cpp/absl/base/internal/direct_mmap.h18
-rw-r--r--abseil-cpp/absl/base/internal/endian.h140
-rw-r--r--abseil-cpp/absl/base/internal/exception_safety_testing.h28
-rw-r--r--abseil-cpp/absl/base/internal/exponential_biased.cc93
-rw-r--r--abseil-cpp/absl/base/internal/exponential_biased.h130
-rw-r--r--abseil-cpp/absl/base/internal/exponential_biased_test.cc199
-rw-r--r--abseil-cpp/absl/base/internal/fast_type_id.h2
-rw-r--r--abseil-cpp/absl/base/internal/inline_variable.h6
-rw-r--r--abseil-cpp/absl/base/internal/inline_variable_testing.h6
-rw-r--r--abseil-cpp/absl/base/internal/invoke.h54
-rw-r--r--abseil-cpp/absl/base/internal/low_level_alloc.cc93
-rw-r--r--abseil-cpp/absl/base/internal/low_level_alloc.h5
-rw-r--r--abseil-cpp/absl/base/internal/low_level_alloc_test.cc30
-rw-r--r--abseil-cpp/absl/base/internal/low_level_scheduling.h5
-rw-r--r--abseil-cpp/absl/base/internal/nullability_impl.h106
-rw-r--r--abseil-cpp/absl/base/internal/periodic_sampler.cc53
-rw-r--r--abseil-cpp/absl/base/internal/periodic_sampler.h211
-rw-r--r--abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc79
-rw-r--r--abseil-cpp/absl/base/internal/periodic_sampler_test.cc177
-rw-r--r--abseil-cpp/absl/base/internal/prefetch.h137
-rw-r--r--abseil-cpp/absl/base/internal/prefetch_test.cc43
-rw-r--r--abseil-cpp/absl/base/internal/raw_logging.cc146
-rw-r--r--abseil-cpp/absl/base/internal/raw_logging.h96
-rw-r--r--abseil-cpp/absl/base/internal/spinlock.cc22
-rw-r--r--abseil-cpp/absl/base/internal/spinlock.h39
-rw-r--r--abseil-cpp/absl/base/internal/spinlock_akaros.inc4
-rw-r--r--abseil-cpp/absl/base/internal/spinlock_linux.inc13
-rw-r--r--abseil-cpp/absl/base/internal/spinlock_posix.inc4
-rw-r--r--abseil-cpp/absl/base/internal/spinlock_wait.h24
-rw-r--r--abseil-cpp/absl/base/internal/spinlock_win32.inc15
-rw-r--r--abseil-cpp/absl/base/internal/strerror.cc10
-rw-r--r--abseil-cpp/absl/base/internal/strerror_test.cc6
-rw-r--r--abseil-cpp/absl/base/internal/sysinfo.cc182
-rw-r--r--abseil-cpp/absl/base/internal/sysinfo_test.cc12
-rw-r--r--abseil-cpp/absl/base/internal/thread_annotations.h9
-rw-r--r--abseil-cpp/absl/base/internal/thread_identity.cc35
-rw-r--r--abseil-cpp/absl/base/internal/thread_identity.h128
-rw-r--r--abseil-cpp/absl/base/internal/thread_identity_test.cc2
-rw-r--r--abseil-cpp/absl/base/internal/throw_delegate.cc153
-rw-r--r--abseil-cpp/absl/base/internal/unaligned_access.h76
-rw-r--r--abseil-cpp/absl/base/internal/unscaledcycleclock.cc38
-rw-r--r--abseil-cpp/absl/base/internal/unscaledcycleclock.h52
-rw-r--r--abseil-cpp/absl/base/internal/unscaledcycleclock_config.h62
-rw-r--r--abseil-cpp/absl/base/invoke_test.cc102
-rw-r--r--abseil-cpp/absl/base/log_severity.cc28
-rw-r--r--abseil-cpp/absl/base/log_severity.h59
-rw-r--r--abseil-cpp/absl/base/log_severity_test.cc49
-rw-r--r--abseil-cpp/absl/base/macros.h14
-rw-r--r--abseil-cpp/absl/base/nullability.h224
-rw-r--r--abseil-cpp/absl/base/nullability_test.cc129
-rw-r--r--abseil-cpp/absl/base/optimization.h109
-rw-r--r--abseil-cpp/absl/base/options.h16
-rw-r--r--abseil-cpp/absl/base/policy_checks.h28
-rw-r--r--abseil-cpp/absl/base/port.h1
-rw-r--r--abseil-cpp/absl/base/prefetch.h198
-rw-r--r--abseil-cpp/absl/base/prefetch_test.cc64
-rw-r--r--abseil-cpp/absl/base/spinlock_test_common.cc41
-rw-r--r--abseil-cpp/absl/base/thread_annotations.h6
-rw-r--r--abseil-cpp/absl/base/throw_delegate_test.cc74
73 files changed, 3244 insertions, 2486 deletions
diff --git a/abseil-cpp/absl/base/BUILD.bazel b/abseil-cpp/absl/base/BUILD.bazel
index 9d96abe..fb008db 100644
--- a/abseil-cpp/absl/base/BUILD.bazel
+++ b/abseil-cpp/absl/base/BUILD.bazel
@@ -14,7 +14,6 @@
# limitations under the License.
#
-load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -64,6 +63,18 @@ cc_library(
)
cc_library(
+ name = "nullability",
+ srcs = ["internal/nullability_impl.h"],
+ hdrs = ["nullability.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":core_headers",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_library(
name = "raw_logging_internal",
srcs = ["internal/raw_logging.cc"],
hdrs = ["internal/raw_logging.h"],
@@ -76,6 +87,7 @@ cc_library(
":atomic_hook",
":config",
":core_headers",
+ ":errno_saver",
":log_severity",
],
)
@@ -114,6 +126,23 @@ cc_library(
)
cc_library(
+ name = "cycleclock_internal",
+ hdrs = [
+ "internal/cycleclock_config.h",
+ "internal/unscaledcycleclock_config.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [
+ ":base_internal",
+ ":config",
+ ],
+)
+
+cc_library(
name = "dynamic_annotations",
srcs = [
"internal/dynamic_annotations.h",
@@ -158,9 +187,12 @@ cc_library(
"internal/direct_mmap.h",
"internal/low_level_alloc.h",
],
- copts = ABSL_DEFAULT_COPTS,
+ copts = ABSL_DEFAULT_COPTS + select({
+ "//conditions:default": [],
+ }),
linkopts = select({
- "//absl:windows": [],
+ "//absl:msvc_compiler": [],
+ "//absl:clang-cl_compiler": [],
"//absl:wasm": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
@@ -220,9 +252,16 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = select({
- "//absl:windows": [
+ "//absl:msvc_compiler": [
"-DEFAULTLIB:advapi32.lib",
],
+ "//absl:clang-cl_compiler": [
+ "-DEFAULTLIB:advapi32.lib",
+ ],
+ "//absl:mingw_compiler": [
+ "-DEFAULTLIB:advapi32.lib",
+ "-ladvapi32",
+ ],
"//absl:wasm": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
@@ -231,6 +270,7 @@ cc_library(
":base_internal",
":config",
":core_headers",
+ ":cycleclock_internal",
":dynamic_annotations",
":log_severity",
":raw_logging_internal",
@@ -429,6 +469,9 @@ cc_test(
srcs = ["spinlock_test_common.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = [
+ "no_test_wasm",
+ ],
deps = [
":base",
":base_internal",
@@ -479,6 +522,7 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":base",
":config",
":core_headers",
],
@@ -521,6 +565,16 @@ cc_test(
)
cc_test(
+ name = "nullability_test",
+ srcs = ["nullability_test.cc"],
+ deps = [
+ ":core_headers",
+ ":nullability",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
name = "raw_logging_test",
srcs = ["raw_logging_test.cc"],
copts = ABSL_TEST_COPTS,
@@ -551,7 +605,10 @@ cc_test(
srcs = ["internal/low_level_alloc_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- tags = ["no_test_ios_x86_64"],
+ tags = [
+ "no_test_ios_x86_64",
+ "no_test_wasm",
+ ],
deps = [
":malloc_internal",
"//absl/container:node_hash_map",
@@ -564,6 +621,9 @@ cc_test(
srcs = ["internal/thread_identity_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = [
+ "no_test_wasm",
+ ],
deps = [
":base",
":core_headers",
@@ -587,100 +647,6 @@ cc_test(
)
cc_library(
- name = "bits",
- hdrs = ["internal/bits.h"],
- linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- ":config",
- ":core_headers",
- ],
-)
-
-cc_test(
- name = "bits_test",
- size = "small",
- srcs = ["internal/bits_test.cc"],
- copts = ABSL_TEST_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- deps = [
- ":bits",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_library(
- name = "exponential_biased",
- srcs = ["internal/exponential_biased.cc"],
- hdrs = ["internal/exponential_biased.h"],
- linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- ":config",
- ":core_headers",
- ],
-)
-
-cc_test(
- name = "exponential_biased_test",
- size = "small",
- srcs = ["internal/exponential_biased_test.cc"],
- copts = ABSL_TEST_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = ["//visibility:private"],
- deps = [
- ":exponential_biased",
- "//absl/strings",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_library(
- name = "periodic_sampler",
- srcs = ["internal/periodic_sampler.cc"],
- hdrs = ["internal/periodic_sampler.h"],
- copts = ABSL_DEFAULT_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- deps = [
- ":core_headers",
- ":exponential_biased",
- ],
-)
-
-cc_test(
- name = "periodic_sampler_test",
- size = "small",
- srcs = ["internal/periodic_sampler_test.cc"],
- copts = ABSL_TEST_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = ["//visibility:private"],
- deps = [
- ":core_headers",
- ":periodic_sampler",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_binary(
- name = "periodic_sampler_benchmark",
- testonly = 1,
- srcs = ["internal/periodic_sampler_benchmark.cc"],
- copts = ABSL_TEST_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- tags = ["benchmark"],
- visibility = ["//visibility:private"],
- deps = [
- ":core_headers",
- ":periodic_sampler",
- "@com_github_google_benchmark//:benchmark_main",
- ],
-)
-
-cc_library(
name = "scoped_set_env",
testonly = 1,
srcs = ["internal/scoped_set_env.cc"],
@@ -790,6 +756,35 @@ cc_test(
],
)
+cc_library(
+ name = "prefetch",
+ hdrs = [
+ "internal/prefetch.h",
+ "prefetch.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":config",
+ ":core_headers", # TODO(b/265984188): remove
+ ],
+)
+
+cc_test(
+ name = "prefetch_test",
+ size = "small",
+ srcs = [
+ "internal/prefetch_test.cc",
+ "prefetch_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":prefetch",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
cc_test(
name = "unique_small_name_test",
size = "small",
diff --git a/abseil-cpp/absl/base/CMakeLists.txt b/abseil-cpp/absl/base/CMakeLists.txt
index 9ff5aa2..76c4ff1 100644
--- a/abseil-cpp/absl/base/CMakeLists.txt
+++ b/abseil-cpp/absl/base/CMakeLists.txt
@@ -16,6 +16,7 @@
find_library(LIBRT rt)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
atomic_hook
@@ -28,6 +29,7 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
errno_saver
@@ -54,6 +56,34 @@ absl_cc_library(
absl_cc_library(
NAME
+ nullability
+ HDRS
+ "nullability.h"
+ SRCS
+ "internal/nullability_impl.h"
+ DEPS
+ absl::core_headers
+ absl::type_traits
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_test(
+ NAME
+ nullability_test
+ SRCS
+ "nullability_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::core_headers
+ absl::nullability
+ GTest::gtest_main
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+ NAME
raw_logging_internal
HDRS
"internal/raw_logging.h"
@@ -63,11 +93,13 @@ absl_cc_library(
absl::atomic_hook
absl::config
absl::core_headers
+ absl::errno_saver
absl::log_severity
COPTS
${ABSL_DEFAULT_COPTS}
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
spinlock_wait
@@ -131,6 +163,7 @@ absl_cc_library(
PUBLIC
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
malloc_internal
@@ -151,6 +184,7 @@ absl_cc_library(
Threads::Threads
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
base_internal
@@ -174,6 +208,7 @@ absl_cc_library(
"call_once.h"
"casts.h"
"internal/cycleclock.h"
+ "internal/cycleclock_config.h"
"internal/low_level_scheduling.h"
"internal/per_thread_tls.h"
"internal/spinlock.h"
@@ -181,6 +216,7 @@ absl_cc_library(
"internal/thread_identity.h"
"internal/tsan_mutex_interface.h"
"internal/unscaledcycleclock.h"
+ "internal/unscaledcycleclock_config.h"
SRCS
"internal/cycleclock.cc"
"internal/spinlock.cc"
@@ -192,7 +228,7 @@ absl_cc_library(
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
$<$<BOOL:${LIBRT}>:-lrt>
- $<$<BOOL:${MINGW}>:"advapi32">
+ $<$<BOOL:${MINGW}>:-ladvapi32>
DEPS
absl::atomic_hook
absl::base_internal
@@ -207,6 +243,7 @@ absl_cc_library(
PUBLIC
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
throw_delegate
@@ -221,6 +258,7 @@ absl_cc_library(
absl::raw_logging_internal
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
exception_testing
@@ -230,10 +268,11 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::config
- gtest
+ GTest::gtest
TESTONLY
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
pretty_function
@@ -243,6 +282,7 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
exception_safety_testing
@@ -259,7 +299,7 @@ absl_cc_library(
absl::meta
absl::strings
absl::utility
- gtest
+ GTest::gtest
TESTONLY
)
@@ -273,9 +313,10 @@ absl_cc_test(
DEPS
absl::exception_safety_testing
absl::memory
- gtest_main
+ GTest::gtest_main
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
atomic_hook_test_helper
@@ -300,8 +341,8 @@ absl_cc_test(
absl::atomic_hook_test_helper
absl::atomic_hook
absl::core_headers
- gmock
- gtest_main
+ GTest::gmock
+ GTest::gtest_main
)
absl_cc_test(
@@ -314,7 +355,7 @@ absl_cc_test(
DEPS
absl::base
absl::core_headers
- gtest_main
+ GTest::gtest_main
)
absl_cc_test(
@@ -327,8 +368,8 @@ absl_cc_test(
DEPS
absl::errno_saver
absl::strerror
- gmock
- gtest_main
+ GTest::gmock
+ GTest::gtest_main
)
absl_cc_test(
@@ -342,7 +383,7 @@ absl_cc_test(
absl::base
absl::config
absl::throw_delegate
- gtest_main
+ GTest::gtest_main
)
absl_cc_test(
@@ -357,7 +398,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::base_internal
- gtest_main
+ GTest::gtest_main
)
absl_cc_test(
@@ -371,10 +412,11 @@ absl_cc_test(
absl::base_internal
absl::memory
absl::strings
- gmock
- gtest_main
+ GTest::gmock
+ GTest::gtest_main
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
spinlock_test_common
@@ -388,7 +430,7 @@ absl_cc_library(
absl::base_internal
absl::core_headers
absl::synchronization
- gtest
+ GTest::gtest
TESTONLY
)
@@ -406,9 +448,10 @@ absl_cc_test(
absl::config
absl::core_headers
absl::synchronization
- gtest_main
+ GTest::gtest_main
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
endian
@@ -418,6 +461,7 @@ absl_cc_library(
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
+ absl::base
absl::config
absl::core_headers
PUBLIC
@@ -434,7 +478,7 @@ absl_cc_test(
absl::base
absl::config
absl::endian
- gtest_main
+ GTest::gtest_main
)
absl_cc_test(
@@ -447,7 +491,7 @@ absl_cc_test(
DEPS
absl::config
absl::synchronization
- gtest_main
+ GTest::gtest_main
)
absl_cc_test(
@@ -461,7 +505,7 @@ absl_cc_test(
absl::base
absl::core_headers
absl::synchronization
- gtest_main
+ GTest::gtest_main
)
absl_cc_test(
@@ -474,7 +518,7 @@ absl_cc_test(
DEPS
absl::raw_logging_internal
absl::strings
- gtest_main
+ GTest::gtest_main
)
absl_cc_test(
@@ -487,7 +531,7 @@ absl_cc_test(
DEPS
absl::base
absl::synchronization
- gtest_main
+ GTest::gtest_main
)
absl_cc_test(
@@ -515,87 +559,10 @@ absl_cc_test(
absl::core_headers
absl::synchronization
Threads::Threads
- gtest_main
-)
-
-absl_cc_library(
- NAME
- bits
- HDRS
- "internal/bits.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
- absl::core_headers
-)
-
-absl_cc_test(
- NAME
- bits_test
- SRCS
- "internal/bits_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::bits
- gtest_main
-)
-
-absl_cc_library(
- NAME
- exponential_biased
- SRCS
- "internal/exponential_biased.cc"
- HDRS
- "internal/exponential_biased.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
- absl::core_headers
-)
-
-absl_cc_test(
- NAME
- exponential_biased_test
- SRCS
- "internal/exponential_biased_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::exponential_biased
- absl::strings
- gmock_main
-)
-
-absl_cc_library(
- NAME
- periodic_sampler
- SRCS
- "internal/periodic_sampler.cc"
- HDRS
- "internal/periodic_sampler.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::core_headers
- absl::exponential_biased
-)
-
-absl_cc_test(
- NAME
- periodic_sampler_test
- SRCS
- "internal/periodic_sampler_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::core_headers
- absl::periodic_sampler
- gmock_main
+ GTest::gtest_main
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
scoped_set_env
@@ -619,7 +586,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::scoped_set_env
- gtest_main
+ GTest::gtest_main
)
absl_cc_test(
@@ -643,10 +610,11 @@ absl_cc_test(
absl::flags_marshalling
absl::log_severity
absl::strings
- gmock
- gtest_main
+ GTest::gmock
+ GTest::gtest_main
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
strerror
@@ -674,10 +642,11 @@ absl_cc_test(
DEPS
absl::strerror
absl::strings
- gmock
- gtest_main
+ GTest::gmock
+ GTest::gtest_main
)
+# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
fast_type_id
@@ -700,7 +669,35 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::fast_type_id
- gtest_main
+ GTest::gtest_main
+)
+
+absl_cc_library(
+ NAME
+ prefetch
+ HDRS
+ "prefetch.h"
+ "internal/prefetch.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ LINKOPTS
+ ${ABSL_DEFAULT_LINKOPTS}
+ DEPS
+ absl::config
+ absl::core_headers # TODO(b/265984188): remove
+)
+
+absl_cc_test(
+ NAME
+ prefetch_test
+ SRCS
+ "prefetch_test.cc"
+ "internal/prefetch_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::prefetch
+ GTest::gtest_main
)
absl_cc_test(
@@ -713,5 +710,5 @@ absl_cc_test(
DEPS
absl::core_headers
absl::optional
- gtest_main
+ GTest::gtest_main
)
diff --git a/abseil-cpp/absl/base/attributes.h b/abseil-cpp/absl/base/attributes.h
index 046fbea..a7f279a 100644
--- a/abseil-cpp/absl/base/attributes.h
+++ b/abseil-cpp/absl/base/attributes.h
@@ -18,8 +18,6 @@
// These macros are used within Abseil and allow the compiler to optimize, where
// applicable, certain function calls.
//
-// This file is used for both C and C++!
-//
// Most macros here are exposing GCC or Clang features, and are stubbed out for
// other compilers.
//
@@ -121,7 +119,7 @@
#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls)
#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls))
-#elif defined(__GNUC__) && !defined(__clang__)
+#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__)
#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
#define ABSL_ATTRIBUTE_NO_TAIL_CALL \
__attribute__((optimize("no-optimize-sibling-calls")))
@@ -133,14 +131,15 @@
// ABSL_ATTRIBUTE_WEAK
//
// Tags a function as weak for the purposes of compilation and linking.
-// Weak attributes currently do not work properly in LLVM's Windows backend,
-// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
+// Weak attributes did not work properly in LLVM's Windows backend before
+// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
// for further information.
// The MinGW compiler doesn't complain about the weak attribute until the link
// step, presumably because Windows doesn't use ELF binaries.
-#if (ABSL_HAVE_ATTRIBUTE(weak) || \
- (defined(__GNUC__) && !defined(__clang__))) && \
- !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__)
+#if (ABSL_HAVE_ATTRIBUTE(weak) || \
+ (defined(__GNUC__) && !defined(__clang__))) && \
+ (!defined(_WIN32) || (defined(__clang__) && __clang_major__ >= 9)) && \
+ !defined(__MINGW32__)
#undef ABSL_ATTRIBUTE_WEAK
#define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
#define ABSL_HAVE_ATTRIBUTE_WEAK 1
@@ -212,8 +211,20 @@
// out of bounds or does other scary things with memory.
// NOTE: GCC supports AddressSanitizer(asan) since 4.8.
// https://gcc.gnu.org/gcc-4.8/changes.html
-#if ABSL_HAVE_ATTRIBUTE(no_sanitize_address)
+#if defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
+ ABSL_HAVE_ATTRIBUTE(no_sanitize_address)
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
+#elif defined(ABSL_HAVE_ADDRESS_SANITIZER) && defined(_MSC_VER) && \
+ _MSC_VER >= 1928
+// https://docs.microsoft.com/en-us/cpp/cpp/no-sanitize-address
+#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __declspec(no_sanitize_address)
+#elif defined(ABSL_HAVE_HWADDRESS_SANITIZER) && ABSL_HAVE_ATTRIBUTE(no_sanitize)
+// HWAddressSanitizer is a sanitizer similar to AddressSanitizer, which uses CPU
+// features to detect similar bugs with less CPU and memory overhead.
+// NOTE: GCC supports HWAddressSanitizer(hwasan) since 11.
+// https://gcc.gnu.org/gcc-11/changes.html
+#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS \
+ __attribute__((no_sanitize("hwaddress")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
#endif
@@ -263,7 +274,7 @@
//
// Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.
-#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__)
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
@@ -283,10 +294,7 @@
// ABSL_ATTRIBUTE_RETURNS_NONNULL
//
// Tells the compiler that a particular function never returns a null pointer.
-#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) || \
- (defined(__GNUC__) && \
- (__GNUC__ > 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && \
- !defined(__clang__))
+#if ABSL_HAVE_ATTRIBUTE(returns_nonnull)
#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
#else
#define ABSL_ATTRIBUTE_RETURNS_NONNULL
@@ -316,15 +324,22 @@
__attribute__((section(#name))) __attribute__((noinline))
#endif
-
// ABSL_ATTRIBUTE_SECTION_VARIABLE
//
// Tells the compiler/linker to put a given variable into a section and define
// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section.
// This functionality is supported by GNU linker.
#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE
+#ifdef _AIX
+// __attribute__((section(#name))) on AIX is achieved by using the `.csect`
+// psudo op which includes an additional integer as part of its syntax indcating
+// alignment. If data fall under different alignments then you might get a
+// compilation error indicating a `Section type conflict`.
+#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name)
+#else
#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name)))
#endif
+#endif
// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS
//
@@ -335,8 +350,8 @@
// a no-op on ELF but not on Mach-O.
//
#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS
-#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \
- extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \
+#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \
+ extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \
extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK
#endif
#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS
@@ -397,6 +412,9 @@
//
// Tells the compiler to warn about unused results.
//
+// For code or headers that are assured to only build with C++17 and up, prefer
+// just using the standard `[[nodiscard]]` directly over this macro.
+//
// When annotating a function, it must appear as the first part of the
// declaration or definition. The compiler will warn if the return value from
// such a function is unused:
@@ -423,9 +441,10 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425
//
// Note: past advice was to place the macro after the argument list.
-#if ABSL_HAVE_ATTRIBUTE(nodiscard)
-#define ABSL_MUST_USE_RESULT [[nodiscard]]
-#elif defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result)
+//
+// TODO(b/176172494): Use ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) when all code is
+// compliant with the stricter [[nodiscard]].
+#if defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result)
#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result))
#else
#define ABSL_MUST_USE_RESULT
@@ -495,7 +514,7 @@
#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]]
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args)
#define ABSL_XRAY_LOG_ARGS(N) \
- [[clang::xray_always_instrument, clang::xray_log_args(N)]]
+ [[clang::xray_always_instrument, clang::xray_log_args(N)]]
#else
#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]]
#endif
@@ -526,6 +545,13 @@
// ABSL_ATTRIBUTE_UNUSED
//
// Prevents the compiler from complaining about variables that appear unused.
+//
+// For code or headers that are assured to only build with C++17 and up, prefer
+// just using the standard '[[maybe_unused]]' directly over this macro.
+//
+// Due to differences in positioning requirements between the old, compiler
+// specific __attribute__ syntax and the now standard [[maybe_unused]], this
+// macro does not attempt to take advantage of '[[maybe_unused]]'.
#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))
#undef ABSL_ATTRIBUTE_UNUSED
#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__))
@@ -546,13 +572,19 @@
// ABSL_ATTRIBUTE_PACKED
//
// Instructs the compiler not to use natural alignment for a tagged data
-// structure, but instead to reduce its alignment to 1. This attribute can
-// either be applied to members of a structure or to a structure in its
-// entirety. Applying this attribute (judiciously) to a structure in its
-// entirety to optimize the memory footprint of very commonly-used structs is
-// fine. Do not apply this attribute to a structure in its entirety if the
-// purpose is to control the offsets of the members in the structure. Instead,
-// apply this attribute only to structure members that need it.
+// structure, but instead to reduce its alignment to 1.
+//
+// Therefore, DO NOT APPLY THIS ATTRIBUTE TO STRUCTS CONTAINING ATOMICS. Doing
+// so can cause atomic variables to be mis-aligned and silently violate
+// atomicity on x86.
+//
+// This attribute can either be applied to members of a structure or to a
+// structure in its entirety. Applying this attribute (judiciously) to a
+// structure in its entirety to optimize the memory footprint of very
+// commonly-used structs is fine. Do not apply this attribute to a structure in
+// its entirety if the purpose is to control the offsets of the members in the
+// structure. Instead, apply this attribute only to structure members that need
+// it.
//
// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the
// natural alignment of structure members not annotated is preserved. Aligned
@@ -597,30 +629,24 @@
// case 42:
// ...
//
-// Notes: when compiled with clang in C++11 mode, the ABSL_FALLTHROUGH_INTENDED
-// macro is expanded to the [[clang::fallthrough]] attribute, which is analysed
-// when performing switch labels fall-through diagnostic
-// (`-Wimplicit-fallthrough`). See clang documentation on language extensions
-// for details:
+// Notes: When supported, GCC and Clang can issue a warning on switch labels
+// with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See
+// clang documentation on language extensions for details:
// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough
//
-// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro
-// has no effect on diagnostics. In any case this macro has no effect on runtime
+// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has
+// no effect on diagnostics. In any case this macro has no effect on runtime
// behavior and performance of code.
+
#ifdef ABSL_FALLTHROUGH_INTENDED
#error "ABSL_FALLTHROUGH_INTENDED should not be defined."
-#endif
-
-// TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough)
+#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]]
+#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough)
#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
-#endif
-#elif defined(__GNUC__) && __GNUC__ >= 7
+#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough)
#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
-#endif
-
-#ifndef ABSL_FALLTHROUGH_INTENDED
+#else
#define ABSL_FALLTHROUGH_INTENDED \
do { \
} while (0)
@@ -632,6 +658,9 @@
// declarations. The macro argument is used as a custom diagnostic message (e.g.
// suggestion of a better alternative).
//
+// For code or headers that are assured to only build with C++14 and up, prefer
+// just using the standard `[[deprecated("message")]]` directly over this macro.
+//
// Examples:
//
// class ABSL_DEPRECATED("Use Bar instead") Foo {...};
@@ -642,26 +671,60 @@
// ABSL_DEPRECATED("Use DoThat() instead")
// void DoThis();
//
+// enum FooEnum {
+// kBar ABSL_DEPRECATED("Use kBaz instead"),
+// };
+//
// Every usage of a deprecated entity will trigger a warning when compiled with
-// clang's `-Wdeprecated-declarations` option. This option is turned off by
-// default, but the warnings will be reported by clang-tidy.
-#if defined(__clang__) && __cplusplus >= 201103L
+// GCC/Clang's `-Wdeprecated-declarations` option. Google's production toolchain
+// turns this warning off by default, instead relying on clang-tidy to report
+// new uses of deprecated code.
+#if ABSL_HAVE_ATTRIBUTE(deprecated)
#define ABSL_DEPRECATED(message) __attribute__((deprecated(message)))
-#endif
-
-#ifndef ABSL_DEPRECATED
+#else
#define ABSL_DEPRECATED(message)
#endif
+// When deprecating Abseil code, it is sometimes necessary to turn off the
+// warning within Abseil, until the deprecated code is actually removed. The
+// deprecated code can be surrounded with these directives to acheive that
+// result.
+//
+// class ABSL_DEPRECATED("Use Bar instead") Foo;
+//
+// ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
+// Baz ComputeBazFromFoo(Foo f);
+// ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
+#if defined(__GNUC__) || defined(__clang__)
+// Clang also supports these GCC pragmas.
+#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \
+ _Pragma("GCC diagnostic pop")
+#else
+#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
+#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
+#endif // defined(__GNUC__) || defined(__clang__)
+
// ABSL_CONST_INIT
//
// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will
// not compile (on supported platforms) unless the variable has a constant
// initializer. This is useful for variables with static and thread storage
// duration, because it guarantees that they will not suffer from the so-called
-// "static init order fiasco". Prefer to put this attribute on the most visible
-// declaration of the variable, if there's more than one, because code that
-// accesses the variable can then use the attribute for optimization.
+// "static init order fiasco".
+//
+// This attribute must be placed on the initializing declaration of the
+// variable. Some compilers will give a -Wmissing-constinit warning when this
+// attribute is placed on some other declaration but missing from the
+// initializing declaration.
+//
+// In some cases (notably with thread_local variables), `ABSL_CONST_INIT` can
+// also be used in a non-initializing declaration to tell the compiler that a
+// variable is already initialized, reducing overhead that would otherwise be
+// incurred by a hidden guard variable. Thus annotating all declarations with
+// this attribute is recommended to potentially enhance optimization.
//
// Example:
//
@@ -670,13 +733,103 @@
// ABSL_CONST_INIT static MyType my_var;
// };
//
-// MyType MyClass::my_var = MakeMyType(...);
+// ABSL_CONST_INIT MyType MyClass::my_var = MakeMyType(...);
+//
+// For code or headers that are assured to only build with C++20 and up, prefer
+// just using the standard `constinit` keyword directly over this macro.
//
// Note that this attribute is redundant if the variable is declared constexpr.
-#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
+#if defined(__cpp_constinit) && __cpp_constinit >= 201907L
+#define ABSL_CONST_INIT constinit
+#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
#define ABSL_CONST_INIT [[clang::require_constant_initialization]]
#else
#define ABSL_CONST_INIT
-#endif // ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
+#endif
+
+// These annotations are not available yet due to fear of breaking code.
+#define ABSL_ATTRIBUTE_PURE_FUNCTION
+#define ABSL_ATTRIBUTE_CONST_FUNCTION
+
+// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
+// parameter or implicit object parameter is retained by the return value of the
+// annotated function (or, for a parameter of a constructor, in the value of the
+// constructed object). This attribute causes warnings to be produced if a
+// temporary object does not live long enough.
+//
+// When applied to a reference parameter, the referenced object is assumed to be
+// retained by the return value of the function. When applied to a non-reference
+// parameter (for example, a pointer or a class type), all temporaries
+// referenced by the parameter are assumed to be retained by the return value of
+// the function.
+//
+// See also the upstream documentation:
+// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)
+#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
+#elif ABSL_HAVE_ATTRIBUTE(lifetimebound)
+#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
+#else
+#define ABSL_ATTRIBUTE_LIFETIME_BOUND
+#endif
+
+// ABSL_ATTRIBUTE_TRIVIAL_ABI
+// Indicates that a type is "trivially relocatable" -- meaning it can be
+// relocated without invoking the constructor/destructor, using a form of move
+// elision.
+//
+// From a memory safety point of view, putting aside destructor ordering, it's
+// safe to apply ABSL_ATTRIBUTE_TRIVIAL_ABI if an object's location
+// can change over the course of its lifetime: if a constructor can be run one
+// place, and then the object magically teleports to another place where some
+// methods are run, and then the object teleports to yet another place where it
+// is destroyed. This is notably not true for self-referential types, where the
+// move-constructor must keep the self-reference up to date. If the type changed
+// location without invoking the move constructor, it would have a dangling
+// self-reference.
+//
+// The use of this teleporting machinery means that the number of paired
+// move/destroy operations can change, and so it is a bad idea to apply this to
+// a type meant to count the number of moves.
+//
+// Warning: applying this can, rarely, break callers. Objects passed by value
+// will be destroyed at the end of the call, instead of the end of the
+// full-expression containing the call. In addition, it changes the ABI
+// of functions accepting this type by value (e.g. to pass in registers).
+//
+// See also the upstream documentation:
+// https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
+//
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::trivial_abi)
+#define ABSL_ATTRIBUTE_TRIVIAL_ABI [[clang::trivial_abi]]
+#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1
+#elif ABSL_HAVE_ATTRIBUTE(trivial_abi)
+#define ABSL_ATTRIBUTE_TRIVIAL_ABI __attribute__((trivial_abi))
+#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1
+#else
+#define ABSL_ATTRIBUTE_TRIVIAL_ABI
+#endif
+
+// ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
+//
+// Indicates a data member can be optimized to occupy no space (if it is empty)
+// and/or its tail padding can be used for other members.
+//
+// For code that is assured to only build with C++20 or later, prefer using
+// the standard attribute `[[no_unique_address]]` directly instead of this
+// macro.
+//
+// https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c20-no_unique_address
+// Current versions of MSVC have disabled `[[no_unique_address]]` since it
+// breaks ABI compatibility, but offers `[[msvc::no_unique_address]]` for
+// situations when it can be assured that it is desired. Since Abseil does not
+// claim ABI compatibility in mixed builds, we can offer it unconditionally.
+#if defined(_MSC_VER) && _MSC_VER >= 1929
+#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
+#elif ABSL_HAVE_CPP_ATTRIBUTE(no_unique_address)
+#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]]
+#else
+#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
+#endif
#endif // ABSL_BASE_ATTRIBUTES_H_
diff --git a/abseil-cpp/absl/base/call_once.h b/abseil-cpp/absl/base/call_once.h
index 5b468af..08436ba 100644
--- a/abseil-cpp/absl/base/call_once.h
+++ b/abseil-cpp/absl/base/call_once.h
@@ -123,7 +123,7 @@ class SchedulingHelper {
private:
base_internal::SchedulingMode mode_;
- bool guard_result_;
+ bool guard_result_ = false;
};
// Bit patterns for call_once state machine values. Internal implementation
@@ -177,15 +177,8 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
scheduling_mode) == kOnceInit) {
base_internal::invoke(std::forward<Callable>(fn),
std::forward<Args>(args)...);
- // The call to SpinLockWake below is an optimization, because the waiter
- // in SpinLockWait is waiting with a short timeout. The atomic load/store
- // sequence is slightly faster than an atomic exchange:
- // old_control = control->exchange(base_internal::kOnceDone,
- // std::memory_order_release);
- // We opt for a slightly faster case when there are no waiters, in spite
- // of longer tail latency when there are waiters.
- old_control = control->load(std::memory_order_relaxed);
- control->store(base_internal::kOnceDone, std::memory_order_release);
+ old_control =
+ control->exchange(base_internal::kOnceDone, std::memory_order_release);
if (old_control == base_internal::kOnceWaiter) {
base_internal::SpinLockWake(control, true);
}
diff --git a/abseil-cpp/absl/base/casts.h b/abseil-cpp/absl/base/casts.h
index 83c6912..d195888 100644
--- a/abseil-cpp/absl/base/casts.h
+++ b/abseil-cpp/absl/base/casts.h
@@ -29,6 +29,10 @@
#include <type_traits>
#include <utility>
+#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
+#include <bit> // For std::bit_cast.
+#endif // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
+
#include "absl/base/internal/identity.h"
#include "absl/base/macros.h"
#include "absl/meta/type_traits.h"
@@ -36,19 +40,6 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace internal_casts {
-
-template <class Dest, class Source>
-struct is_bitcastable
- : std::integral_constant<
- bool,
- sizeof(Dest) == sizeof(Source) &&
- type_traits_internal::is_trivially_copyable<Source>::value &&
- type_traits_internal::is_trivially_copyable<Dest>::value &&
- std::is_default_constructible<Dest>::value> {};
-
-} // namespace internal_casts
-
// implicit_cast()
//
// Performs an implicit conversion between types following the language
@@ -105,81 +96,83 @@ constexpr To implicit_cast(typename absl::internal::identity_t<To> to) {
// bit_cast()
//
-// Performs a bitwise cast on a type without changing the underlying bit
-// representation of that type's value. The two types must be of the same size
-// and both types must be trivially copyable. As with most casts, use with
-// caution. A `bit_cast()` might be needed when you need to temporarily treat a
-// type as some other type, such as in the following cases:
-//
-// * Serialization (casting temporarily to `char *` for those purposes is
-// always allowed by the C++ standard)
-// * Managing the individual bits of a type within mathematical operations
-// that are not normally accessible through that type
-// * Casting non-pointer types to pointer types (casting the other way is
-// allowed by `reinterpret_cast()` but round-trips cannot occur the other
-// way).
+// Creates a value of the new type `Dest` whose representation is the same as
+// that of the argument, which is of (deduced) type `Source` (a "bitwise cast";
+// every bit in the value representation of the result is equal to the
+// corresponding bit in the object representation of the source). Source and
+// destination types must be of the same size, and both types must be trivially
+// copyable.
//
-// Example:
+// As with most casts, use with caution. A `bit_cast()` might be needed when you
+// need to treat a value as the value of some other type, for example, to access
+// the individual bits of an object which are not normally accessible through
+// the object's type, such as for working with the binary representation of a
+// floating point value:
//
// float f = 3.14159265358979;
-// int i = bit_cast<int32_t>(f);
+// int i = bit_cast<int>(f);
// // i = 0x40490fdb
//
-// Casting non-pointer types to pointer types and then dereferencing them
-// traditionally produces undefined behavior.
+// Reinterpreting and accessing a value directly as a different type (as shown
+// below) usually results in undefined behavior.
//
// Example:
//
// // WRONG
-// float f = 3.14159265358979; // WRONG
-// int i = * reinterpret_cast<int*>(&f); // WRONG
+// float f = 3.14159265358979;
+// int i = reinterpret_cast<int&>(f); // Wrong
+// int j = *reinterpret_cast<int*>(&f); // Equally wrong
+// int k = *bit_cast<int*>(&f); // Equally wrong
+//
+// Reinterpret-casting results in undefined behavior according to the ISO C++
+// specification, section [basic.lval]. Roughly, this section says: if an object
+// in memory has one type, and a program accesses it with a different type, the
+// result is undefined behavior for most "different type".
//
-// The address-casting method produces undefined behavior according to the ISO
-// C++ specification section [basic.lval]. Roughly, this section says: if an
-// object in memory has one type, and a program accesses it with a different
-// type, the result is undefined behavior for most values of "different type".
+// Using bit_cast on a pointer and then dereferencing it is no better than using
+// reinterpret_cast. You should only use bit_cast on the value itself.
//
// Such casting results in type punning: holding an object in memory of one type
// and reading its bits back using a different type. A `bit_cast()` avoids this
-// issue by implementing its casts using `memcpy()`, which avoids introducing
-// this undefined behavior.
-//
-// NOTE: The requirements here are more strict than the bit_cast of standard
-// proposal p0476 due to the need for workarounds and lack of intrinsics.
-// Specifically, this implementation also requires `Dest` to be
-// default-constructible.
+// issue by copying the object representation to a new value, which avoids
+// introducing this undefined behavior (since the original value is never
+// accessed in the wrong way).
+//
+// The requirements of `absl::bit_cast` are more strict than that of
+// `std::bit_cast` unless compiler support is available. Specifically, without
+// compiler support, this implementation also requires `Dest` to be
+// default-constructible. In C++20, `absl::bit_cast` is replaced by
+// `std::bit_cast`.
+#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
+
+using std::bit_cast;
+
+#else // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
+
template <
typename Dest, typename Source,
- typename std::enable_if<internal_casts::is_bitcastable<Dest, Source>::value,
+ typename std::enable_if<sizeof(Dest) == sizeof(Source) &&
+ std::is_trivially_copyable<Source>::value &&
+ std::is_trivially_copyable<Dest>::value
+#if !ABSL_HAVE_BUILTIN(__builtin_bit_cast)
+ && std::is_default_constructible<Dest>::value
+#endif // !ABSL_HAVE_BUILTIN(__builtin_bit_cast)
+ ,
int>::type = 0>
+#if ABSL_HAVE_BUILTIN(__builtin_bit_cast)
+inline constexpr Dest bit_cast(const Source& source) {
+ return __builtin_bit_cast(Dest, source);
+}
+#else // ABSL_HAVE_BUILTIN(__builtin_bit_cast)
inline Dest bit_cast(const Source& source) {
Dest dest;
memcpy(static_cast<void*>(std::addressof(dest)),
static_cast<const void*>(std::addressof(source)), sizeof(dest));
return dest;
}
+#endif // ABSL_HAVE_BUILTIN(__builtin_bit_cast)
-// NOTE: This overload is only picked if the requirements of bit_cast are
-// not met. It is therefore UB, but is provided temporarily as previous
-// versions of this function template were unchecked. Do not use this in
-// new code.
-template <
- typename Dest, typename Source,
- typename std::enable_if<
- !internal_casts::is_bitcastable<Dest, Source>::value,
- int>::type = 0>
-ABSL_DEPRECATED(
- "absl::bit_cast type requirements were violated. Update the types "
- "being used such that they are the same size and are both "
- "TriviallyCopyable.")
-inline Dest bit_cast(const Source& source) {
- static_assert(sizeof(Dest) == sizeof(Source),
- "Source and destination types should have equal sizes.");
-
- Dest dest;
- memcpy(&dest, &source, sizeof(dest));
- return dest;
-}
+#endif // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/abseil-cpp/absl/base/config.h b/abseil-cpp/absl/base/config.h
index c1d0494..1de7993 100644
--- a/abseil-cpp/absl/base/config.h
+++ b/abseil-cpp/absl/base/config.h
@@ -56,6 +56,25 @@
#include <cstddef>
#endif // __cplusplus
+// ABSL_INTERNAL_CPLUSPLUS_LANG
+//
+// MSVC does not set the value of __cplusplus correctly, but instead uses
+// _MSVC_LANG as a stand-in.
+// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
+//
+// However, there are reports that MSVC even sets _MSVC_LANG incorrectly at
+// times, for example:
+// https://github.com/microsoft/vscode-cpptools/issues/1770
+// https://reviews.llvm.org/D70996
+//
+// For this reason, this symbol is considered INTERNAL and code outside of
+// Abseil must not use it.
+#if defined(_MSVC_LANG)
+#define ABSL_INTERNAL_CPLUSPLUS_LANG _MSVC_LANG
+#elif defined(__cplusplus)
+#define ABSL_INTERNAL_CPLUSPLUS_LANG __cplusplus
+#endif
+
#if defined(__APPLE__)
// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED,
// __IPHONE_8_0.
@@ -66,6 +85,35 @@
#include "absl/base/options.h"
#include "absl/base/policy_checks.h"
+// Abseil long-term support (LTS) releases will define
+// `ABSL_LTS_RELEASE_VERSION` to the integer representing the date string of the
+// LTS release version, and will define `ABSL_LTS_RELEASE_PATCH_LEVEL` to the
+// integer representing the patch-level for that release.
+//
+// For example, for LTS release version "20300401.2", this would give us
+// ABSL_LTS_RELEASE_VERSION == 20300401 && ABSL_LTS_RELEASE_PATCH_LEVEL == 2
+//
+// These symbols will not be defined in non-LTS code.
+//
+// Abseil recommends that clients live-at-head. Therefore, if you are using
+// these symbols to assert a minimum version requirement, we recommend you do it
+// as
+//
+// #if defined(ABSL_LTS_RELEASE_VERSION) && ABSL_LTS_RELEASE_VERSION < 20300401
+// #error Project foo requires Abseil LTS version >= 20300401
+// #endif
+//
+// The `defined(ABSL_LTS_RELEASE_VERSION)` part of the check excludes
+// live-at-head clients from the minimum version assertion.
+//
+// See https://abseil.io/about/releases for more information on Abseil release
+// management.
+//
+// LTS releases can be obtained from
+// https://github.com/abseil/abseil-cpp/releases.
+#define ABSL_LTS_RELEASE_VERSION 20230802
+#define ABSL_LTS_RELEASE_PATCH_LEVEL 0
+
// Helper macro to convert a CPP variable to a string literal.
#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x)
@@ -121,10 +169,16 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0
#define ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_END
+#define ABSL_INTERNAL_C_SYMBOL(x) x
#elif ABSL_OPTION_USE_INLINE_NAMESPACE == 1
#define ABSL_NAMESPACE_BEGIN \
inline namespace ABSL_OPTION_INLINE_NAMESPACE_NAME {
#define ABSL_NAMESPACE_END }
+#define ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) x##_##v
+#define ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, v) \
+ ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v)
+#define ABSL_INTERNAL_C_SYMBOL(x) \
+ ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, ABSL_OPTION_INLINE_NAMESPACE_NAME)
#else
#error options.h is misconfigured.
#endif
@@ -148,39 +202,43 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_HAVE_BUILTIN(x) 0
#endif
-#if defined(__is_identifier)
-#define ABSL_INTERNAL_HAS_KEYWORD(x) !(__is_identifier(x))
-#else
-#define ABSL_INTERNAL_HAS_KEYWORD(x) 0
-#endif
-
#ifdef __has_feature
#define ABSL_HAVE_FEATURE(f) __has_feature(f)
#else
#define ABSL_HAVE_FEATURE(f) 0
#endif
+// Portable check for GCC minimum version:
+// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) \
+ (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
+#else
+#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) 0
+#endif
+
+#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
+#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) \
+ (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y))
+#else
+#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) 0
+#endif
+
// ABSL_HAVE_TLS is defined to 1 when __thread should be supported.
-// We assume __thread is supported on Linux when compiled with Clang or compiled
-// against libstdc++ with _GLIBCXX_HAVE_TLS defined.
+// We assume __thread is supported on Linux or Asylo when compiled with Clang or
+// compiled against libstdc++ with _GLIBCXX_HAVE_TLS defined.
#ifdef ABSL_HAVE_TLS
#error ABSL_HAVE_TLS cannot be directly set
-#elif defined(__linux__) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS))
+#elif (defined(__linux__) || defined(__ASYLO__)) && \
+ (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS))
#define ABSL_HAVE_TLS 1
#endif
// ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
//
// Checks whether `std::is_trivially_destructible<T>` is supported.
-//
-// Notes: All supported compilers using libc++ support this feature, as does
-// gcc >= 4.8.1 using libstdc++, and Visual Studio.
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set
-#elif defined(_LIBCPP_VERSION) || \
- (!defined(__clang__) && defined(__GNUC__) && defined(__GLIBCXX__) && \
- (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || \
- defined(_MSC_VER)
#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1
#endif
@@ -188,35 +246,27 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
//
// Checks whether `std::is_trivially_default_constructible<T>` and
// `std::is_trivially_copy_constructible<T>` are supported.
+#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
+#else
+#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
+#endif
// ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
//
// Checks whether `std::is_trivially_copy_assignable<T>` is supported.
-
-// Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with
-// either libc++ or libstdc++, and Visual Studio (but not NVCC).
-#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
-#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
-#elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE)
-#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set
-#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \
- (!defined(__clang__) && defined(__GNUC__) && \
- (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 4)) && \
- (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) || \
- (defined(_MSC_VER) && !defined(__NVCC__))
-#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
+#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot be directly set
+#else
#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
#endif
-// ABSL_HAVE_SOURCE_LOCATION_CURRENT
+// ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE
//
-// Indicates whether `absl::SourceLocation::current()` will return useful
-// information in some contexts.
-#ifndef ABSL_HAVE_SOURCE_LOCATION_CURRENT
-#if ABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \
- ABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE)
-#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
-#endif
+// Checks whether `std::is_trivially_copyable<T>` is supported.
+#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE
+#error ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE cannot be directly set
+#define ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE 1
#endif
// ABSL_HAVE_THREAD_LOCAL
@@ -311,25 +361,21 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// For further details, consult the compiler's documentation.
#ifdef ABSL_HAVE_EXCEPTIONS
#error ABSL_HAVE_EXCEPTIONS cannot be directly set.
-
-#elif defined(__clang__)
-
-#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
+#elif ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(3, 6)
// Clang >= 3.6
#if ABSL_HAVE_FEATURE(cxx_exceptions)
#define ABSL_HAVE_EXCEPTIONS 1
#endif // ABSL_HAVE_FEATURE(cxx_exceptions)
-#else
+#elif defined(__clang__)
// Clang < 3.6
// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
#define ABSL_HAVE_EXCEPTIONS 1
#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
-#endif // __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
-
// Handle remaining special cases and default to exceptions being supported.
-#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \
- !(defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__cpp_exceptions)) && \
+#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \
+ !(ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0) && \
+ !defined(__cpp_exceptions)) && \
!(defined(_MSC_VER) && !defined(_CPPUNWIND))
#define ABSL_HAVE_EXCEPTIONS 1
#endif
@@ -361,10 +407,12 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// POSIX.1-2001.
#ifdef ABSL_HAVE_MMAP
#error ABSL_HAVE_MMAP cannot be directly set
-#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
- defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
- defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
- defined(__ASYLO__)
+#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
+ defined(_AIX) || defined(__ros__) || defined(__native_client__) || \
+ defined(__asmjs__) || defined(__wasm__) || defined(__Fuchsia__) || \
+ defined(__sun) || defined(__ASYLO__) || defined(__myriad2__) || \
+ defined(__HAIKU__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
+ defined(__QNX__) || defined(__VXWORKS__) || defined(__hexagon__)
#define ABSL_HAVE_MMAP 1
#endif
@@ -375,17 +423,28 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
#error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
- defined(__ros__)
+ defined(_AIX) || defined(__ros__) || defined(__OpenBSD__) || \
+ defined(__NetBSD__) || defined(__VXWORKS__)
#define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1
#endif
+// ABSL_HAVE_SCHED_GETCPU
+//
+// Checks whether sched_getcpu is available.
+#ifdef ABSL_HAVE_SCHED_GETCPU
+#error ABSL_HAVE_SCHED_GETCPU cannot be directly set
+#elif defined(__linux__)
+#define ABSL_HAVE_SCHED_GETCPU 1
+#endif
+
// ABSL_HAVE_SCHED_YIELD
//
// Checks whether the platform implements sched_yield(2) as defined in
// POSIX.1-2001.
#ifdef ABSL_HAVE_SCHED_YIELD
#error ABSL_HAVE_SCHED_YIELD cannot be directly set
-#elif defined(__linux__) || defined(__ros__) || defined(__native_client__)
+#elif defined(__linux__) || defined(__ros__) || defined(__native_client__) || \
+ defined(__VXWORKS__)
#define ABSL_HAVE_SCHED_YIELD 1
#endif
@@ -400,7 +459,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// platforms.
#ifdef ABSL_HAVE_SEMAPHORE_H
#error ABSL_HAVE_SEMAPHORE_H cannot be directly set
-#elif defined(__linux__) || defined(__ros__)
+#elif defined(__linux__) || defined(__ros__) || defined(__VXWORKS__)
#define ABSL_HAVE_SEMAPHORE_H 1
#endif
@@ -428,6 +487,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#elif defined(__Fuchsia__)
// Signals don't exist on fuchsia.
#elif defined(__native_client__)
+// Signals don't exist on hexagon/QuRT
+#elif defined(__hexagon__)
#else
// other standard libraries
#define ABSL_HAVE_ALARM 1
@@ -461,22 +522,29 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#error "absl endian detection needs to be set up for your compiler"
#endif
-// macOS 10.13 and iOS 10.11 don't let you use <any>, <optional>, or <variant>
-// even though the headers exist and are publicly noted to work. See
+// macOS < 10.13 and iOS < 12 don't support <any>, <optional>, or <variant>
+// because the libc++ shared library shipped on the system doesn't have the
+// requisite exported symbols. See
// https://github.com/abseil/abseil-cpp/issues/207 and
// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes
+//
// libc++ spells out the availability requirements in the file
// llvm-project/libcxx/include/__config via the #define
-// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS.
-#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \
- ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
- __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400) || \
- (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
- __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
- (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
- __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
- (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
- __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
+// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS. The set of versions has been
+// modified a few times, via
+// https://github.com/llvm/llvm-project/commit/7fb40e1569dd66292b647f4501b85517e9247953
+// and
+// https://github.com/llvm/llvm-project/commit/0bc451e7e137c4ccadcd3377250874f641ca514a
+// The second has the actually correct versions, thus, is what we copy here.
+#if defined(__APPLE__) && \
+ ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300) || \
+ (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
+ (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
+ (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
#else
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
@@ -484,71 +552,44 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// ABSL_HAVE_STD_ANY
//
-// Checks whether C++17 std::any is available by checking whether <any> exists.
+// Checks whether C++17 std::any is available.
#ifdef ABSL_HAVE_STD_ANY
#error "ABSL_HAVE_STD_ANY cannot be directly set."
-#endif
-
-#ifdef __has_include
-#if __has_include(<any>) && __cplusplus >= 201703L && \
+#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
#define ABSL_HAVE_STD_ANY 1
#endif
-#endif
// ABSL_HAVE_STD_OPTIONAL
//
// Checks whether C++17 std::optional is available.
#ifdef ABSL_HAVE_STD_OPTIONAL
#error "ABSL_HAVE_STD_OPTIONAL cannot be directly set."
-#endif
-
-#ifdef __has_include
-#if __has_include(<optional>) && __cplusplus >= 201703L && \
+#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
#define ABSL_HAVE_STD_OPTIONAL 1
#endif
-#endif
// ABSL_HAVE_STD_VARIANT
//
// Checks whether C++17 std::variant is available.
#ifdef ABSL_HAVE_STD_VARIANT
#error "ABSL_HAVE_STD_VARIANT cannot be directly set."
-#endif
-
-#ifdef __has_include
-#if __has_include(<variant>) && __cplusplus >= 201703L && \
+#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
#define ABSL_HAVE_STD_VARIANT 1
#endif
-#endif
// ABSL_HAVE_STD_STRING_VIEW
//
// Checks whether C++17 std::string_view is available.
#ifdef ABSL_HAVE_STD_STRING_VIEW
#error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set."
-#endif
-
-#ifdef __has_include
-#if __has_include(<string_view>) && __cplusplus >= 201703L
-#define ABSL_HAVE_STD_STRING_VIEW 1
-#endif
-#endif
-
-// For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than
-// the support for <optional>, <any>, <string_view>, <variant>. So we use
-// _MSC_VER to check whether we have VS 2017 RTM (when <optional>, <any>,
-// <string_view>, <variant> is implemented) or higher. Also, `__cplusplus` is
-// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language
-// version.
-// TODO(zhangxy): fix tests before enabling aliasing for `std::any`.
-#if defined(_MSC_VER) && _MSC_VER >= 1910 && \
- ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402)
-// #define ABSL_HAVE_STD_ANY 1
-#define ABSL_HAVE_STD_OPTIONAL 1
-#define ABSL_HAVE_STD_VARIANT 1
+#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
#define ABSL_HAVE_STD_STRING_VIEW 1
#endif
@@ -644,8 +685,6 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#endif
#endif
-#undef ABSL_INTERNAL_HAS_KEYWORD
-
// ABSL_DLL
//
// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)`
@@ -665,18 +704,24 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_DLL
#endif // defined(_MSC_VER)
+#if defined(_MSC_VER)
+#if defined(ABSL_BUILD_TEST_DLL)
+#define ABSL_TEST_DLL __declspec(dllexport)
+#elif defined(ABSL_CONSUME_TEST_DLL)
+#define ABSL_TEST_DLL __declspec(dllimport)
+#else
+#define ABSL_TEST_DLL
+#endif
+#else
+#define ABSL_TEST_DLL
+#endif // defined(_MSC_VER)
+
// ABSL_HAVE_MEMORY_SANITIZER
//
// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of
// a compiler instrumentation module and a run-time library.
#ifdef ABSL_HAVE_MEMORY_SANITIZER
#error "ABSL_HAVE_MEMORY_SANITIZER cannot be directly set."
-#elif defined(MEMORY_SANITIZER)
-// The MEMORY_SANITIZER macro is deprecated but we will continue to honor it
-// for now.
-#define ABSL_HAVE_MEMORY_SANITIZER 1
-#elif defined(__SANITIZE_MEMORY__)
-#define ABSL_HAVE_MEMORY_SANITIZER 1
#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer)
#define ABSL_HAVE_MEMORY_SANITIZER 1
#endif
@@ -686,10 +731,6 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// ThreadSanitizer (TSan) is a fast data race detector.
#ifdef ABSL_HAVE_THREAD_SANITIZER
#error "ABSL_HAVE_THREAD_SANITIZER cannot be directly set."
-#elif defined(THREAD_SANITIZER)
-// The THREAD_SANITIZER macro is deprecated but we will continue to honor it
-// for now.
-#define ABSL_HAVE_THREAD_SANITIZER 1
#elif defined(__SANITIZE_THREAD__)
#define ABSL_HAVE_THREAD_SANITIZER 1
#elif ABSL_HAVE_FEATURE(thread_sanitizer)
@@ -701,14 +742,196 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// AddressSanitizer (ASan) is a fast memory error detector.
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
#error "ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set."
-#elif defined(ADDRESS_SANITIZER)
-// The ADDRESS_SANITIZER macro is deprecated but we will continue to honor it
-// for now.
-#define ABSL_HAVE_ADDRESS_SANITIZER 1
#elif defined(__SANITIZE_ADDRESS__)
#define ABSL_HAVE_ADDRESS_SANITIZER 1
#elif ABSL_HAVE_FEATURE(address_sanitizer)
#define ABSL_HAVE_ADDRESS_SANITIZER 1
#endif
+// ABSL_HAVE_HWADDRESS_SANITIZER
+//
+// Hardware-Assisted AddressSanitizer (or HWASAN) is even faster than asan
+// memory error detector which can use CPU features like ARM TBI, Intel LAM or
+// AMD UAI.
+#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
+#error "ABSL_HAVE_HWADDRESS_SANITIZER cannot be directly set."
+#elif defined(__SANITIZE_HWADDRESS__)
+#define ABSL_HAVE_HWADDRESS_SANITIZER 1
+#elif ABSL_HAVE_FEATURE(hwaddress_sanitizer)
+#define ABSL_HAVE_HWADDRESS_SANITIZER 1
+#endif
+
+// ABSL_HAVE_DATAFLOW_SANITIZER
+//
+// Dataflow Sanitizer (or DFSAN) is a generalised dynamic data flow analysis.
+#ifdef ABSL_HAVE_DATAFLOW_SANITIZER
+#error "ABSL_HAVE_DATAFLOW_SANITIZER cannot be directly set."
+#elif defined(DATAFLOW_SANITIZER)
+// GCC provides no method for detecting the presence of the standalone
+// DataFlowSanitizer (-fsanitize=dataflow), so GCC users of -fsanitize=dataflow
+// should also use -DDATAFLOW_SANITIZER.
+#define ABSL_HAVE_DATAFLOW_SANITIZER 1
+#elif ABSL_HAVE_FEATURE(dataflow_sanitizer)
+#define ABSL_HAVE_DATAFLOW_SANITIZER 1
+#endif
+
+// ABSL_HAVE_LEAK_SANITIZER
+//
+// LeakSanitizer (or lsan) is a detector of memory leaks.
+// https://clang.llvm.org/docs/LeakSanitizer.html
+// https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer
+//
+// The macro ABSL_HAVE_LEAK_SANITIZER can be used to detect at compile-time
+// whether the LeakSanitizer is potentially available. However, just because the
+// LeakSanitizer is available does not mean it is active. Use the
+// always-available run-time interface in //absl/debugging/leak_check.h for
+// interacting with LeakSanitizer.
+#ifdef ABSL_HAVE_LEAK_SANITIZER
+#error "ABSL_HAVE_LEAK_SANITIZER cannot be directly set."
+#elif defined(LEAK_SANITIZER)
+// GCC provides no method for detecting the presence of the standalone
+// LeakSanitizer (-fsanitize=leak), so GCC users of -fsanitize=leak should also
+// use -DLEAK_SANITIZER.
+#define ABSL_HAVE_LEAK_SANITIZER 1
+// Clang standalone LeakSanitizer (-fsanitize=leak)
+#elif ABSL_HAVE_FEATURE(leak_sanitizer)
+#define ABSL_HAVE_LEAK_SANITIZER 1
+#elif defined(ABSL_HAVE_ADDRESS_SANITIZER)
+// GCC or Clang using the LeakSanitizer integrated into AddressSanitizer.
+#define ABSL_HAVE_LEAK_SANITIZER 1
+#endif
+
+// ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
+//
+// Class template argument deduction is a language feature added in C++17.
+#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
+#error "ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION cannot be directly set."
+#elif defined(__cpp_deduction_guides)
+#define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1
+#endif
+
+// ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
+//
+// Prior to C++17, static constexpr variables defined in classes required a
+// separate definition outside of the class body, for example:
+//
+// class Foo {
+// static constexpr int kBar = 0;
+// };
+// constexpr int Foo::kBar;
+//
+// In C++17, these variables defined in classes are considered inline variables,
+// and the extra declaration is redundant. Since some compilers warn on the
+// extra declarations, ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL can be used
+// conditionally ignore them:
+//
+// #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
+// constexpr int Foo::kBar;
+// #endif
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG < 201703L
+#define ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
+#endif
+
+// `ABSL_INTERNAL_HAS_RTTI` determines whether abseil is being compiled with
+// RTTI support.
+#ifdef ABSL_INTERNAL_HAS_RTTI
+#error ABSL_INTERNAL_HAS_RTTI cannot be directly set
+#elif (defined(__GNUC__) && defined(__GXX_RTTI)) || \
+ (defined(_MSC_VER) && defined(_CPPRTTI)) || \
+ (!defined(__GNUC__) && !defined(_MSC_VER))
+#define ABSL_INTERNAL_HAS_RTTI 1
+#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
+
+// ABSL_INTERNAL_HAVE_SSE is used for compile-time detection of SSE support.
+// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
+// which architectures support the various x86 instruction sets.
+#ifdef ABSL_INTERNAL_HAVE_SSE
+#error ABSL_INTERNAL_HAVE_SSE cannot be directly set
+#elif defined(__SSE__)
+#define ABSL_INTERNAL_HAVE_SSE 1
+#elif (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)) && \
+ !defined(_M_ARM64EC)
+// MSVC only defines _M_IX86_FP for x86 32-bit code, and _M_IX86_FP >= 1
+// indicates that at least SSE was targeted with the /arch:SSE option.
+// All x86-64 processors support SSE, so support can be assumed.
+// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
+#define ABSL_INTERNAL_HAVE_SSE 1
+#endif
+
+// ABSL_INTERNAL_HAVE_SSE2 is used for compile-time detection of SSE2 support.
+// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
+// which architectures support the various x86 instruction sets.
+#ifdef ABSL_INTERNAL_HAVE_SSE2
+#error ABSL_INTERNAL_HAVE_SSE2 cannot be directly set
+#elif defined(__SSE2__)
+#define ABSL_INTERNAL_HAVE_SSE2 1
+#elif (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)) && \
+ !defined(_M_ARM64EC)
+// MSVC only defines _M_IX86_FP for x86 32-bit code, and _M_IX86_FP >= 2
+// indicates that at least SSE2 was targeted with the /arch:SSE2 option.
+// All x86-64 processors support SSE2, so support can be assumed.
+// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
+#define ABSL_INTERNAL_HAVE_SSE2 1
+#endif
+
+// ABSL_INTERNAL_HAVE_SSSE3 is used for compile-time detection of SSSE3 support.
+// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
+// which architectures support the various x86 instruction sets.
+//
+// MSVC does not have a mode that targets SSSE3 at compile-time. To use SSSE3
+// with MSVC requires either assuming that the code will only every run on CPUs
+// that support SSSE3, otherwise __cpuid() can be used to detect support at
+// runtime and fallback to a non-SSSE3 implementation when SSSE3 is unsupported
+// by the CPU.
+#ifdef ABSL_INTERNAL_HAVE_SSSE3
+#error ABSL_INTERNAL_HAVE_SSSE3 cannot be directly set
+#elif defined(__SSSE3__)
+#define ABSL_INTERNAL_HAVE_SSSE3 1
+#endif
+
+// ABSL_INTERNAL_HAVE_ARM_NEON is used for compile-time detection of NEON (ARM
+// SIMD).
+//
+// If __CUDA_ARCH__ is defined, then we are compiling CUDA code in device mode.
+// In device mode, NEON intrinsics are not available, regardless of host
+// platform.
+// https://llvm.org/docs/CompileCudaWithLLVM.html#detecting-clang-vs-nvcc-from-code
+#ifdef ABSL_INTERNAL_HAVE_ARM_NEON
+#error ABSL_INTERNAL_HAVE_ARM_NEON cannot be directly set
+#elif defined(__ARM_NEON) && !defined(__CUDA_ARCH__)
+#define ABSL_INTERNAL_HAVE_ARM_NEON 1
+#endif
+
+// ABSL_HAVE_CONSTANT_EVALUATED is used for compile-time detection of
+// constant evaluation support through `absl::is_constant_evaluated`.
+#ifdef ABSL_HAVE_CONSTANT_EVALUATED
+#error ABSL_HAVE_CONSTANT_EVALUATED cannot be directly set
+#endif
+#ifdef __cpp_lib_is_constant_evaluated
+#define ABSL_HAVE_CONSTANT_EVALUATED 1
+#elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)
+#define ABSL_HAVE_CONSTANT_EVALUATED 1
+#endif
+
+// ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros
+// into an integer that can be compared against.
+#ifdef ABSL_INTERNAL_EMSCRIPTEN_VERSION
+#error ABSL_INTERNAL_EMSCRIPTEN_VERSION cannot be directly set
+#endif
+#ifdef __EMSCRIPTEN__
+#include <emscripten/version.h>
+#ifdef __EMSCRIPTEN_major__
+#if __EMSCRIPTEN_minor__ >= 1000
+#error __EMSCRIPTEN_minor__ is too big to fit in ABSL_INTERNAL_EMSCRIPTEN_VERSION
+#endif
+#if __EMSCRIPTEN_tiny__ >= 1000
+#error __EMSCRIPTEN_tiny__ is too big to fit in ABSL_INTERNAL_EMSCRIPTEN_VERSION
+#endif
+#define ABSL_INTERNAL_EMSCRIPTEN_VERSION \
+ ((__EMSCRIPTEN_major__)*1000000 + (__EMSCRIPTEN_minor__)*1000 + \
+ (__EMSCRIPTEN_tiny__))
+#endif
+#endif
+
#endif // ABSL_BASE_CONFIG_H_
diff --git a/abseil-cpp/absl/base/dynamic_annotations.h b/abseil-cpp/absl/base/dynamic_annotations.h
index 545f8cb..7ba8912 100644
--- a/abseil-cpp/absl/base/dynamic_annotations.h
+++ b/abseil-cpp/absl/base/dynamic_annotations.h
@@ -46,6 +46,7 @@
#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
#include <stddef.h>
+#include <stdint.h>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
@@ -53,6 +54,10 @@
#include "absl/base/macros.h"
#endif
+#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
+#include <sanitizer/hwasan_interface.h>
+#endif
+
// TODO(rogeeff): Remove after the backward compatibility period.
#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export
@@ -110,6 +115,9 @@
// Define race annotations.
#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
+// Some of the symbols used in this section (e.g. AnnotateBenignRaceSized) are
+// defined by the compiler-based sanitizer implementation, not by the Abseil
+// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.
// -------------------------------------------------------------
// Annotations that suppress errors. It is usually better to express the
@@ -286,17 +294,22 @@ ABSL_INTERNAL_END_EXTERN_C
// Define IGNORE_READS_BEGIN/_END annotations.
#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
+// Some of the symbols used in this section (e.g. AnnotateIgnoreReadsBegin) are
+// defined by the compiler-based implementation, not by the Abseil
+// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.
// Request the analysis tool to ignore all reads in the current thread until
// ABSL_ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
// reads, while still checking other reads and all writes.
// See also ABSL_ANNOTATE_UNPROTECTED_READ.
-#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
- ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin) \
+ (__FILE__, __LINE__)
// Stop ignoring reads.
-#define ABSL_ANNOTATE_IGNORE_READS_END() \
- ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
+#define ABSL_ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd) \
+ (__FILE__, __LINE__)
// Function prototypes of annotations provided by the compiler-based sanitizer
// implementation.
@@ -316,16 +329,22 @@ ABSL_INTERNAL_END_EXTERN_C
// TODO(delesley) -- The exclusive lock here ignores writes as well, but
// allows IGNORE_READS_AND_WRITES to work properly.
-#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
- ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED( \
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsBegin)) \
+ ()
-#define ABSL_ANNOTATE_IGNORE_READS_END() \
- ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
+#define ABSL_ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED( \
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsEnd)) \
+ ()
-ABSL_INTERNAL_STATIC_INLINE void AbslInternalAnnotateIgnoreReadsBegin()
+ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
+ AbslInternalAnnotateIgnoreReadsBegin)()
ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE {}
-ABSL_INTERNAL_STATIC_INLINE void AbslInternalAnnotateIgnoreReadsEnd()
+ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
+ AbslInternalAnnotateIgnoreReadsEnd)()
ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE {}
#else
@@ -419,31 +438,6 @@ ABSL_NAMESPACE_END
#endif
-#ifdef __cplusplus
-#ifdef ABSL_HAVE_THREAD_SANITIZER
-ABSL_INTERNAL_BEGIN_EXTERN_C
-int RunningOnValgrind();
-double ValgrindSlowdown();
-ABSL_INTERNAL_END_EXTERN_C
-#else
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-ABSL_DEPRECATED(
- "Don't use this interface. It is misleading and is being deleted.")
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline int RunningOnValgrind() { return 0; }
-ABSL_DEPRECATED(
- "Don't use this interface. It is misleading and is being deleted.")
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline double ValgrindSlowdown() { return 1.0; }
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-using absl::base_internal::RunningOnValgrind;
-using absl::base_internal::ValgrindSlowdown;
-#endif
-#endif
-
// -------------------------------------------------------------------------
// Address sanitizer annotations
@@ -457,7 +451,7 @@ using absl::base_internal::ValgrindSlowdown;
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
#define ABSL_ADDRESS_SANITIZER_REDZONE(name) \
struct { \
- char x[8] __attribute__((aligned(8))); \
+ alignas(8) char x[8]; \
} name
#else
@@ -468,6 +462,26 @@ using absl::base_internal::ValgrindSlowdown;
#endif // ABSL_HAVE_ADDRESS_SANITIZER
// -------------------------------------------------------------------------
+// HWAddress sanitizer annotations
+
+#ifdef __cplusplus
+namespace absl {
+#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
+// Under HWASAN changes the tag of the pointer.
+template <typename T>
+T* HwasanTagPointer(T* ptr, uintptr_t tag) {
+ return reinterpret_cast<T*>(__hwasan_tag_pointer(ptr, tag));
+}
+#else
+template <typename T>
+T* HwasanTagPointer(T* ptr, uintptr_t) {
+ return ptr;
+}
+#endif
+} // namespace absl
+#endif
+
+// -------------------------------------------------------------------------
// Undefine the macros intended only for this file.
#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
diff --git a/abseil-cpp/absl/base/exception_safety_testing_test.cc b/abseil-cpp/absl/base/exception_safety_testing_test.cc
index a59be29..bf5aa7c 100644
--- a/abseil-cpp/absl/base/exception_safety_testing_test.cc
+++ b/abseil-cpp/absl/base/exception_safety_testing_test.cc
@@ -148,7 +148,7 @@ TEST(ThrowingValueTest, ThrowingBitwiseOps) {
ThrowingValue<> bomb1, bomb2;
TestOp([&bomb1]() { ~bomb1; });
- TestOp([&]() { bomb1& bomb2; });
+ TestOp([&]() { bomb1 & bomb2; });
TestOp([&]() { bomb1 | bomb2; });
TestOp([&]() { bomb1 ^ bomb2; });
}
@@ -332,13 +332,16 @@ TEST(ThrowingValueTest, NonThrowingPlacementDelete) {
constexpr int kArrayLen = 2;
// We intentionally create extra space to store the tag allocated by placement
// new[].
- constexpr int kStorageLen = 4;
+ constexpr size_t kExtraSpaceLen = sizeof(size_t) * 2;
alignas(ThrowingValue<>) unsigned char buf[sizeof(ThrowingValue<>)];
alignas(ThrowingValue<>) unsigned char
- array_buf[sizeof(ThrowingValue<>[kStorageLen])];
+ array_buf[kExtraSpaceLen + sizeof(ThrowingValue<>[kArrayLen])];
auto* placed = new (&buf) ThrowingValue<>(1);
auto placed_array = new (&array_buf) ThrowingValue<>[kArrayLen];
+ auto* placed_array_end = reinterpret_cast<unsigned char*>(placed_array) +
+ sizeof(ThrowingValue<>[kArrayLen]);
+ EXPECT_LE(placed_array_end, array_buf + sizeof(array_buf));
SetCountdown();
ExpectNoThrow([placed, &buf]() {
@@ -701,7 +704,10 @@ struct BasicGuaranteeWithExtraContracts : public NonNegative {
static constexpr int kExceptionSentinel = 9999;
};
+
+#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
constexpr int BasicGuaranteeWithExtraContracts::kExceptionSentinel;
+#endif
TEST(ExceptionCheckTest, BasicGuaranteeWithExtraContracts) {
auto tester_with_val =
diff --git a/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h b/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h
index 3e72b49..c72015e 100644
--- a/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h
+++ b/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_
-#define ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_
+#ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
+#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
#include "absl/base/internal/atomic_hook.h"
@@ -31,4 +31,4 @@ void RegisterFunc(VoidF func);
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_
+#endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
diff --git a/abseil-cpp/absl/base/internal/bits.h b/abseil-cpp/absl/base/internal/bits.h
deleted file mode 100644
index 81648e2..0000000
--- a/abseil-cpp/absl/base/internal/bits.h
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2018 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_BASE_INTERNAL_BITS_H_
-#define ABSL_BASE_INTERNAL_BITS_H_
-
-// This file contains bitwise ops which are implementation details of various
-// absl libraries.
-
-#include <cstdint>
-
-#include "absl/base/config.h"
-
-// Clang on Windows has __builtin_clzll; otherwise we need to use the
-// windows intrinsic functions.
-#if defined(_MSC_VER) && !defined(__clang__)
-#include <intrin.h>
-#if defined(_M_X64)
-#pragma intrinsic(_BitScanReverse64)
-#pragma intrinsic(_BitScanForward64)
-#endif
-#pragma intrinsic(_BitScanReverse)
-#pragma intrinsic(_BitScanForward)
-#endif
-
-#include "absl/base/attributes.h"
-
-#if defined(_MSC_VER) && !defined(__clang__)
-// We can achieve something similar to attribute((always_inline)) with MSVC by
-// using the __forceinline keyword, however this is not perfect. MSVC is
-// much less aggressive about inlining, and even with the __forceinline keyword.
-#define ABSL_BASE_INTERNAL_FORCEINLINE __forceinline
-#else
-// Use default attribute inline.
-#define ABSL_BASE_INTERNAL_FORCEINLINE inline ABSL_ATTRIBUTE_ALWAYS_INLINE
-#endif
-
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64Slow(uint64_t n) {
- int zeroes = 60;
- if (n >> 32) {
- zeroes -= 32;
- n >>= 32;
- }
- if (n >> 16) {
- zeroes -= 16;
- n >>= 16;
- }
- if (n >> 8) {
- zeroes -= 8;
- n >>= 8;
- }
- if (n >> 4) {
- zeroes -= 4;
- n >>= 4;
- }
- return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) {
-#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_X64)
- // MSVC does not have __buitin_clzll. Use _BitScanReverse64.
- unsigned long result = 0; // NOLINT(runtime/int)
- if (_BitScanReverse64(&result, n)) {
- return 63 - result;
- }
- return 64;
-#elif defined(_MSC_VER) && !defined(__clang__)
- // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
- unsigned long result = 0; // NOLINT(runtime/int)
- if ((n >> 32) &&
- _BitScanReverse(&result, static_cast<unsigned long>(n >> 32))) {
- return 31 - result;
- }
- if (_BitScanReverse(&result, static_cast<unsigned long>(n))) {
- return 63 - result;
- }
- return 64;
-#elif defined(__GNUC__) || defined(__clang__)
- // Use __builtin_clzll, which uses the following instructions:
- // x86: bsr
- // ARM64: clz
- // PPC: cntlzd
- static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
- "__builtin_clzll does not take 64-bit arg");
-
- // Handle 0 as a special case because __builtin_clzll(0) is undefined.
- if (n == 0) {
- return 64;
- }
- return __builtin_clzll(n);
-#else
- return CountLeadingZeros64Slow(n);
-#endif
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32Slow(uint64_t n) {
- int zeroes = 28;
- if (n >> 16) {
- zeroes -= 16;
- n >>= 16;
- }
- if (n >> 8) {
- zeroes -= 8;
- n >>= 8;
- }
- if (n >> 4) {
- zeroes -= 4;
- n >>= 4;
- }
- return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32(uint32_t n) {
-#if defined(_MSC_VER) && !defined(__clang__)
- unsigned long result = 0; // NOLINT(runtime/int)
- if (_BitScanReverse(&result, n)) {
- return 31 - result;
- }
- return 32;
-#elif defined(__GNUC__) || defined(__clang__)
- // Use __builtin_clz, which uses the following instructions:
- // x86: bsr
- // ARM64: clz
- // PPC: cntlzd
- static_assert(sizeof(int) == sizeof(n),
- "__builtin_clz does not take 32-bit arg");
-
- // Handle 0 as a special case because __builtin_clz(0) is undefined.
- if (n == 0) {
- return 32;
- }
- return __builtin_clz(n);
-#else
- return CountLeadingZeros32Slow(n);
-#endif
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64Slow(uint64_t n) {
- int c = 63;
- n &= ~n + 1;
- if (n & 0x00000000FFFFFFFF) c -= 32;
- if (n & 0x0000FFFF0000FFFF) c -= 16;
- if (n & 0x00FF00FF00FF00FF) c -= 8;
- if (n & 0x0F0F0F0F0F0F0F0F) c -= 4;
- if (n & 0x3333333333333333) c -= 2;
- if (n & 0x5555555555555555) c -= 1;
- return c;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64(uint64_t n) {
-#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_X64)
- unsigned long result = 0; // NOLINT(runtime/int)
- _BitScanForward64(&result, n);
- return result;
-#elif defined(_MSC_VER) && !defined(__clang__)
- unsigned long result = 0; // NOLINT(runtime/int)
- if (static_cast<uint32_t>(n) == 0) {
- _BitScanForward(&result, static_cast<unsigned long>(n >> 32));
- return result + 32;
- }
- _BitScanForward(&result, static_cast<unsigned long>(n));
- return result;
-#elif defined(__GNUC__) || defined(__clang__)
- static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
- "__builtin_ctzll does not take 64-bit arg");
- return __builtin_ctzll(n);
-#else
- return CountTrailingZerosNonZero64Slow(n);
-#endif
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32Slow(uint32_t n) {
- int c = 31;
- n &= ~n + 1;
- if (n & 0x0000FFFF) c -= 16;
- if (n & 0x00FF00FF) c -= 8;
- if (n & 0x0F0F0F0F) c -= 4;
- if (n & 0x33333333) c -= 2;
- if (n & 0x55555555) c -= 1;
- return c;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32(uint32_t n) {
-#if defined(_MSC_VER) && !defined(__clang__)
- unsigned long result = 0; // NOLINT(runtime/int)
- _BitScanForward(&result, n);
- return result;
-#elif defined(__GNUC__) || defined(__clang__)
- static_assert(sizeof(int) == sizeof(n),
- "__builtin_ctz does not take 32-bit arg");
- return __builtin_ctz(n);
-#else
- return CountTrailingZerosNonZero32Slow(n);
-#endif
-}
-
-#undef ABSL_BASE_INTERNAL_FORCEINLINE
-
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_BASE_INTERNAL_BITS_H_
diff --git a/abseil-cpp/absl/base/internal/bits_test.cc b/abseil-cpp/absl/base/internal/bits_test.cc
deleted file mode 100644
index 7855fa6..0000000
--- a/abseil-cpp/absl/base/internal/bits_test.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2018 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/base/internal/bits.h"
-
-#include "gtest/gtest.h"
-
-namespace {
-
-int CLZ64(uint64_t n) {
- int fast = absl::base_internal::CountLeadingZeros64(n);
- int slow = absl::base_internal::CountLeadingZeros64Slow(n);
- EXPECT_EQ(fast, slow) << n;
- return fast;
-}
-
-TEST(BitsTest, CountLeadingZeros64) {
- EXPECT_EQ(64, CLZ64(uint64_t{}));
- EXPECT_EQ(0, CLZ64(~uint64_t{}));
-
- for (int index = 0; index < 64; index++) {
- uint64_t x = static_cast<uint64_t>(1) << index;
- const auto cnt = 63 - index;
- ASSERT_EQ(cnt, CLZ64(x)) << index;
- ASSERT_EQ(cnt, CLZ64(x + x - 1)) << index;
- }
-}
-
-int CLZ32(uint32_t n) {
- int fast = absl::base_internal::CountLeadingZeros32(n);
- int slow = absl::base_internal::CountLeadingZeros32Slow(n);
- EXPECT_EQ(fast, slow) << n;
- return fast;
-}
-
-TEST(BitsTest, CountLeadingZeros32) {
- EXPECT_EQ(32, CLZ32(uint32_t{}));
- EXPECT_EQ(0, CLZ32(~uint32_t{}));
-
- for (int index = 0; index < 32; index++) {
- uint32_t x = static_cast<uint32_t>(1) << index;
- const auto cnt = 31 - index;
- ASSERT_EQ(cnt, CLZ32(x)) << index;
- ASSERT_EQ(cnt, CLZ32(x + x - 1)) << index;
- ASSERT_EQ(CLZ64(x), CLZ32(x) + 32);
- }
-}
-
-int CTZ64(uint64_t n) {
- int fast = absl::base_internal::CountTrailingZerosNonZero64(n);
- int slow = absl::base_internal::CountTrailingZerosNonZero64Slow(n);
- EXPECT_EQ(fast, slow) << n;
- return fast;
-}
-
-TEST(BitsTest, CountTrailingZerosNonZero64) {
- EXPECT_EQ(0, CTZ64(~uint64_t{}));
-
- for (int index = 0; index < 64; index++) {
- uint64_t x = static_cast<uint64_t>(1) << index;
- const auto cnt = index;
- ASSERT_EQ(cnt, CTZ64(x)) << index;
- ASSERT_EQ(cnt, CTZ64(~(x - 1))) << index;
- }
-}
-
-int CTZ32(uint32_t n) {
- int fast = absl::base_internal::CountTrailingZerosNonZero32(n);
- int slow = absl::base_internal::CountTrailingZerosNonZero32Slow(n);
- EXPECT_EQ(fast, slow) << n;
- return fast;
-}
-
-TEST(BitsTest, CountTrailingZerosNonZero32) {
- EXPECT_EQ(0, CTZ32(~uint32_t{}));
-
- for (int index = 0; index < 32; index++) {
- uint32_t x = static_cast<uint32_t>(1) << index;
- const auto cnt = index;
- ASSERT_EQ(cnt, CTZ32(x)) << index;
- ASSERT_EQ(cnt, CTZ32(~(x - 1))) << index;
- }
-}
-
-
-} // namespace
diff --git a/abseil-cpp/absl/base/internal/cycleclock.cc b/abseil-cpp/absl/base/internal/cycleclock.cc
index 0e65005..902e3f5 100644
--- a/abseil-cpp/absl/base/internal/cycleclock.cc
+++ b/abseil-cpp/absl/base/internal/cycleclock.cc
@@ -25,6 +25,8 @@
#include <atomic>
#include <chrono> // NOLINT(build/c++11)
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/base/internal/unscaledcycleclock.h"
namespace absl {
@@ -33,44 +35,20 @@ namespace base_internal {
#if ABSL_USE_UNSCALED_CYCLECLOCK
-namespace {
-
-#ifdef NDEBUG
-#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
-// Not debug mode and the UnscaledCycleClock frequency is the CPU
-// frequency. Scale the CycleClock to prevent overflow if someone
-// tries to represent the time as cycles since the Unix epoch.
-static constexpr int32_t kShift = 1;
-#else
-// Not debug mode and the UnscaledCycleClock isn't operating at the
-// raw CPU frequency. There is no need to do any scaling, so don't
-// needlessly sacrifice precision.
-static constexpr int32_t kShift = 0;
-#endif
-#else
-// In debug mode use a different shift to discourage depending on a
-// particular shift value.
-static constexpr int32_t kShift = 2;
+#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
+constexpr int32_t CycleClock::kShift;
+constexpr double CycleClock::kFrequencyScale;
#endif
-static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
-static std::atomic<CycleClockSourceFunc> cycle_clock_source;
+ABSL_CONST_INIT std::atomic<CycleClockSourceFunc>
+ CycleClock::cycle_clock_source_{nullptr};
-CycleClockSourceFunc LoadCycleClockSource() {
- // Optimize for the common case (no callback) by first doing a relaxed load;
- // this is significantly faster on non-x86 platforms.
- if (cycle_clock_source.load(std::memory_order_relaxed) == nullptr) {
- return nullptr;
- }
- // This corresponds to the store(std::memory_order_release) in
- // CycleClockSource::Register, and makes sure that any updates made prior to
- // registering the callback are visible to this thread before the callback is
- // invoked.
- return cycle_clock_source.load(std::memory_order_acquire);
+void CycleClockSource::Register(CycleClockSourceFunc source) {
+ // Corresponds to the load(std::memory_order_acquire) in LoadCycleClockSource.
+ CycleClock::cycle_clock_source_.store(source, std::memory_order_release);
}
-} // namespace
-
+#ifdef _WIN32
int64_t CycleClock::Now() {
auto fn = LoadCycleClockSource();
if (fn == nullptr) {
@@ -78,15 +56,7 @@ int64_t CycleClock::Now() {
}
return fn() >> kShift;
}
-
-double CycleClock::Frequency() {
- return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();
-}
-
-void CycleClockSource::Register(CycleClockSourceFunc source) {
- // Corresponds to the load(std::memory_order_acquire) in LoadCycleClockSource.
- cycle_clock_source.store(source, std::memory_order_release);
-}
+#endif
#else
diff --git a/abseil-cpp/absl/base/internal/cycleclock.h b/abseil-cpp/absl/base/internal/cycleclock.h
index a18b584..cbfdf57 100644
--- a/abseil-cpp/absl/base/internal/cycleclock.h
+++ b/abseil-cpp/absl/base/internal/cycleclock.h
@@ -42,14 +42,20 @@
#ifndef ABSL_BASE_INTERNAL_CYCLECLOCK_H_
#define ABSL_BASE_INTERNAL_CYCLECLOCK_H_
+#include <atomic>
#include <cstdint>
+#include "absl/base/attributes.h"
#include "absl/base/config.h"
+#include "absl/base/internal/cycleclock_config.h"
+#include "absl/base/internal/unscaledcycleclock.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
+using CycleClockSourceFunc = int64_t (*)();
+
// -----------------------------------------------------------------------------
// CycleClock
// -----------------------------------------------------------------------------
@@ -68,12 +74,21 @@ class CycleClock {
static double Frequency();
private:
+#if ABSL_USE_UNSCALED_CYCLECLOCK
+ static CycleClockSourceFunc LoadCycleClockSource();
+
+ static constexpr int32_t kShift = kCycleClockShift;
+ static constexpr double kFrequencyScale = kCycleClockFrequencyScale;
+
+ ABSL_CONST_INIT static std::atomic<CycleClockSourceFunc> cycle_clock_source_;
+#endif // ABSL_USE_UNSCALED_CYCLECLOC
+
CycleClock() = delete; // no instances
CycleClock(const CycleClock&) = delete;
CycleClock& operator=(const CycleClock&) = delete;
-};
-using CycleClockSourceFunc = int64_t (*)();
+ friend class CycleClockSource;
+};
class CycleClockSource {
private:
@@ -87,6 +102,41 @@ class CycleClockSource {
static void Register(CycleClockSourceFunc source);
};
+#if ABSL_USE_UNSCALED_CYCLECLOCK
+
+inline CycleClockSourceFunc CycleClock::LoadCycleClockSource() {
+#if !defined(__x86_64__)
+ // Optimize for the common case (no callback) by first doing a relaxed load;
+ // this is significantly faster on non-x86 platforms.
+ if (cycle_clock_source_.load(std::memory_order_relaxed) == nullptr) {
+ return nullptr;
+ }
+#endif // !defined(__x86_64__)
+
+ // This corresponds to the store(std::memory_order_release) in
+ // CycleClockSource::Register, and makes sure that any updates made prior to
+ // registering the callback are visible to this thread before the callback
+ // is invoked.
+ return cycle_clock_source_.load(std::memory_order_acquire);
+}
+
+// Accessing globals in inlined code in Window DLLs is problematic.
+#ifndef _WIN32
+inline int64_t CycleClock::Now() {
+ auto fn = LoadCycleClockSource();
+ if (fn == nullptr) {
+ return base_internal::UnscaledCycleClock::Now() >> kShift;
+ }
+ return fn() >> kShift;
+}
+#endif
+
+inline double CycleClock::Frequency() {
+ return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();
+}
+
+#endif // ABSL_USE_UNSCALED_CYCLECLOCK
+
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/abseil-cpp/absl/base/internal/cycleclock_config.h b/abseil-cpp/absl/base/internal/cycleclock_config.h
new file mode 100644
index 0000000..191112b
--- /dev/null
+++ b/abseil-cpp/absl/base/internal/cycleclock_config.h
@@ -0,0 +1,55 @@
+// Copyright 2022 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_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
+#define ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
+
+#include <cstdint>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/inline_variable.h"
+#include "absl/base/internal/unscaledcycleclock_config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+#if ABSL_USE_UNSCALED_CYCLECLOCK
+#ifdef NDEBUG
+#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
+// Not debug mode and the UnscaledCycleClock frequency is the CPU
+// frequency. Scale the CycleClock to prevent overflow if someone
+// tries to represent the time as cycles since the Unix epoch.
+ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 1);
+#else
+// Not debug mode and the UnscaledCycleClock isn't operating at the
+// raw CPU frequency. There is no need to do any scaling, so don't
+// needlessly sacrifice precision.
+ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 0);
+#endif
+#else // NDEBUG
+// In debug mode use a different shift to discourage depending on a
+// particular shift value.
+ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 2);
+#endif // NDEBUG
+
+ABSL_INTERNAL_INLINE_CONSTEXPR(double, kCycleClockFrequencyScale,
+ 1.0 / (1 << kCycleClockShift));
+#endif // ABSL_USE_UNSCALED_CYCLECLOC
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
diff --git a/abseil-cpp/absl/base/internal/direct_mmap.h b/abseil-cpp/absl/base/internal/direct_mmap.h
index 16accf0..1beb2ee 100644
--- a/abseil-cpp/absl/base/internal/direct_mmap.h
+++ b/abseil-cpp/absl/base/internal/direct_mmap.h
@@ -20,7 +20,7 @@
#include "absl/base/config.h"
-#if ABSL_HAVE_MMAP
+#ifdef ABSL_HAVE_MMAP
#include <sys/mman.h>
@@ -41,13 +41,13 @@
#ifdef __mips__
// Include definitions of the ABI currently in use.
-#ifdef __BIONIC__
+#if defined(__BIONIC__) || !defined(__GLIBC__)
// Android doesn't have sgidefs.h, but does have asm/sgidefs.h, which has the
// definitions we need.
#include <asm/sgidefs.h>
#else
#include <sgidefs.h>
-#endif // __BIONIC__
+#endif // __BIONIC__ || !__GLIBC__
#endif // __mips__
// SYS_mmap and SYS_munmap are not defined in Android.
@@ -72,12 +72,15 @@ namespace base_internal {
// Platform specific logic extracted from
// https://chromium.googlesource.com/linux-syscall-support/+/master/linux_syscall_support.h
inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
- off64_t offset) noexcept {
+ off_t offset) noexcept {
#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
+ defined(__m68k__) || defined(__sh__) || \
+ (defined(__hppa__) && !defined(__LP64__)) || \
(defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
(defined(__PPC__) && !defined(__PPC64__)) || \
(defined(__riscv) && __riscv_xlen == 32) || \
- (defined(__s390__) && !defined(__s390x__))
+ (defined(__s390__) && !defined(__s390x__)) || \
+ (defined(__sparc__) && !defined(__arch64__))
// On these architectures, implement mmap with mmap2.
static int pagesize = 0;
if (pagesize == 0) {
@@ -94,11 +97,12 @@ inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
#ifdef __BIONIC__
// SYS_mmap2 has problems on Android API level <= 16.
// Workaround by invoking __mmap2() instead.
- return __mmap2(start, length, prot, flags, fd, offset / pagesize);
+ return __mmap2(start, length, prot, flags, fd,
+ static_cast<size_t>(offset / pagesize));
#else
return reinterpret_cast<void*>(
syscall(SYS_mmap2, start, length, prot, flags, fd,
- static_cast<off_t>(offset / pagesize)));
+ static_cast<unsigned long>(offset / pagesize))); // NOLINT
#endif
#elif defined(__s390x__)
// On s390x, mmap() arguments are passed in memory.
diff --git a/abseil-cpp/absl/base/internal/endian.h b/abseil-cpp/absl/base/internal/endian.h
index 9677530..50747d7 100644
--- a/abseil-cpp/absl/base/internal/endian.h
+++ b/abseil-cpp/absl/base/internal/endian.h
@@ -16,16 +16,10 @@
#ifndef ABSL_BASE_INTERNAL_ENDIAN_H_
#define ABSL_BASE_INTERNAL_ENDIAN_H_
-// The following guarantees declaration of the byte swap functions
-#ifdef _MSC_VER
-#include <stdlib.h> // NOLINT(build/include)
-#elif defined(__FreeBSD__)
-#include <sys/endian.h>
-#elif defined(__GLIBC__)
-#include <byteswap.h> // IWYU pragma: export
-#endif
-
#include <cstdint>
+#include <cstdlib>
+
+#include "absl/base/casts.h"
#include "absl/base/config.h"
#include "absl/base/internal/unaligned_access.h"
#include "absl/base/port.h"
@@ -33,47 +27,11 @@
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.
-// The 16-bit version is available in Clang and GCC only as of GCC 4.8.0.
-// For simplicity, we enable them all only for GCC 4.8.0 or later.
-#if defined(__clang__) || \
- (defined(__GNUC__) && \
- ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ >= 5))
inline uint64_t gbswap_64(uint64_t host_int) {
+#if ABSL_HAVE_BUILTIN(__builtin_bswap64) || defined(__GNUC__)
return __builtin_bswap64(host_int);
-}
-inline uint32_t gbswap_32(uint32_t host_int) {
- return __builtin_bswap32(host_int);
-}
-inline uint16_t gbswap_16(uint16_t host_int) {
- return __builtin_bswap16(host_int);
-}
-
#elif defined(_MSC_VER)
-inline uint64_t gbswap_64(uint64_t host_int) {
return _byteswap_uint64(host_int);
-}
-inline uint32_t gbswap_32(uint32_t host_int) {
- return _byteswap_ulong(host_int);
-}
-inline uint16_t gbswap_16(uint16_t host_int) {
- return _byteswap_ushort(host_int);
-}
-
-#else
-inline uint64_t gbswap_64(uint64_t host_int) {
-#if defined(__GNUC__) && defined(__x86_64__) && !defined(__APPLE__)
- // Adapted from /usr/include/byteswap.h. Not available on Mac.
- if (__builtin_constant_p(host_int)) {
- return __bswap_constant_64(host_int);
- } else {
- uint64_t result;
- __asm__("bswap %0" : "=r"(result) : "0"(host_int));
- return result;
- }
-#elif defined(__GLIBC__)
- return bswap_64(host_int);
#else
return (((host_int & uint64_t{0xFF}) << 56) |
((host_int & uint64_t{0xFF00}) << 40) |
@@ -83,12 +41,14 @@ inline uint64_t gbswap_64(uint64_t host_int) {
((host_int & uint64_t{0xFF0000000000}) >> 24) |
((host_int & uint64_t{0xFF000000000000}) >> 40) |
((host_int & uint64_t{0xFF00000000000000}) >> 56));
-#endif // bswap_64
+#endif
}
inline uint32_t gbswap_32(uint32_t host_int) {
-#if defined(__GLIBC__)
- return bswap_32(host_int);
+#if ABSL_HAVE_BUILTIN(__builtin_bswap32) || defined(__GNUC__)
+ return __builtin_bswap32(host_int);
+#elif defined(_MSC_VER)
+ return _byteswap_ulong(host_int);
#else
return (((host_int & uint32_t{0xFF}) << 24) |
((host_int & uint32_t{0xFF00}) << 8) |
@@ -98,33 +58,29 @@ inline uint32_t gbswap_32(uint32_t host_int) {
}
inline uint16_t gbswap_16(uint16_t host_int) {
-#if defined(__GLIBC__)
- return bswap_16(host_int);
+#if ABSL_HAVE_BUILTIN(__builtin_bswap16) || defined(__GNUC__)
+ return __builtin_bswap16(host_int);
+#elif defined(_MSC_VER)
+ return _byteswap_ushort(host_int);
#else
return (((host_int & uint16_t{0xFF}) << 8) |
((host_int & uint16_t{0xFF00}) >> 8));
#endif
}
-#endif // intrinsics available
-
#ifdef ABSL_IS_LITTLE_ENDIAN
-// Definitions for ntohl etc. that don't require us to include
-// netinet/in.h. We wrap gbswap_32 and gbswap_16 in functions rather
-// than just #defining them because in debug mode, gcc doesn't
-// correctly handle the (rather involved) definitions of bswap_32.
-// gcc guarantees that inline functions are as fast as macros, so
-// this isn't a performance hit.
+// Portable definitions for htonl (host-to-network) and friends on little-endian
+// architectures.
inline uint16_t ghtons(uint16_t x) { return gbswap_16(x); }
inline uint32_t ghtonl(uint32_t x) { return gbswap_32(x); }
inline uint64_t ghtonll(uint64_t x) { return gbswap_64(x); }
#elif defined ABSL_IS_BIG_ENDIAN
-// These definitions are simpler on big-endian machines
-// These are functions instead of macros to avoid self-assignment warnings
-// on calls such as "i = ghtnol(i);". This also provides type checking.
+// Portable definitions for htonl (host-to-network) etc on big-endian
+// architectures. These definitions are simpler since the host byte order is the
+// same as network byte order.
inline uint16_t ghtons(uint16_t x) { return x; }
inline uint32_t ghtonl(uint32_t x) { return x; }
inline uint64_t ghtonll(uint64_t x) { return x; }
@@ -173,6 +129,36 @@ inline constexpr bool IsLittleEndian() { return false; }
#endif /* ENDIAN */
+inline uint8_t FromHost(uint8_t x) { return x; }
+inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
+inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
+inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
+inline uint8_t ToHost(uint8_t x) { return x; }
+inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
+inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
+inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
+
+inline int8_t FromHost(int8_t x) { return x; }
+inline int16_t FromHost(int16_t x) {
+ return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
+}
+inline int32_t FromHost(int32_t x) {
+ return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
+}
+inline int64_t FromHost(int64_t x) {
+ return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
+}
+inline int8_t ToHost(int8_t x) { return x; }
+inline int16_t ToHost(int16_t x) {
+ return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
+}
+inline int32_t ToHost(int32_t x) {
+ return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
+}
+inline int64_t ToHost(int64_t x) {
+ return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
+}
+
// Functions to do unaligned loads and stores in little-endian order.
inline uint16_t Load16(const void *p) {
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
@@ -233,6 +219,36 @@ inline constexpr bool IsLittleEndian() { return false; }
#endif /* ENDIAN */
+inline uint8_t FromHost(uint8_t x) { return x; }
+inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
+inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
+inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
+inline uint8_t ToHost(uint8_t x) { return x; }
+inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
+inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
+inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
+
+inline int8_t FromHost(int8_t x) { return x; }
+inline int16_t FromHost(int16_t x) {
+ return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
+}
+inline int32_t FromHost(int32_t x) {
+ return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
+}
+inline int64_t FromHost(int64_t x) {
+ return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
+}
+inline int8_t ToHost(int8_t x) { return x; }
+inline int16_t ToHost(int16_t x) {
+ return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
+}
+inline int32_t ToHost(int32_t x) {
+ return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
+}
+inline int64_t ToHost(int64_t x) {
+ return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
+}
+
// Functions to do unaligned loads and stores in big-endian order.
inline uint16_t Load16(const void *p) {
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
diff --git a/abseil-cpp/absl/base/internal/exception_safety_testing.h b/abseil-cpp/absl/base/internal/exception_safety_testing.h
index 6ba89d0..c106154 100644
--- a/abseil-cpp/absl/base/internal/exception_safety_testing.h
+++ b/abseil-cpp/absl/base/internal/exception_safety_testing.h
@@ -536,7 +536,22 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
}
// Memory management operators
- // Args.. allows us to overload regular and placement new in one shot
+ static void* operator new(size_t s) noexcept(
+ IsSpecified(TypeSpec::kNoThrowNew)) {
+ if (!IsSpecified(TypeSpec::kNoThrowNew)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
+ }
+ return ::operator new(s);
+ }
+
+ static void* operator new[](size_t s) noexcept(
+ IsSpecified(TypeSpec::kNoThrowNew)) {
+ if (!IsSpecified(TypeSpec::kNoThrowNew)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
+ }
+ return ::operator new[](s);
+ }
+
template <typename... Args>
static void* operator new(size_t s, Args&&... args) noexcept(
IsSpecified(TypeSpec::kNoThrowNew)) {
@@ -557,12 +572,6 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
// Abseil doesn't support throwing overloaded operator delete. These are
// provided so a throwing operator-new can clean up after itself.
- //
- // We provide both regular and templated operator delete because if only the
- // templated version is provided as we did with operator new, the compiler has
- // no way of knowing which overload of operator delete to call. See
- // https://en.cppreference.com/w/cpp/memory/new/operator_delete and
- // https://en.cppreference.com/w/cpp/language/delete for the gory details.
void operator delete(void* p) noexcept { ::operator delete(p); }
template <typename... Args>
@@ -726,9 +735,8 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
ThrowingAllocator select_on_container_copy_construction() noexcept(
IsSpecified(AllocSpec::kNoThrowAllocate)) {
- auto& out = *this;
ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
- return out;
+ return *this;
}
template <typename U>
@@ -938,7 +946,7 @@ class ExceptionSafetyTest {
* `std::unique_ptr<T> operator()() const` where T is the type being tested.
* It is used for reliably creating identical T instances to test on.
*
- * - Operation: The operation object (passsed in via tester.WithOperation(...)
+ * - Operation: The operation object (passed in via tester.WithOperation(...)
* or tester.Test(...)) must be invocable with the signature
* `void operator()(T*) const` where T is the type being tested. It is used
* for performing steps on a T instance that may throw and that need to be
diff --git a/abseil-cpp/absl/base/internal/exponential_biased.cc b/abseil-cpp/absl/base/internal/exponential_biased.cc
deleted file mode 100644
index 1b30c06..0000000
--- a/abseil-cpp/absl/base/internal/exponential_biased.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// 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.
-
-#include "absl/base/internal/exponential_biased.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <atomic>
-#include <cmath>
-#include <limits>
-
-#include "absl/base/attributes.h"
-#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
-// inverse cumulative distribution function for an exponential. Specifically:
-// Let m be the inverse of the sample period, then the probability
-// distribution function is m*exp(-mx) so the CDF is
-// p = 1 - exp(-mx), so
-// q = 1 - p = exp(-mx)
-// log_e(q) = -mx
-// -log_e(q)/m = x
-// log_2(q) * (-log_e(2) * 1/m) = x
-// In the code, q is actually in the range 1 to 2**26, hence the -26 below
-int64_t ExponentialBiased::GetSkipCount(int64_t mean) {
- if (ABSL_PREDICT_FALSE(!initialized_)) {
- Initialize();
- }
-
- uint64_t rng = NextRandom(rng_);
- rng_ = rng;
-
- // Take the top 26 bits as the random number
- // (This plus the 1<<58 sampling bound give a max possible step of
- // 5194297183973780480 bytes.)
- // The uint32_t cast is to prevent a (hard-to-reproduce) NAN
- // under piii debug for some binaries.
- double q = static_cast<uint32_t>(rng >> (kPrngNumBits - 26)) + 1.0;
- // Put the computed p-value through the CDF of a geometric.
- double interval = bias_ + (std::log2(q) - 26) * (-std::log(2.0) * mean);
- // Very large values of interval overflow int64_t. To avoid that, we will
- // cheat and clamp any huge values to (int64_t max)/2. This is a potential
- // source of bias, but the mean would need to be such a large value that it's
- // not likely to come up. For example, with a mean of 1e18, the probability of
- // hitting this condition is about 1/1000. For a mean of 1e17, standard
- // calculators claim that this event won't happen.
- if (interval > static_cast<double>(std::numeric_limits<int64_t>::max() / 2)) {
- // Assume huge values are bias neutral, retain bias for next call.
- return std::numeric_limits<int64_t>::max() / 2;
- }
- double value = std::round(interval);
- bias_ = interval - value;
- return value;
-}
-
-int64_t ExponentialBiased::GetStride(int64_t mean) {
- return GetSkipCount(mean - 1) + 1;
-}
-
-void ExponentialBiased::Initialize() {
- // We don't get well distributed numbers from `this` so we call NextRandom() a
- // bunch to mush the bits around. We use a global_rand to handle the case
- // where the same thread (by memory address) gets created and destroyed
- // repeatedly.
- ABSL_CONST_INIT static std::atomic<uint32_t> global_rand(0);
- uint64_t r = reinterpret_cast<uint64_t>(this) +
- global_rand.fetch_add(1, std::memory_order_relaxed);
- for (int i = 0; i < 20; ++i) {
- r = NextRandom(r);
- }
- rng_ = r;
- initialized_ = true;
-}
-
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/abseil-cpp/absl/base/internal/exponential_biased.h b/abseil-cpp/absl/base/internal/exponential_biased.h
deleted file mode 100644
index 94f79a3..0000000
--- a/abseil-cpp/absl/base/internal/exponential_biased.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// 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_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
-#define ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
-
-#include <stdint.h>
-
-#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
-// rounded exponential distribution. This generator manages very little state,
-// and imposes no synchronization overhead. This makes it useful in specialized
-// scenarios requiring minimum overhead, such as stride based periodic sampling.
-//
-// ExponentialBiased provides two closely related functions, GetSkipCount() and
-// GetStride(), both returning a rounded integer defining a number of events
-// required before some event with a given mean probability occurs.
-//
-// The distribution is useful to generate a random wait time or some periodic
-// event with a given mean probability. For example, if an action is supposed to
-// happen on average once every 'N' events, then we can get a random 'stride'
-// counting down how long before the event to happen. For example, if we'd want
-// to sample one in every 1000 'Frobber' calls, our code could look like this:
-//
-// Frobber::Frobber() {
-// stride_ = exponential_biased_.GetStride(1000);
-// }
-//
-// void Frobber::Frob(int arg) {
-// if (--stride == 0) {
-// SampleFrob(arg);
-// stride_ = exponential_biased_.GetStride(1000);
-// }
-// ...
-// }
-//
-// The rounding of the return value creates a bias, especially for smaller means
-// where the distribution of the fraction is not evenly distributed. We correct
-// this bias by tracking the fraction we rounded up or down on each iteration,
-// effectively tracking the distance between the cumulative value, and the
-// rounded cumulative value. For example, given a mean of 2:
-//
-// raw = 1.63076, cumulative = 1.63076, rounded = 2, bias = -0.36923
-// raw = 0.14624, cumulative = 1.77701, rounded = 2, bias = 0.14624
-// raw = 4.93194, cumulative = 6.70895, rounded = 7, bias = -0.06805
-// raw = 0.24206, cumulative = 6.95101, rounded = 7, bias = 0.24206
-// etc...
-//
-// Adjusting with rounding bias is relatively trivial:
-//
-// double value = bias_ + exponential_distribution(mean)();
-// double rounded_value = std::round(value);
-// bias_ = value - rounded_value;
-// return rounded_value;
-//
-// This class is thread-compatible.
-class ExponentialBiased {
- public:
- // The number of bits set by NextRandom.
- static constexpr int kPrngNumBits = 48;
-
- // `GetSkipCount()` returns the number of events to skip before some chosen
- // event happens. For example, randomly tossing a coin, we will on average
- // throw heads once before we get tails. We can simulate random coin tosses
- // using GetSkipCount() as:
- //
- // ExponentialBiased eb;
- // for (...) {
- // int number_of_heads_before_tail = eb.GetSkipCount(1);
- // for (int flips = 0; flips < number_of_heads_before_tail; ++flips) {
- // printf("head...");
- // }
- // printf("tail\n");
- // }
- //
- int64_t GetSkipCount(int64_t mean);
-
- // GetStride() returns the number of events required for a specific event to
- // happen. See the class comments for a usage example. `GetStride()` is
- // equivalent to `GetSkipCount(mean - 1) + 1`. When to use `GetStride()` or
- // `GetSkipCount()` depends mostly on what best fits the use case.
- int64_t GetStride(int64_t mean);
-
- // Computes a random number in the range [0, 1<<(kPrngNumBits+1) - 1]
- //
- // This is public to enable testing.
- static uint64_t NextRandom(uint64_t rnd);
-
- private:
- void Initialize();
-
- uint64_t rng_{0};
- double bias_{0};
- bool initialized_{false};
-};
-
-// Returns the next prng value.
-// pRNG is: aX+b mod c with a = 0x5DEECE66D, b = 0xB, c = 1<<48
-// This is the lrand64 generator.
-inline uint64_t ExponentialBiased::NextRandom(uint64_t rnd) {
- const uint64_t prng_mult = uint64_t{0x5DEECE66D};
- const uint64_t prng_add = 0xB;
- const uint64_t prng_mod_power = 48;
- const uint64_t prng_mod_mask =
- ~((~static_cast<uint64_t>(0)) << prng_mod_power);
- return (prng_mult * rnd + prng_add) & prng_mod_mask;
-}
-
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
diff --git a/abseil-cpp/absl/base/internal/exponential_biased_test.cc b/abseil-cpp/absl/base/internal/exponential_biased_test.cc
deleted file mode 100644
index 90a482d..0000000
--- a/abseil-cpp/absl/base/internal/exponential_biased_test.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-// 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.
-
-#include "absl/base/internal/exponential_biased.h"
-
-#include <stddef.h>
-
-#include <cmath>
-#include <cstdint>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/strings/str_cat.h"
-
-using ::testing::Ge;
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-
-MATCHER_P2(IsBetween, a, b,
- absl::StrCat(std::string(negation ? "isn't" : "is"), " between ", a,
- " and ", b)) {
- return a <= arg && arg <= b;
-}
-
-// Tests of the quality of the random numbers generated
-// This uses the Anderson Darling test for uniformity.
-// See "Evaluating the Anderson-Darling Distribution" by Marsaglia
-// for details.
-
-// Short cut version of ADinf(z), z>0 (from Marsaglia)
-// This returns the p-value for Anderson Darling statistic in
-// the limit as n-> infinity. For finite n, apply the error fix below.
-double AndersonDarlingInf(double z) {
- if (z < 2) {
- return exp(-1.2337141 / z) / sqrt(z) *
- (2.00012 +
- (0.247105 -
- (0.0649821 - (0.0347962 - (0.011672 - 0.00168691 * z) * z) * z) *
- z) *
- z);
- }
- return exp(
- -exp(1.0776 -
- (2.30695 -
- (0.43424 - (0.082433 - (0.008056 - 0.0003146 * z) * z) * z) * z) *
- z));
-}
-
-// Corrects the approximation error in AndersonDarlingInf for small values of n
-// Add this to AndersonDarlingInf to get a better approximation
-// (from Marsaglia)
-double AndersonDarlingErrFix(int n, double x) {
- if (x > 0.8) {
- return (-130.2137 +
- (745.2337 -
- (1705.091 - (1950.646 - (1116.360 - 255.7844 * x) * x) * x) * x) *
- x) /
- n;
- }
- double cutoff = 0.01265 + 0.1757 / n;
- if (x < cutoff) {
- double t = x / cutoff;
- t = sqrt(t) * (1 - t) * (49 * t - 102);
- return t * (0.0037 / (n * n) + 0.00078 / n + 0.00006) / n;
- } else {
- double t = (x - cutoff) / (0.8 - cutoff);
- t = -0.00022633 +
- (6.54034 - (14.6538 - (14.458 - (8.259 - 1.91864 * t) * t) * t) * t) *
- t;
- return t * (0.04213 + 0.01365 / n) / n;
- }
-}
-
-// Returns the AndersonDarling p-value given n and the value of the statistic
-double AndersonDarlingPValue(int n, double z) {
- double ad = AndersonDarlingInf(z);
- double errfix = AndersonDarlingErrFix(n, ad);
- return ad + errfix;
-}
-
-double AndersonDarlingStatistic(const std::vector<double>& random_sample) {
- int n = random_sample.size();
- double ad_sum = 0;
- for (int i = 0; i < n; i++) {
- ad_sum += (2 * i + 1) *
- std::log(random_sample[i] * (1 - random_sample[n - 1 - i]));
- }
- double ad_statistic = -n - 1 / static_cast<double>(n) * ad_sum;
- return ad_statistic;
-}
-
-// Tests if the array of doubles is uniformly distributed.
-// Returns the p-value of the Anderson Darling Statistic
-// for the given set of sorted random doubles
-// See "Evaluating the Anderson-Darling Distribution" by
-// Marsaglia and Marsaglia for details.
-double AndersonDarlingTest(const std::vector<double>& random_sample) {
- double ad_statistic = AndersonDarlingStatistic(random_sample);
- double p = AndersonDarlingPValue(random_sample.size(), ad_statistic);
- return p;
-}
-
-TEST(ExponentialBiasedTest, CoinTossDemoWithGetSkipCount) {
- ExponentialBiased eb;
- for (int runs = 0; runs < 10; ++runs) {
- for (int flips = eb.GetSkipCount(1); flips > 0; --flips) {
- printf("head...");
- }
- printf("tail\n");
- }
- int heads = 0;
- for (int i = 0; i < 10000000; i += 1 + eb.GetSkipCount(1)) {
- ++heads;
- }
- printf("Heads = %d (%f%%)\n", heads, 100.0 * heads / 10000000);
-}
-
-TEST(ExponentialBiasedTest, SampleDemoWithStride) {
- ExponentialBiased eb;
- int stride = eb.GetStride(10);
- int samples = 0;
- for (int i = 0; i < 10000000; ++i) {
- if (--stride == 0) {
- ++samples;
- stride = eb.GetStride(10);
- }
- }
- printf("Samples = %d (%f%%)\n", samples, 100.0 * samples / 10000000);
-}
-
-
-// Testing that NextRandom generates uniform random numbers. Applies the
-// Anderson-Darling test for uniformity
-TEST(ExponentialBiasedTest, TestNextRandom) {
- for (auto n : std::vector<int>({
- 10, // Check short-range correlation
- 100, 1000,
- 10000 // Make sure there's no systemic error
- })) {
- uint64_t x = 1;
- // This assumes that the prng returns 48 bit numbers
- uint64_t max_prng_value = static_cast<uint64_t>(1) << 48;
- // Initialize.
- for (int i = 1; i <= 20; i++) {
- x = ExponentialBiased::NextRandom(x);
- }
- std::vector<uint64_t> int_random_sample(n);
- // Collect samples
- for (int i = 0; i < n; i++) {
- int_random_sample[i] = x;
- x = ExponentialBiased::NextRandom(x);
- }
- // First sort them...
- std::sort(int_random_sample.begin(), int_random_sample.end());
- std::vector<double> random_sample(n);
- // Convert them to uniform randoms (in the range [0,1])
- for (int i = 0; i < n; i++) {
- random_sample[i] =
- static_cast<double>(int_random_sample[i]) / max_prng_value;
- }
- // Now compute the Anderson-Darling statistic
- double ad_pvalue = AndersonDarlingTest(random_sample);
- EXPECT_GT(std::min(ad_pvalue, 1 - ad_pvalue), 0.0001)
- << "prng is not uniform: n = " << n << " p = " << ad_pvalue;
- }
-}
-
-// The generator needs to be available as a thread_local and as a static
-// variable.
-TEST(ExponentialBiasedTest, InitializationModes) {
- ABSL_CONST_INIT static ExponentialBiased eb_static;
- EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0));
-
-#if ABSL_HAVE_THREAD_LOCAL
- thread_local ExponentialBiased eb_thread;
- EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0));
-#endif
-
- ExponentialBiased eb_stack;
- EXPECT_THAT(eb_stack.GetSkipCount(2), Ge(0));
-}
-
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/abseil-cpp/absl/base/internal/fast_type_id.h b/abseil-cpp/absl/base/internal/fast_type_id.h
index 3db59e8..a547b3a 100644
--- a/abseil-cpp/absl/base/internal/fast_type_id.h
+++ b/abseil-cpp/absl/base/internal/fast_type_id.h
@@ -28,8 +28,10 @@ struct FastTypeTag {
constexpr static char dummy_var = 0;
};
+#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
template <typename Type>
constexpr char FastTypeTag<Type>::dummy_var;
+#endif
// FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
// passed-in type. These are meant to be good match for keys into maps or
diff --git a/abseil-cpp/absl/base/internal/inline_variable.h b/abseil-cpp/absl/base/internal/inline_variable.h
index 130d8c2..df933fa 100644
--- a/abseil-cpp/absl/base/internal/inline_variable.h
+++ b/abseil-cpp/absl/base/internal/inline_variable.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
-#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
+#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
+#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
#include <type_traits>
@@ -104,4 +104,4 @@
#endif // __cpp_inline_variables
-#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
+#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
diff --git a/abseil-cpp/absl/base/internal/inline_variable_testing.h b/abseil-cpp/absl/base/internal/inline_variable_testing.h
index 3856b9f..f3c8145 100644
--- a/abseil-cpp/absl/base/internal/inline_variable_testing.h
+++ b/abseil-cpp/absl/base/internal/inline_variable_testing.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_BASE_INLINE_VARIABLE_TESTING_H_
-#define ABSL_BASE_INLINE_VARIABLE_TESTING_H_
+#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
+#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
#include "absl/base/internal/inline_variable.h"
@@ -43,4 +43,4 @@ const int& get_int_b();
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_BASE_INLINE_VARIABLE_TESTING_H_
+#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
diff --git a/abseil-cpp/absl/base/internal/invoke.h b/abseil-cpp/absl/base/internal/invoke.h
index 5c71f32..643c2a4 100644
--- a/abseil-cpp/absl/base/internal/invoke.h
+++ b/abseil-cpp/absl/base/internal/invoke.h
@@ -14,6 +14,8 @@
//
// absl::base_internal::invoke(f, args...) is an implementation of
// INVOKE(f, args...) from section [func.require] of the C++ standard.
+// When compiled as C++17 and later versions, it is implemented as an alias of
+// std::invoke.
//
// [func.require]
// Define INVOKE (f, t1, t2, ..., tN) as follows:
@@ -35,6 +37,26 @@
#ifndef ABSL_BASE_INTERNAL_INVOKE_H_
#define ABSL_BASE_INTERNAL_INVOKE_H_
+#include "absl/base/config.h"
+
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+
+#include <functional>
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+using std::invoke;
+using std::invoke_result_t;
+using std::is_invocable_r;
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#else // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+
#include <algorithm>
#include <type_traits>
#include <utility>
@@ -80,8 +102,18 @@ struct MemFunAndRef : StrippedAccept<MemFunAndRef> {
static decltype((std::declval<Obj>().*
std::declval<MemFun>())(std::declval<Args>()...))
Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) {
+// Ignore bogus GCC warnings on this line.
+// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101436 for similar example.
+#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
return (std::forward<Obj>(obj).*
std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
+#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
+#pragma GCC diagnostic pop
+#endif
}
};
@@ -180,8 +212,30 @@ invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
std::forward<Args>(args)...);
}
+
+template <typename AlwaysVoid, typename, typename, typename...>
+struct IsInvocableRImpl : std::false_type {};
+
+template <typename R, typename F, typename... Args>
+struct IsInvocableRImpl<
+ absl::void_t<absl::base_internal::invoke_result_t<F, Args...> >, R, F,
+ Args...>
+ : std::integral_constant<
+ bool,
+ std::is_convertible<absl::base_internal::invoke_result_t<F, Args...>,
+ R>::value ||
+ std::is_void<R>::value> {};
+
+// Type trait whose member `value` is true if invoking `F` with `Args` is valid,
+// and either the return type is convertible to `R`, or `R` is void.
+// C++11-compatible version of `std::is_invocable_r`.
+template <typename R, typename F, typename... Args>
+using is_invocable_r = IsInvocableRImpl<void, R, F, Args...>;
+
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
+#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+
#endif // ABSL_BASE_INTERNAL_INVOKE_H_
diff --git a/abseil-cpp/absl/base/internal/low_level_alloc.cc b/abseil-cpp/absl/base/internal/low_level_alloc.cc
index 229ab91..6d2cfea 100644
--- a/abseil-cpp/absl/base/internal/low_level_alloc.cc
+++ b/abseil-cpp/absl/base/internal/low_level_alloc.cc
@@ -42,25 +42,25 @@
#include <windows.h>
#endif
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
+
#include <string.h>
+
#include <algorithm>
#include <atomic>
#include <cerrno>
#include <cstddef>
-#include <new> // for placement-new
+#include <new> // for placement-new
#include "absl/base/dynamic_annotations.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/spinlock.h"
-// MAP_ANONYMOUS
-#if defined(__APPLE__)
-// For mmap, Linux defines both MAP_ANONYMOUS and MAP_ANON and says MAP_ANON is
-// deprecated. In Darwin, MAP_ANON is all there is.
-#if !defined MAP_ANONYMOUS
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
#define MAP_ANONYMOUS MAP_ANON
-#endif // !MAP_ANONYMOUS
-#endif // __APPLE__
+#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -122,7 +122,7 @@ static int IntLog2(size_t size, size_t base) {
static int Random(uint32_t *state) {
uint32_t r = *state;
int result = 1;
- while ((((r = r*1103515245 + 12345) >> 30) & 1) == 0) {
+ while ((((r = r * 1103515245 + 12345) >> 30) & 1) == 0) {
result++;
}
*state = r;
@@ -144,7 +144,7 @@ static int LLA_SkiplistLevels(size_t size, size_t base, uint32_t *random) {
size_t max_fit = (size - offsetof(AllocList, next)) / sizeof(AllocList *);
int level = IntLog2(size, base) + (random != nullptr ? Random(random) : 1);
if (static_cast<size_t>(level) > max_fit) level = static_cast<int>(max_fit);
- if (level > kMaxLevel-1) level = kMaxLevel - 1;
+ if (level > kMaxLevel - 1) level = kMaxLevel - 1;
ABSL_RAW_CHECK(level >= 1, "block not big enough for even one level");
return level;
}
@@ -153,8 +153,8 @@ static int LLA_SkiplistLevels(size_t size, size_t base, uint32_t *random) {
// For 0 <= i < head->levels, set prev[i] to "no_greater", where no_greater
// points to the last element at level i in the AllocList less than *e, or is
// head if no such element exists.
-static AllocList *LLA_SkiplistSearch(AllocList *head,
- AllocList *e, AllocList **prev) {
+static AllocList *LLA_SkiplistSearch(AllocList *head, AllocList *e,
+ AllocList **prev) {
AllocList *p = head;
for (int level = head->levels - 1; level >= 0; level--) {
for (AllocList *n; (n = p->next[level]) != nullptr && n < e; p = n) {
@@ -190,7 +190,7 @@ static void LLA_SkiplistDelete(AllocList *head, AllocList *e,
prev[i]->next[i] = e->next[i];
}
while (head->levels > 0 && head->next[head->levels - 1] == nullptr) {
- head->levels--; // reduce head->levels if level unused
+ head->levels--; // reduce head->levels if level unused
}
}
@@ -249,9 +249,9 @@ void CreateGlobalArenas() {
// Returns a global arena that does not call into hooks. Used by NewArena()
// when kCallMallocHook is not set.
-LowLevelAlloc::Arena* UnhookedArena() {
+LowLevelAlloc::Arena *UnhookedArena() {
base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas);
- return reinterpret_cast<LowLevelAlloc::Arena*>(&unhooked_arena_storage);
+ return reinterpret_cast<LowLevelAlloc::Arena *>(&unhooked_arena_storage);
}
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
@@ -269,7 +269,7 @@ LowLevelAlloc::Arena *UnhookedAsyncSigSafeArena() {
// Returns the default arena, as used by LowLevelAlloc::Alloc() and friends.
LowLevelAlloc::Arena *LowLevelAlloc::DefaultArena() {
base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas);
- return reinterpret_cast<LowLevelAlloc::Arena*>(&default_arena_storage);
+ return reinterpret_cast<LowLevelAlloc::Arena *>(&default_arena_storage);
}
// magic numbers to identify allocated and unallocated blocks
@@ -332,7 +332,7 @@ size_t GetPageSize() {
#elif defined(__wasm__) || defined(__asmjs__)
return getpagesize();
#else
- return sysconf(_SC_PAGESIZE);
+ return static_cast<size_t>(sysconf(_SC_PAGESIZE));
#endif
}
@@ -356,15 +356,14 @@ LowLevelAlloc::Arena::Arena(uint32_t flags_value)
min_size(2 * round_up),
random(0) {
freelist.header.size = 0;
- freelist.header.magic =
- Magic(kMagicUnallocated, &freelist.header);
+ freelist.header.magic = Magic(kMagicUnallocated, &freelist.header);
freelist.header.arena = this;
freelist.levels = 0;
memset(freelist.next, 0, sizeof(freelist.next));
}
// L < meta_data_arena->mu
-LowLevelAlloc::Arena *LowLevelAlloc::NewArena(int32_t flags) {
+LowLevelAlloc::Arena *LowLevelAlloc::NewArena(uint32_t flags) {
Arena *meta_data_arena = DefaultArena();
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
@@ -375,7 +374,7 @@ LowLevelAlloc::Arena *LowLevelAlloc::NewArena(int32_t flags) {
meta_data_arena = UnhookedArena();
}
Arena *result =
- new (AllocWithArena(sizeof (*result), meta_data_arena)) Arena(flags);
+ new (AllocWithArena(sizeof(*result), meta_data_arena)) Arena(flags);
return result;
}
@@ -480,8 +479,8 @@ static void Coalesce(AllocList *a) {
AllocList *prev[kMaxLevel];
LLA_SkiplistDelete(&arena->freelist, n, prev);
LLA_SkiplistDelete(&arena->freelist, a, prev);
- a->levels = LLA_SkiplistLevels(a->header.size, arena->min_size,
- &arena->random);
+ a->levels =
+ LLA_SkiplistLevels(a->header.size, arena->min_size, &arena->random);
LLA_SkiplistInsert(&arena->freelist, a, prev);
}
}
@@ -489,27 +488,27 @@ static void Coalesce(AllocList *a) {
// Adds block at location "v" to the free list
// L >= arena->mu
static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena) {
- AllocList *f = reinterpret_cast<AllocList *>(
- reinterpret_cast<char *>(v) - sizeof (f->header));
+ AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) -
+ sizeof(f->header));
ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),
"bad magic number in AddToFreelist()");
ABSL_RAW_CHECK(f->header.arena == arena,
"bad arena pointer in AddToFreelist()");
- f->levels = LLA_SkiplistLevels(f->header.size, arena->min_size,
- &arena->random);
+ f->levels =
+ LLA_SkiplistLevels(f->header.size, arena->min_size, &arena->random);
AllocList *prev[kMaxLevel];
LLA_SkiplistInsert(&arena->freelist, f, prev);
f->header.magic = Magic(kMagicUnallocated, &f->header);
- Coalesce(f); // maybe coalesce with successor
- Coalesce(prev[0]); // maybe coalesce with predecessor
+ Coalesce(f); // maybe coalesce with successor
+ Coalesce(prev[0]); // maybe coalesce with predecessor
}
// Frees storage allocated by LowLevelAlloc::Alloc().
// L < arena->mu
void LowLevelAlloc::Free(void *v) {
if (v != nullptr) {
- AllocList *f = reinterpret_cast<AllocList *>(
- reinterpret_cast<char *>(v) - sizeof (f->header));
+ AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) -
+ sizeof(f->header));
LowLevelAlloc::Arena *arena = f->header.arena;
ArenaLock section(arena);
AddToFreelist(v, arena);
@@ -524,21 +523,21 @@ void LowLevelAlloc::Free(void *v) {
static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
void *result = nullptr;
if (request != 0) {
- AllocList *s; // will point to region that satisfies request
+ AllocList *s; // will point to region that satisfies request
ArenaLock section(arena);
// round up with header
- size_t req_rnd = RoundUp(CheckedAdd(request, sizeof (s->header)),
- arena->round_up);
- for (;;) { // loop until we find a suitable region
+ size_t req_rnd =
+ RoundUp(CheckedAdd(request, sizeof(s->header)), arena->round_up);
+ for (;;) { // loop until we find a suitable region
// find the minimum levels that a block of this size must have
int i = LLA_SkiplistLevels(req_rnd, arena->min_size, nullptr) - 1;
- if (i < arena->freelist.levels) { // potential blocks exist
+ if (i < arena->freelist.levels) { // potential blocks exist
AllocList *before = &arena->freelist; // predecessor of s
while ((s = Next(i, before, arena)) != nullptr &&
s->header.size < req_rnd) {
before = s;
}
- if (s != nullptr) { // we found a region
+ if (s != nullptr) { // we found a region
break;
}
}
@@ -550,7 +549,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
size_t new_pages_size = RoundUp(req_rnd, arena->pagesize * 16);
void *new_pages;
#ifdef _WIN32
- new_pages = VirtualAlloc(0, new_pages_size,
+ new_pages = VirtualAlloc(nullptr, new_pages_size,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
ABSL_RAW_CHECK(new_pages != nullptr, "VirtualAlloc failed");
#else
@@ -570,6 +569,18 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
ABSL_RAW_LOG(FATAL, "mmap error: %d", errno);
}
+#ifdef __linux__
+#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
+ // Attempt to name the allocated address range in /proc/$PID/smaps on
+ // Linux.
+ //
+ // This invocation of prctl() may fail if the Linux kernel was not
+ // configured with the CONFIG_ANON_VMA_NAME option. This is OK since
+ // the naming of arenas is primarily a debugging aid.
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, new_pages, new_pages_size,
+ "absl");
+#endif
+#endif // __linux__
#endif // _WIN32
arena->mu.Lock();
s = reinterpret_cast<AllocList *>(new_pages);
@@ -580,12 +591,12 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
AddToFreelist(&s->levels, arena); // insert new region into free list
}
AllocList *prev[kMaxLevel];
- LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list
+ LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list
// s points to the first free region that's big enough
if (CheckedAdd(req_rnd, arena->min_size) <= s->header.size) {
// big enough to split
- AllocList *n = reinterpret_cast<AllocList *>
- (req_rnd + reinterpret_cast<char *>(s));
+ AllocList *n =
+ reinterpret_cast<AllocList *>(req_rnd + reinterpret_cast<char *>(s));
n->header.size = s->header.size - req_rnd;
n->header.magic = Magic(kMagicAllocated, &n->header);
n->header.arena = arena;
diff --git a/abseil-cpp/absl/base/internal/low_level_alloc.h b/abseil-cpp/absl/base/internal/low_level_alloc.h
index db91951..c2f1f25 100644
--- a/abseil-cpp/absl/base/internal/low_level_alloc.h
+++ b/abseil-cpp/absl/base/internal/low_level_alloc.h
@@ -46,7 +46,8 @@
// for more information.
#ifdef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
#error ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING cannot be directly set
-#elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__)
+#elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__) || \
+ defined(__hexagon__)
#define ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING 1
#endif
@@ -103,7 +104,7 @@ class LowLevelAlloc {
// the provided flags. For example, the call NewArena(kAsyncSignalSafe)
// is itself async-signal-safe, as well as generatating an arena that provides
// async-signal-safe Alloc/Free.
- static Arena *NewArena(int32_t flags);
+ static Arena *NewArena(uint32_t flags);
// Destroys an arena allocated by NewArena and returns true,
// provided no allocated blocks remain in the arena.
diff --git a/abseil-cpp/absl/base/internal/low_level_alloc_test.cc b/abseil-cpp/absl/base/internal/low_level_alloc_test.cc
index 2f2eaff..8fdec09 100644
--- a/abseil-cpp/absl/base/internal/low_level_alloc_test.cc
+++ b/abseil-cpp/absl/base/internal/low_level_alloc_test.cc
@@ -21,6 +21,10 @@
#include <unordered_map>
#include <utility>
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
#include "absl/container/node_hash_map.h"
namespace absl {
@@ -82,7 +86,7 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
AllocMap::iterator it;
BlockDesc block_desc;
int rnd;
- LowLevelAlloc::Arena *arena = 0;
+ LowLevelAlloc::Arena *arena = nullptr;
if (use_new_arena) {
int32_t flags = call_malloc_hook ? LowLevelAlloc::kCallMallocHook : 0;
arena = LowLevelAlloc::NewArena(flags);
@@ -97,11 +101,10 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
case 0: // coin came up heads: add a block
using_low_level_alloc = true;
block_desc.len = rand() & 0x3fff;
- block_desc.ptr =
- reinterpret_cast<char *>(
- arena == 0
- ? LowLevelAlloc::Alloc(block_desc.len)
- : LowLevelAlloc::AllocWithArena(block_desc.len, arena));
+ block_desc.ptr = reinterpret_cast<char *>(
+ arena == nullptr
+ ? LowLevelAlloc::Alloc(block_desc.len)
+ : LowLevelAlloc::AllocWithArena(block_desc.len, arena));
using_low_level_alloc = false;
RandomizeBlockDesc(&block_desc);
rnd = rand();
@@ -158,5 +161,20 @@ ABSL_NAMESPACE_END
int main(int argc, char *argv[]) {
// The actual test runs in the global constructor of `before_main`.
printf("PASS\n");
+#ifdef __EMSCRIPTEN__
+ // clang-format off
+// This is JS here. Don't try to format it.
+ MAIN_THREAD_EM_ASM({
+ if (ENVIRONMENT_IS_WEB) {
+ if (typeof TEST_FINISH === 'function') {
+ TEST_FINISH($0);
+ } else {
+ console.error('Attempted to exit with status ' + $0);
+ console.error('But TEST_FINSIHED is not a function.');
+ }
+ }
+ }, 0);
+// clang-format on
+#endif
return 0;
}
diff --git a/abseil-cpp/absl/base/internal/low_level_scheduling.h b/abseil-cpp/absl/base/internal/low_level_scheduling.h
index 6ef79fb..9baccc0 100644
--- a/abseil-cpp/absl/base/internal/low_level_scheduling.h
+++ b/abseil-cpp/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;
};
//------------------------------------------------------------------------------
diff --git a/abseil-cpp/absl/base/internal/nullability_impl.h b/abseil-cpp/absl/base/internal/nullability_impl.h
new file mode 100644
index 0000000..36e1b33
--- /dev/null
+++ b/abseil-cpp/absl/base/internal/nullability_impl.h
@@ -0,0 +1,106 @@
+// Copyright 2023 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_BASE_INTERNAL_NULLABILITY_IMPL_H_
+#define ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
+
+#include <memory>
+#include <type_traits>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+
+namespace nullability_internal {
+
+// `IsNullabilityCompatible` checks whether its first argument is a class
+// explicitly tagged as supporting nullability annotations. The tag is the type
+// declaration `absl_nullability_compatible`.
+template <typename, typename = void>
+struct IsNullabilityCompatible : std::false_type {};
+
+template <typename T>
+struct IsNullabilityCompatible<
+ T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type {
+};
+
+template <typename T>
+constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value;
+
+template <typename T>
+constexpr bool IsSupportedType<T*> = true;
+
+template <typename T, typename U>
+constexpr bool IsSupportedType<T U::*> = true;
+
+template <typename T, typename... Deleter>
+constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true;
+
+template <typename T>
+constexpr bool IsSupportedType<std::shared_ptr<T>> = true;
+
+template <typename T>
+struct EnableNullable {
+ static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
+ "Template argument must be a raw or supported smart pointer "
+ "type. See absl/base/nullability.h.");
+ using type = T;
+};
+
+template <typename T>
+struct EnableNonnull {
+ static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
+ "Template argument must be a raw or supported smart pointer "
+ "type. See absl/base/nullability.h.");
+ using type = T;
+};
+
+template <typename T>
+struct EnableNullabilityUnknown {
+ static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
+ "Template argument must be a raw or supported smart pointer "
+ "type. See absl/base/nullability.h.");
+ using type = T;
+};
+
+// Note: we do not apply Clang nullability attributes (e.g. _Nullable). These
+// only support raw pointers, and conditionally enabling them only for raw
+// pointers inhibits template arg deduction. Ideally, they would support all
+// pointer-like types.
+template <typename T, typename = typename EnableNullable<T>::type>
+using NullableImpl
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+ [[clang::annotate("Nullable")]]
+#endif
+ = T;
+
+template <typename T, typename = typename EnableNonnull<T>::type>
+using NonnullImpl
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+ [[clang::annotate("Nonnull")]]
+#endif
+ = T;
+
+template <typename T, typename = typename EnableNullabilityUnknown<T>::type>
+using NullabilityUnknownImpl
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+ [[clang::annotate("Nullability_Unspecified")]]
+#endif
+ = T;
+
+} // namespace nullability_internal
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
diff --git a/abseil-cpp/absl/base/internal/periodic_sampler.cc b/abseil-cpp/absl/base/internal/periodic_sampler.cc
deleted file mode 100644
index 520dabb..0000000
--- a/abseil-cpp/absl/base/internal/periodic_sampler.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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.
-
-#include "absl/base/internal/periodic_sampler.h"
-
-#include <atomic>
-
-#include "absl/base/internal/exponential_biased.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-
-int64_t PeriodicSamplerBase::GetExponentialBiased(int period) noexcept {
- return rng_.GetStride(period);
-}
-
-bool PeriodicSamplerBase::SubtleConfirmSample() noexcept {
- int current_period = period();
-
- // Deal with period case 0 (always off) and 1 (always on)
- if (ABSL_PREDICT_FALSE(current_period < 2)) {
- stride_ = 0;
- return current_period == 1;
- }
-
- // Check if this is the first call to Sample()
- if (ABSL_PREDICT_FALSE(stride_ == 1)) {
- stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period));
- if (static_cast<int64_t>(stride_) < -1) {
- ++stride_;
- return false;
- }
- }
-
- stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period));
- return true;
-}
-
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/abseil-cpp/absl/base/internal/periodic_sampler.h b/abseil-cpp/absl/base/internal/periodic_sampler.h
deleted file mode 100644
index f8a8679..0000000
--- a/abseil-cpp/absl/base/internal/periodic_sampler.h
+++ /dev/null
@@ -1,211 +0,0 @@
-// 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_BASE_INTERNAL_PERIODIC_SAMPLER_H_
-#define ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_
-
-#include <stdint.h>
-
-#include <atomic>
-
-#include "absl/base/internal/exponential_biased.h"
-#include "absl/base/optimization.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-
-// PeriodicSamplerBase provides the basic period sampler implementation.
-//
-// This is the base class for the templated PeriodicSampler class, which holds
-// a global std::atomic value identified by a user defined tag, such that
-// each specific PeriodSampler implementation holds its own global period.
-//
-// PeriodicSamplerBase is thread-compatible except where stated otherwise.
-class PeriodicSamplerBase {
- public:
- // PeriodicSamplerBase is trivial / copyable / movable / destructible.
- PeriodicSamplerBase() = default;
- PeriodicSamplerBase(PeriodicSamplerBase&&) = default;
- PeriodicSamplerBase(const PeriodicSamplerBase&) = default;
-
- // Returns true roughly once every `period` calls. This is established by a
- // randomly picked `stride` that is counted down on each call to `Sample`.
- // This stride is picked such that the probability of `Sample()` returning
- // true is 1 in `period`.
- inline bool Sample() noexcept;
-
- // The below methods are intended for optimized use cases where the
- // size of the inlined fast path code is highly important. Applications
- // should use the `Sample()` method unless they have proof that their
- // specific use case requires the optimizations offered by these methods.
- //
- // An example of such a use case is SwissTable sampling. All sampling checks
- // are in inlined SwissTable methods, and the number of call sites is huge.
- // In this case, the inlined code size added to each translation unit calling
- // SwissTable methods is non-trivial.
- //
- // The `SubtleMaybeSample()` function spuriously returns true even if the
- // function should not be sampled, applications MUST match each call to
- // 'SubtleMaybeSample()' returning true with a `SubtleConfirmSample()` call,
- // and use the result of the latter as the sampling decision.
- // In other words: the code should logically be equivalent to:
- //
- // if (SubtleMaybeSample() && SubtleConfirmSample()) {
- // // Sample this call
- // }
- //
- // In the 'inline-size' optimized case, the `SubtleConfirmSample()` call can
- // be placed out of line, for example, the typical use case looks as follows:
- //
- // // --- frobber.h -----------
- // void FrobberSampled();
- //
- // inline void FrobberImpl() {
- // // ...
- // }
- //
- // inline void Frobber() {
- // if (ABSL_PREDICT_FALSE(sampler.SubtleMaybeSample())) {
- // FrobberSampled();
- // } else {
- // FrobberImpl();
- // }
- // }
- //
- // // --- frobber.cc -----------
- // void FrobberSampled() {
- // if (!sampler.SubtleConfirmSample())) {
- // // Spurious false positive
- // FrobberImpl();
- // return;
- // }
- //
- // // Sampled execution
- // // ...
- // }
- inline bool SubtleMaybeSample() noexcept;
- bool SubtleConfirmSample() noexcept;
-
- protected:
- // We explicitly don't use a virtual destructor as this class is never
- // virtually destroyed, and it keeps the class trivial, which avoids TLS
- // prologue and epilogue code for our TLS instances.
- ~PeriodicSamplerBase() = default;
-
- // Returns the next stride for our sampler.
- // This function is virtual for testing purposes only.
- virtual int64_t GetExponentialBiased(int period) noexcept;
-
- private:
- // Returns the current period of this sampler. Thread-safe.
- virtual int period() const noexcept = 0;
-
- // Keep and decrement stride_ as an unsigned integer, but compare the value
- // to zero casted as a signed int. clang and msvc do not create optimum code
- // if we use signed for the combined decrement and sign comparison.
- //
- // Below 3 alternative options, all compiles generate the best code
- // using the unsigned increment <---> signed int comparison option.
- //
- // Option 1:
- // int64_t stride_;
- // if (ABSL_PREDICT_TRUE(++stride_ < 0)) { ... }
- //
- // GCC x64 (OK) : https://gcc.godbolt.org/z/R5MzzA
- // GCC ppc (OK) : https://gcc.godbolt.org/z/z7NZAt
- // Clang x64 (BAD): https://gcc.godbolt.org/z/t4gPsd
- // ICC x64 (OK) : https://gcc.godbolt.org/z/rE6s8W
- // MSVC x64 (OK) : https://gcc.godbolt.org/z/ARMXqS
- //
- // Option 2:
- // int64_t stride_ = 0;
- // if (ABSL_PREDICT_TRUE(--stride_ >= 0)) { ... }
- //
- // GCC x64 (OK) : https://gcc.godbolt.org/z/jSQxYK
- // GCC ppc (OK) : https://gcc.godbolt.org/z/VJdYaA
- // Clang x64 (BAD): https://gcc.godbolt.org/z/Xm4NjX
- // ICC x64 (OK) : https://gcc.godbolt.org/z/4snaFd
- // MSVC x64 (BAD): https://gcc.godbolt.org/z/BgnEKE
- //
- // Option 3:
- // uint64_t stride_;
- // if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) { ... }
- //
- // GCC x64 (OK) : https://gcc.godbolt.org/z/bFbfPy
- // GCC ppc (OK) : https://gcc.godbolt.org/z/S9KkUE
- // Clang x64 (OK) : https://gcc.godbolt.org/z/UYzRb4
- // ICC x64 (OK) : https://gcc.godbolt.org/z/ptTNfD
- // MSVC x64 (OK) : https://gcc.godbolt.org/z/76j4-5
- uint64_t stride_ = 0;
- ExponentialBiased rng_;
-};
-
-inline bool PeriodicSamplerBase::SubtleMaybeSample() noexcept {
- // See comments on `stride_` for the unsigned increment / signed compare.
- if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) {
- return false;
- }
- return true;
-}
-
-inline bool PeriodicSamplerBase::Sample() noexcept {
- return ABSL_PREDICT_FALSE(SubtleMaybeSample()) ? SubtleConfirmSample()
- : false;
-}
-
-// PeriodicSampler is a concreted periodic sampler implementation.
-// The user provided Tag identifies the implementation, and is required to
-// isolate the global state of this instance from other instances.
-//
-// Typical use case:
-//
-// struct HashTablezTag {};
-// thread_local PeriodicSampler sampler;
-//
-// void HashTableSamplingLogic(...) {
-// if (sampler.Sample()) {
-// HashTableSlowSamplePath(...);
-// }
-// }
-//
-template <typename Tag, int default_period = 0>
-class PeriodicSampler final : public PeriodicSamplerBase {
- public:
- ~PeriodicSampler() = default;
-
- int period() const noexcept final {
- return period_.load(std::memory_order_relaxed);
- }
-
- // Sets the global period for this sampler. Thread-safe.
- // Setting a period of 0 disables the sampler, i.e., every call to Sample()
- // will return false. Setting a period of 1 puts the sampler in 'always on'
- // mode, i.e., every call to Sample() returns true.
- static void SetGlobalPeriod(int period) {
- period_.store(period, std::memory_order_relaxed);
- }
-
- private:
- static std::atomic<int> period_;
-};
-
-template <typename Tag, int default_period>
-std::atomic<int> PeriodicSampler<Tag, default_period>::period_(default_period);
-
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_
diff --git a/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc b/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc
deleted file mode 100644
index 5ad469c..0000000
--- a/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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.
-
-#include "benchmark/benchmark.h"
-#include "absl/base/internal/periodic_sampler.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-namespace {
-
-template <typename Sampler>
-void BM_Sample(Sampler* sampler, benchmark::State& state) {
- for (auto _ : state) {
- benchmark::DoNotOptimize(sampler);
- benchmark::DoNotOptimize(sampler->Sample());
- }
-}
-
-template <typename Sampler>
-void BM_SampleMinunumInlined(Sampler* sampler, benchmark::State& state) {
- for (auto _ : state) {
- benchmark::DoNotOptimize(sampler);
- if (ABSL_PREDICT_FALSE(sampler->SubtleMaybeSample())) {
- benchmark::DoNotOptimize(sampler->SubtleConfirmSample());
- }
- }
-}
-
-void BM_PeriodicSampler_TinySample(benchmark::State& state) {
- struct Tag {};
- PeriodicSampler<Tag, 10> sampler;
- BM_Sample(&sampler, state);
-}
-BENCHMARK(BM_PeriodicSampler_TinySample);
-
-void BM_PeriodicSampler_ShortSample(benchmark::State& state) {
- struct Tag {};
- PeriodicSampler<Tag, 1024> sampler;
- BM_Sample(&sampler, state);
-}
-BENCHMARK(BM_PeriodicSampler_ShortSample);
-
-void BM_PeriodicSampler_LongSample(benchmark::State& state) {
- struct Tag {};
- PeriodicSampler<Tag, 1024 * 1024> sampler;
- BM_Sample(&sampler, state);
-}
-BENCHMARK(BM_PeriodicSampler_LongSample);
-
-void BM_PeriodicSampler_LongSampleMinunumInlined(benchmark::State& state) {
- struct Tag {};
- PeriodicSampler<Tag, 1024 * 1024> sampler;
- BM_SampleMinunumInlined(&sampler, state);
-}
-BENCHMARK(BM_PeriodicSampler_LongSampleMinunumInlined);
-
-void BM_PeriodicSampler_Disabled(benchmark::State& state) {
- struct Tag {};
- PeriodicSampler<Tag, 0> sampler;
- BM_Sample(&sampler, state);
-}
-BENCHMARK(BM_PeriodicSampler_Disabled);
-
-} // namespace
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/abseil-cpp/absl/base/internal/periodic_sampler_test.cc b/abseil-cpp/absl/base/internal/periodic_sampler_test.cc
deleted file mode 100644
index 3b301e3..0000000
--- a/abseil-cpp/absl/base/internal/periodic_sampler_test.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-// 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.
-
-#include "absl/base/internal/periodic_sampler.h"
-
-#include <thread> // NOLINT(build/c++11)
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/attributes.h"
-#include "absl/base/macros.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-namespace {
-
-using testing::Eq;
-using testing::Return;
-using testing::StrictMock;
-
-class MockPeriodicSampler : public PeriodicSamplerBase {
- public:
- virtual ~MockPeriodicSampler() = default;
-
- MOCK_METHOD(int, period, (), (const, noexcept));
- MOCK_METHOD(int64_t, GetExponentialBiased, (int), (noexcept));
-};
-
-TEST(PeriodicSamplerBaseTest, Sample) {
- StrictMock<MockPeriodicSampler> sampler;
-
- EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(16));
- EXPECT_CALL(sampler, GetExponentialBiased(16))
- .WillOnce(Return(2))
- .WillOnce(Return(3))
- .WillOnce(Return(4));
-
- EXPECT_FALSE(sampler.Sample());
- EXPECT_TRUE(sampler.Sample());
-
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
- EXPECT_TRUE(sampler.Sample());
-
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
-}
-
-TEST(PeriodicSamplerBaseTest, ImmediatelySample) {
- StrictMock<MockPeriodicSampler> sampler;
-
- EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16));
- EXPECT_CALL(sampler, GetExponentialBiased(16))
- .WillOnce(Return(1))
- .WillOnce(Return(2))
- .WillOnce(Return(3));
-
- EXPECT_TRUE(sampler.Sample());
-
- EXPECT_FALSE(sampler.Sample());
- EXPECT_TRUE(sampler.Sample());
-
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
-}
-
-TEST(PeriodicSamplerBaseTest, Disabled) {
- StrictMock<MockPeriodicSampler> sampler;
-
- EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(0));
-
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
-}
-
-TEST(PeriodicSamplerBaseTest, AlwaysOn) {
- StrictMock<MockPeriodicSampler> sampler;
-
- EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(1));
-
- EXPECT_TRUE(sampler.Sample());
- EXPECT_TRUE(sampler.Sample());
- EXPECT_TRUE(sampler.Sample());
-}
-
-TEST(PeriodicSamplerBaseTest, Disable) {
- StrictMock<MockPeriodicSampler> sampler;
-
- EXPECT_CALL(sampler, period()).WillOnce(Return(16));
- EXPECT_CALL(sampler, GetExponentialBiased(16)).WillOnce(Return(3));
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
-
- EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(0));
-
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
-}
-
-TEST(PeriodicSamplerBaseTest, Enable) {
- StrictMock<MockPeriodicSampler> sampler;
-
- EXPECT_CALL(sampler, period()).WillOnce(Return(0));
- EXPECT_FALSE(sampler.Sample());
-
- EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16));
- EXPECT_CALL(sampler, GetExponentialBiased(16))
- .Times(2)
- .WillRepeatedly(Return(3));
-
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
- EXPECT_TRUE(sampler.Sample());
-
- EXPECT_FALSE(sampler.Sample());
- EXPECT_FALSE(sampler.Sample());
-}
-
-TEST(PeriodicSamplerTest, ConstructConstInit) {
- struct Tag {};
- ABSL_CONST_INIT static PeriodicSampler<Tag> sampler;
- (void)sampler;
-}
-
-TEST(PeriodicSamplerTest, DefaultPeriod0) {
- struct Tag {};
- PeriodicSampler<Tag> sampler;
- EXPECT_THAT(sampler.period(), Eq(0));
-}
-
-TEST(PeriodicSamplerTest, DefaultPeriod) {
- struct Tag {};
- PeriodicSampler<Tag, 100> sampler;
- EXPECT_THAT(sampler.period(), Eq(100));
-}
-
-TEST(PeriodicSamplerTest, SetGlobalPeriod) {
- struct Tag1 {};
- struct Tag2 {};
- PeriodicSampler<Tag1, 25> sampler1;
- PeriodicSampler<Tag2, 50> sampler2;
-
- EXPECT_THAT(sampler1.period(), Eq(25));
- EXPECT_THAT(sampler2.period(), Eq(50));
-
- std::thread thread([] {
- PeriodicSampler<Tag1, 25> sampler1;
- PeriodicSampler<Tag2, 50> sampler2;
- EXPECT_THAT(sampler1.period(), Eq(25));
- EXPECT_THAT(sampler2.period(), Eq(50));
- sampler1.SetGlobalPeriod(10);
- sampler2.SetGlobalPeriod(20);
- });
- thread.join();
-
- EXPECT_THAT(sampler1.period(), Eq(10));
- EXPECT_THAT(sampler2.period(), Eq(20));
-}
-
-} // namespace
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/abseil-cpp/absl/base/internal/prefetch.h b/abseil-cpp/absl/base/internal/prefetch.h
new file mode 100644
index 0000000..aecfd87
--- /dev/null
+++ b/abseil-cpp/absl/base/internal/prefetch.h
@@ -0,0 +1,137 @@
+// Copyright 2022 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(b/265984188): remove all uses and delete this header.
+
+#ifndef ABSL_BASE_INTERNAL_PREFETCH_H_
+#define ABSL_BASE_INTERNAL_PREFETCH_H_
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/prefetch.h"
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#if defined(_MSC_VER) && defined(ABSL_INTERNAL_HAVE_SSE)
+#include <intrin.h>
+#pragma intrinsic(_mm_prefetch)
+#endif
+
+// Compatibility wrappers around __builtin_prefetch, to prefetch data
+// for read if supported by the toolchain.
+
+// Move data into the cache before it is read, or "prefetch" it.
+//
+// The value of `addr` is the address of the memory to prefetch. If
+// the target and compiler support it, data prefetch instructions are
+// generated. If the prefetch is done some time before the memory is
+// read, it may be in the cache by the time the read occurs.
+//
+// The function names specify the temporal locality heuristic applied,
+// using the names of Intel prefetch instructions:
+//
+// T0 - high degree of temporal locality; data should be left in as
+// many levels of the cache possible
+// T1 - moderate degree of temporal locality
+// T2 - low degree of temporal locality
+// Nta - no temporal locality, data need not be left in the cache
+// after the read
+//
+// Incorrect or gratuitous use of these functions can degrade
+// performance, so use them only when representative benchmarks show
+// an improvement.
+//
+// Example usage:
+//
+// absl::base_internal::PrefetchT0(addr);
+//
+// Currently, the different prefetch calls behave on some Intel
+// architectures as follows:
+//
+// SNB..SKL SKX
+// PrefetchT0() L1/L2/L3 L1/L2
+// PrefetchT1() L2/L3 L2
+// PrefetchT2() L2/L3 L2
+// PrefetchNta() L1/--/L3 L1*
+//
+// * On SKX PrefetchNta() will bring the line into L1 but will evict
+// from L3 cache. This might result in surprising behavior.
+//
+// SNB = Sandy Bridge, SKL = Skylake, SKX = Skylake Xeon.
+//
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead")
+inline void PrefetchT0(const void* address) {
+ absl::PrefetchToLocalCache(address);
+}
+
+ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead")
+inline void PrefetchNta(const void* address) {
+ absl::PrefetchToLocalCacheNta(address);
+}
+
+ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead")
+void PrefetchT1(const void* addr);
+
+ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead")
+void PrefetchT2(const void* addr);
+
+// Implementation details follow.
+
+#if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
+
+#define ABSL_INTERNAL_HAVE_PREFETCH 1
+
+// See __builtin_prefetch:
+// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
+//
+// These functions speculatively load for read only. This is
+// safe for all currently supported platforms. However, prefetch for
+// store may have problems depending on the target platform.
+//
+inline void PrefetchT1(const void* addr) {
+ // Note: this uses prefetcht1 on Intel.
+ __builtin_prefetch(addr, 0, 2);
+}
+inline void PrefetchT2(const void* addr) {
+ // Note: this uses prefetcht2 on Intel.
+ __builtin_prefetch(addr, 0, 1);
+}
+
+#elif defined(ABSL_INTERNAL_HAVE_SSE)
+
+#define ABSL_INTERNAL_HAVE_PREFETCH 1
+
+inline void PrefetchT1(const void* addr) {
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T1);
+}
+inline void PrefetchT2(const void* addr) {
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T2);
+}
+
+#else
+inline void PrefetchT1(const void*) {}
+inline void PrefetchT2(const void*) {}
+#endif
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_PREFETCH_H_
diff --git a/abseil-cpp/absl/base/internal/prefetch_test.cc b/abseil-cpp/absl/base/internal/prefetch_test.cc
new file mode 100644
index 0000000..7c1dae4
--- /dev/null
+++ b/abseil-cpp/absl/base/internal/prefetch_test.cc
@@ -0,0 +1,43 @@
+// Copyright 2022 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/base/internal/prefetch.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+int number = 42;
+
+TEST(Prefetch, TemporalLocalityNone) {
+ absl::base_internal::PrefetchNta(&number);
+ EXPECT_EQ(number, 42);
+}
+
+TEST(Prefetch, TemporalLocalityLow) {
+ absl::base_internal::PrefetchT2(&number);
+ EXPECT_EQ(number, 42);
+}
+
+TEST(Prefetch, TemporalLocalityMedium) {
+ absl::base_internal::PrefetchT1(&number);
+ EXPECT_EQ(number, 42);
+}
+
+TEST(Prefetch, TemporalLocalityHigh) {
+ absl::base_internal::PrefetchT0(&number);
+ EXPECT_EQ(number, 42);
+}
+
+} // namespace
diff --git a/abseil-cpp/absl/base/internal/raw_logging.cc b/abseil-cpp/absl/base/internal/raw_logging.cc
index ae8754c..4c922cc 100644
--- a/abseil-cpp/absl/base/internal/raw_logging.cc
+++ b/abseil-cpp/absl/base/internal/raw_logging.cc
@@ -14,15 +14,21 @@
#include "absl/base/internal/raw_logging.h"
-#include <stddef.h>
#include <cstdarg>
+#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#include <string>
+
+#ifdef __EMSCRIPTEN__
+#include <emscripten/console.h>
+#endif
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/atomic_hook.h"
+#include "absl/base/internal/errno_saver.h"
#include "absl/base/log_severity.h"
// We know how to perform low-level writes to stderr in POSIX and Windows. For
@@ -36,8 +42,8 @@
// This preprocessor token is also defined in raw_io.cc. If you need to copy
// this, consider moving both to config.h instead.
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
- defined(__Fuchsia__) || defined(__native_client__) || \
- defined(__EMSCRIPTEN__) || defined(__ASYLO__)
+ defined(__Fuchsia__) || defined(__native_client__) || \
+ defined(__OpenBSD__) || defined(__EMSCRIPTEN__) || defined(__ASYLO__)
#include <unistd.h>
@@ -50,7 +56,8 @@
// ABSL_HAVE_SYSCALL_WRITE is defined when the platform provides the syscall
// syscall(SYS_write, /*int*/ fd, /*char* */ buf, /*size_t*/ len);
// for low level operations that want to avoid libc.
-#if (defined(__linux__) || defined(__FreeBSD__)) && !defined(__ANDROID__)
+#if (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && \
+ !defined(__ANDROID__)
#include <sys/syscall.h>
#define ABSL_HAVE_SYSCALL_WRITE 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
@@ -67,36 +74,35 @@
#undef ABSL_HAVE_RAW_IO
#endif
-// 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
-// selected set of platforms for which we expect not to be able to raw log.
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace raw_log_internal {
+namespace {
-ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
- absl::raw_logging_internal::LogPrefixHook>
- log_prefix_hook;
-ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
- absl::raw_logging_internal::AbortHook>
- abort_hook;
+// 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 selected set of platforms for which we expect not to be able to raw log.
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
-static const char kTruncated[] = " ... (message truncated)\n";
+constexpr char kTruncated[] = " ... (message truncated)\n";
// sprintf the format to the buffer, adjusting *buf and *size to reflect the
// consumed bytes, and return whether the message fit without truncation. If
// truncation occurred, if possible leave room in the buffer for the message
// kTruncated[].
-inline static bool VADoRawLog(char** buf, int* size, const char* format,
- va_list ap) ABSL_PRINTF_ATTRIBUTE(3, 0);
-inline static bool VADoRawLog(char** buf, int* size,
- const char* format, va_list ap) {
- int n = vsnprintf(*buf, *size, format, ap);
+bool VADoRawLog(char** buf, int* size, const char* format, va_list ap)
+ ABSL_PRINTF_ATTRIBUTE(3, 0);
+bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {
+ if (*size < 0)
+ return false;
+ int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap);
bool result = true;
if (n < 0 || n > *size) {
result = false;
if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
- n = *size - sizeof(kTruncated); // room for truncation message
+ n = *size - static_cast<int>(sizeof(kTruncated));
} else {
- n = 0; // no room for truncation message
+ n = 0; // no room for truncation message
}
}
*size -= n;
@@ -105,9 +111,7 @@ inline static bool VADoRawLog(char** buf, int* size,
}
#endif // ABSL_LOW_LEVEL_WRITE_SUPPORTED
-static constexpr int kLogBufSize = 3000;
-
-namespace {
+constexpr int kLogBufSize = 3000;
// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
// that invoke malloc() and getenv() that might acquire some locks.
@@ -118,9 +122,11 @@ namespace {
bool DoRawLog(char** buf, int* size, const char* format, ...)
ABSL_PRINTF_ATTRIBUTE(3, 4);
bool DoRawLog(char** buf, int* size, const char* format, ...) {
+ if (*size < 0)
+ return false;
va_list ap;
va_start(ap, format);
- int n = vsnprintf(*buf, *size, format, ap);
+ int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap);
va_end(ap);
if (n < 0 || n > *size) return false;
*size -= n;
@@ -128,6 +134,18 @@ bool DoRawLog(char** buf, int* size, const char* format, ...) {
return true;
}
+bool DefaultLogFilterAndPrefix(absl::LogSeverity, const char* file, int line,
+ char** buf, int* buf_size) {
+ DoRawLog(buf, buf_size, "[%s : %d] RAW: ", file, line);
+ return true;
+}
+
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+absl::base_internal::AtomicHook<LogFilterAndPrefixHook>
+ log_filter_and_prefix_hook(DefaultLogFilterAndPrefix);
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+absl::base_internal::AtomicHook<AbortHook> abort_hook;
+
void RawLogVA(absl::LogSeverity severity, const char* file, int line,
const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(4, 0);
void RawLogVA(absl::LogSeverity severity, const char* file, int line,
@@ -148,14 +166,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
}
#endif
- auto log_prefix_hook_ptr = log_prefix_hook.Load();
- if (log_prefix_hook_ptr) {
- enabled = log_prefix_hook_ptr(severity, file, line, &buf, &size);
- } else {
- if (enabled) {
- DoRawLog(&buf, &size, "[%s : %d] RAW: ", file, line);
- }
- }
+ enabled = log_filter_and_prefix_hook(severity, file, line, &buf, &size);
const char* const prefix_end = buf;
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
@@ -166,11 +177,12 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
} else {
DoRawLog(&buf, &size, "%s", kTruncated);
}
- absl::raw_logging_internal::SafeWriteToStderr(buffer, strlen(buffer));
+ AsyncSignalSafeWriteError(buffer, strlen(buffer));
}
#else
static_cast<void>(format);
static_cast<void>(ap);
+ static_cast<void>(enabled);
#endif
// Abort the process after logging a FATAL message, even if the output itself
@@ -181,18 +193,53 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
}
}
+// Non-formatting version of RawLog().
+//
+// TODO(gfalcon): When string_view no longer depends on base, change this
+// interface to take its message as a string_view instead.
+void DefaultInternalLog(absl::LogSeverity severity, const char* file, int line,
+ const std::string& message) {
+ RawLog(severity, file, line, "%.*s", static_cast<int>(message.size()),
+ message.data());
+}
+
} // namespace
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace raw_logging_internal {
-void SafeWriteToStderr(const char *s, size_t len) {
-#if defined(ABSL_HAVE_SYSCALL_WRITE)
+void AsyncSignalSafeWriteError(const char* s, size_t len) {
+ if (!len) return;
+ absl::base_internal::ErrnoSaver errno_saver;
+#if defined(__EMSCRIPTEN__)
+ // In WebAssembly, bypass filesystem emulation via fwrite.
+ if (s[len - 1] == '\n') {
+ // Skip a trailing newline character as emscripten_errn adds one itself.
+ len--;
+ }
+ // emscripten_errn was introduced in 3.1.41 but broken in standalone mode
+ // until 3.1.43.
+#if ABSL_INTERNAL_EMSCRIPTEN_VERSION >= 3001043
+ emscripten_errn(s, len);
+#else
+ char buf[kLogBufSize];
+ if (len >= kLogBufSize) {
+ len = kLogBufSize - 1;
+ constexpr size_t trunc_len = sizeof(kTruncated) - 2;
+ memcpy(buf + len - trunc_len, kTruncated, trunc_len);
+ buf[len] = '\0';
+ len -= trunc_len;
+ } else {
+ buf[len] = '\0';
+ }
+ memcpy(buf, s, len);
+ _emscripten_err(buf);
+#endif
+#elif defined(ABSL_HAVE_SYSCALL_WRITE)
+ // We prefer calling write via `syscall` to minimize the risk of libc doing
+ // something "helpful".
syscall(SYS_write, STDERR_FILENO, s, len);
#elif defined(ABSL_HAVE_POSIX_WRITE)
write(STDERR_FILENO, s, len);
#elif defined(ABSL_HAVE_RAW_IO)
- _write(/* stderr */ 2, s, len);
+ _write(/* stderr */ 2, s, static_cast<unsigned>(len));
#else
// stderr logging unsupported on this platform
(void) s;
@@ -201,8 +248,6 @@ void SafeWriteToStderr(const char *s, size_t len) {
}
void RawLog(absl::LogSeverity severity, const char* file, int line,
- const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
-void RawLog(absl::LogSeverity severity, const char* file, int line,
const char* format, ...) {
va_list ap;
va_start(ap, format);
@@ -210,15 +255,6 @@ void RawLog(absl::LogSeverity severity, const char* file, int line,
va_end(ap);
}
-// Non-formatting version of RawLog().
-//
-// TODO(gfalcon): When string_view no longer depends on base, change this
-// interface to take its message as a string_view instead.
-static void DefaultInternalLog(absl::LogSeverity severity, const char* file,
- int line, const std::string& message) {
- RawLog(severity, file, line, "%s", message.c_str());
-}
-
bool RawLoggingFullySupported() {
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
return true;
@@ -231,10 +267,16 @@ ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL
absl::base_internal::AtomicHook<InternalLogFunction>
internal_log_function(DefaultInternalLog);
+void RegisterLogFilterAndPrefixHook(LogFilterAndPrefixHook func) {
+ log_filter_and_prefix_hook.Store(func);
+}
+
+void RegisterAbortHook(AbortHook func) { abort_hook.Store(func); }
+
void RegisterInternalLogFunction(InternalLogFunction func) {
internal_log_function.Store(func);
}
-} // namespace raw_logging_internal
+} // namespace raw_log_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/abseil-cpp/absl/base/internal/raw_logging.h b/abseil-cpp/absl/base/internal/raw_logging.h
index 2508f3c..b79550b 100644
--- a/abseil-cpp/absl/base/internal/raw_logging.h
+++ b/abseil-cpp/absl/base/internal/raw_logging.h
@@ -43,12 +43,12 @@
#define ABSL_RAW_LOG(severity, ...) \
do { \
- constexpr const char* absl_raw_logging_internal_basename = \
- ::absl::raw_logging_internal::Basename(__FILE__, \
- sizeof(__FILE__) - 1); \
- ::absl::raw_logging_internal::RawLog(ABSL_RAW_LOGGING_INTERNAL_##severity, \
- absl_raw_logging_internal_basename, \
- __LINE__, __VA_ARGS__); \
+ constexpr const char* absl_raw_log_internal_basename = \
+ ::absl::raw_log_internal::Basename(__FILE__, sizeof(__FILE__) - 1); \
+ ::absl::raw_log_internal::RawLog(ABSL_RAW_LOG_INTERNAL_##severity, \
+ absl_raw_log_internal_basename, __LINE__, \
+ __VA_ARGS__); \
+ ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity; \
} while (0)
// Similar to CHECK(condition) << message, but for low-level modules:
@@ -72,12 +72,13 @@
//
// The API is a subset of the above: each macro only takes two arguments. Use
// StrCat if you need to build a richer message.
-#define ABSL_INTERNAL_LOG(severity, message) \
- do { \
- constexpr const char* absl_raw_logging_internal_filename = __FILE__; \
- ::absl::raw_logging_internal::internal_log_function( \
- ABSL_RAW_LOGGING_INTERNAL_##severity, \
- absl_raw_logging_internal_filename, __LINE__, message); \
+#define ABSL_INTERNAL_LOG(severity, message) \
+ do { \
+ constexpr const char* absl_raw_log_internal_filename = __FILE__; \
+ ::absl::raw_log_internal::internal_log_function( \
+ ABSL_RAW_LOG_INTERNAL_##severity, absl_raw_log_internal_filename, \
+ __LINE__, message); \
+ ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity; \
} while (0)
#define ABSL_INTERNAL_CHECK(condition, message) \
@@ -89,16 +90,36 @@
} \
} while (0)
-#define ABSL_RAW_LOGGING_INTERNAL_INFO ::absl::LogSeverity::kInfo
-#define ABSL_RAW_LOGGING_INTERNAL_WARNING ::absl::LogSeverity::kWarning
-#define ABSL_RAW_LOGGING_INTERNAL_ERROR ::absl::LogSeverity::kError
-#define ABSL_RAW_LOGGING_INTERNAL_FATAL ::absl::LogSeverity::kFatal
-#define ABSL_RAW_LOGGING_INTERNAL_LEVEL(severity) \
+#ifndef NDEBUG
+
+#define ABSL_RAW_DLOG(severity, ...) ABSL_RAW_LOG(severity, __VA_ARGS__)
+#define ABSL_RAW_DCHECK(condition, message) ABSL_RAW_CHECK(condition, message)
+
+#else // NDEBUG
+
+#define ABSL_RAW_DLOG(severity, ...) \
+ while (false) ABSL_RAW_LOG(severity, __VA_ARGS__)
+#define ABSL_RAW_DCHECK(condition, message) \
+ while (false) ABSL_RAW_CHECK(condition, message)
+
+#endif // NDEBUG
+
+#define ABSL_RAW_LOG_INTERNAL_INFO ::absl::LogSeverity::kInfo
+#define ABSL_RAW_LOG_INTERNAL_WARNING ::absl::LogSeverity::kWarning
+#define ABSL_RAW_LOG_INTERNAL_ERROR ::absl::LogSeverity::kError
+#define ABSL_RAW_LOG_INTERNAL_FATAL ::absl::LogSeverity::kFatal
+#define ABSL_RAW_LOG_INTERNAL_LEVEL(severity) \
::absl::NormalizeLogSeverity(severity)
+#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_INFO
+#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_WARNING
+#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_ERROR
+#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_FATAL ABSL_UNREACHABLE()
+#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_LEVEL(severity)
+
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace raw_logging_internal {
+namespace raw_log_internal {
// Helper function to implement ABSL_RAW_LOG
// Logs format... at "severity" level, reporting it
@@ -107,12 +128,9 @@ namespace raw_logging_internal {
void RawLog(absl::LogSeverity severity, const char* file, int line,
const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
-// Writes the provided buffer directly to stderr, in a safe, low-level manner.
-//
-// In POSIX this means calling write(), which is async-signal safe and does
-// not malloc. If the platform supports the SYS_write syscall, we invoke that
-// directly to side-step any libc interception.
-void SafeWriteToStderr(const char *s, size_t len);
+// Writes the provided buffer directly to stderr, in a signal-safe, low-level
+// manner. Preserves errno.
+void AsyncSignalSafeWriteError(const char* s, size_t len);
// compile-time function to get the "base" filename, that is, the part of
// a filename after the last "/" or "\" path separator. The search starts at
@@ -131,7 +149,7 @@ constexpr const char* Basename(const char* fname, int offset) {
// TODO(gfalcon): Come up with a better name for this method.
bool RawLoggingFullySupported();
-// Function type for a raw_logging customization hook for suppressing messages
+// Function type for a raw_log customization hook for suppressing messages
// by severity, and for writing custom prefixes on non-suppressed messages.
//
// The installed hook is called for every raw log invocation. The message will
@@ -140,19 +158,20 @@ bool RawLoggingFullySupported();
// also provided with an output buffer, where it can write a custom log message
// prefix.
//
-// The raw_logging system does not allocate memory or grab locks. User-provided
+// The raw_log system does not allocate memory or grab locks. User-provided
// hooks must avoid these operations, and must not throw exceptions.
//
// 'severity' is the severity level of the message being written.
// 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro
// was located.
-// 'buffer' and 'buf_size' are pointers to the buffer and buffer size. If the
-// hook writes a prefix, it must increment *buffer and decrement *buf_size
+// 'buf' and 'buf_size' are pointers to the buffer and buffer size. If the
+// hook writes a prefix, it must increment *buf and decrement *buf_size
// accordingly.
-using LogPrefixHook = bool (*)(absl::LogSeverity severity, const char* file,
- int line, char** buffer, int* buf_size);
+using LogFilterAndPrefixHook = bool (*)(absl::LogSeverity severity,
+ const char* file, int line, char** buf,
+ int* buf_size);
-// Function type for a raw_logging customization hook called to abort a process
+// Function type for a raw_log customization hook called to abort a process
// when a FATAL message is logged. If the provided AbortHook() returns, the
// logging system will call abort().
//
@@ -160,7 +179,10 @@ using LogPrefixHook = bool (*)(absl::LogSeverity severity, const char* file,
// was located.
// The NUL-terminated logged message lives in the buffer between 'buf_start'
// and 'buf_end'. 'prefix_end' points to the first non-prefix character of the
-// buffer (as written by the LogPrefixHook.)
+// buffer (as written by the LogFilterAndPrefixHook.)
+//
+// The lifetime of the filename and message buffers will not end while the
+// process remains alive.
using AbortHook = void (*)(const char* file, int line, const char* buf_start,
const char* prefix_end, const char* buf_end);
@@ -176,9 +198,17 @@ ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook<
InternalLogFunction>
internal_log_function;
+// Registers hooks of the above types. Only a single hook of each type may be
+// registered. It is an error to call these functions multiple times with
+// different input arguments.
+//
+// These functions are safe to call at any point during initialization; they do
+// not block or malloc, and are async-signal safe.
+void RegisterLogFilterAndPrefixHook(LogFilterAndPrefixHook func);
+void RegisterAbortHook(AbortHook func);
void RegisterInternalLogFunction(InternalLogFunction func);
-} // namespace raw_logging_internal
+} // namespace raw_log_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/abseil-cpp/absl/base/internal/spinlock.cc b/abseil-cpp/absl/base/internal/spinlock.cc
index a7d44f3..381b913 100644
--- a/abseil-cpp/absl/base/internal/spinlock.cc
+++ b/abseil-cpp/absl/base/internal/spinlock.cc
@@ -19,6 +19,7 @@
#include <limits>
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/base/internal/atomic_hook.h"
#include "absl/base/internal/cycleclock.h"
#include "absl/base/internal/spinlock_wait.h"
@@ -66,12 +67,14 @@ void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock,
submit_profile_data.Store(fn);
}
+#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
// Static member variable definitions.
constexpr uint32_t SpinLock::kSpinLockHeld;
constexpr uint32_t SpinLock::kSpinLockCooperative;
constexpr uint32_t SpinLock::kSpinLockDisabledScheduling;
constexpr uint32_t SpinLock::kSpinLockSleeper;
constexpr uint32_t SpinLock::kWaitTimeMask;
+#endif
// Uncommon constructors.
SpinLock::SpinLock(base_internal::SchedulingMode mode)
@@ -125,8 +128,9 @@ void SpinLock::SlowLock() {
// it as having a sleeper.
if ((lock_value & kWaitTimeMask) == 0) {
// Here, just "mark" that the thread is going to sleep. Don't store the
- // lock wait time in the lock as that will cause the current lock
- // owner to think it experienced contention.
+ // lock wait time in the lock -- the lock word stores the amount of time
+ // that the current holder waited before acquiring the lock, not the wait
+ // time of any thread currently waiting to acquire it.
if (lockword_.compare_exchange_strong(
lock_value, lock_value | kSpinLockSleeper,
std::memory_order_relaxed, std::memory_order_relaxed)) {
@@ -140,6 +144,14 @@ void SpinLock::SlowLock() {
// this thread obtains the lock.
lock_value = TryLockInternal(lock_value, wait_cycles);
continue; // Skip the delay at the end of the loop.
+ } else if ((lock_value & kWaitTimeMask) == 0) {
+ // The lock is still held, without a waiter being marked, but something
+ // else about the lock word changed, causing our CAS to fail. For
+ // example, a new lock holder may have acquired the lock with
+ // kSpinLockDisabledScheduling set, whereas the previous holder had not
+ // set that flag. In this case, attempt again to mark ourselves as a
+ // waiter.
+ continue;
}
}
@@ -166,7 +178,7 @@ void SpinLock::SlowUnlock(uint32_t lock_value) {
// reserve a unitary wait time to represent that a waiter exists without our
// own acquisition having been contended.
if ((lock_value & kWaitTimeMask) != kSpinLockSleeper) {
- const uint64_t wait_cycles = DecodeWaitCycles(lock_value);
+ const int64_t wait_cycles = DecodeWaitCycles(lock_value);
ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
submit_profile_data(this, wait_cycles);
ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
@@ -208,9 +220,9 @@ uint32_t SpinLock::EncodeWaitCycles(int64_t wait_start_time,
return clamped;
}
-uint64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
+int64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
// Cast to uint32_t first to ensure bits [63:32] are cleared.
- const uint64_t scaled_wait_time =
+ const int64_t scaled_wait_time =
static_cast<uint32_t>(lock_value & kWaitTimeMask);
return scaled_wait_time << (kProfileTimestampShift - kLockwordReservedShift);
}
diff --git a/abseil-cpp/absl/base/internal/spinlock.h b/abseil-cpp/absl/base/internal/spinlock.h
index e6ac9e6..09ba582 100644
--- a/abseil-cpp/absl/base/internal/spinlock.h
+++ b/abseil-cpp/absl/base/internal/spinlock.h
@@ -15,25 +15,22 @@
//
// Most users requiring mutual exclusion should use Mutex.
-// SpinLock is provided for use in three situations:
-// - for use in code that Mutex itself depends on
-// - to get a faster fast-path release under low contention (without an
-// atomic read-modify-write) In return, SpinLock has worse behaviour under
-// contention, which is why Mutex is preferred in most situations.
+// SpinLock is provided for use in two situations:
+// - for use by Abseil internal code that Mutex itself depends on
// - for async signal safety (see below)
// SpinLock is async signal safe. If a spinlock is used within a signal
// handler, all code that acquires the lock must ensure that the signal cannot
// arrive while they are holding the lock. Typically, this is done by blocking
// the signal.
+//
+// Threads waiting on a SpinLock may be woken in an arbitrary order.
#ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_
#define ABSL_BASE_INTERNAL_SPINLOCK_H_
-#include <stdint.h>
-#include <sys/types.h>
-
#include <atomic>
+#include <cstdint>
#include "absl/base/attributes.h"
#include "absl/base/const_init.h"
@@ -42,8 +39,6 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/internal/tsan_mutex_interface.h"
-#include "absl/base/macros.h"
-#include "absl/base/port.h"
#include "absl/base/thread_annotations.h"
namespace absl {
@@ -121,6 +116,14 @@ class ABSL_LOCKABLE SpinLock {
return (lockword_.load(std::memory_order_relaxed) & kSpinLockHeld) != 0;
}
+ // Return immediately if this thread holds the SpinLock exclusively.
+ // Otherwise, report an error by crashing with a diagnostic.
+ inline void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK() {
+ if (!IsHeld()) {
+ ABSL_RAW_LOG(FATAL, "thread should hold the lock on SpinLock");
+ }
+ }
+
protected:
// These should not be exported except for testing.
@@ -130,7 +133,7 @@ class ABSL_LOCKABLE SpinLock {
int64_t wait_end_time);
// Extract number of wait cycles in a lock value.
- static uint64_t DecodeWaitCycles(uint32_t lock_value);
+ static int64_t DecodeWaitCycles(uint32_t lock_value);
// Provide access to protected method above. Use for testing only.
friend struct SpinLockTest;
@@ -140,8 +143,20 @@ class ABSL_LOCKABLE SpinLock {
//
// bit[0] encodes whether a lock is being held.
// bit[1] encodes whether a lock uses cooperative scheduling.
- // bit[2] encodes whether a lock disables scheduling.
+ // bit[2] encodes whether the current lock holder disabled scheduling when
+ // acquiring the lock. Only set when kSpinLockHeld is also set.
// bit[3:31] encodes time a lock spent on waiting as a 29-bit unsigned int.
+ // This is set by the lock holder to indicate how long it waited on
+ // the lock before eventually acquiring it. The number of cycles is
+ // encoded as a 29-bit unsigned int, or in the case that the current
+ // holder did not wait but another waiter is queued, the LSB
+ // (kSpinLockSleeper) is set. The implementation does not explicitly
+ // track the number of queued waiters beyond this. It must always be
+ // assumed that waiters may exist if the current holder was required to
+ // queue.
+ //
+ // Invariant: if the lock is not held, the value is either 0 or
+ // kSpinLockCooperative.
static constexpr uint32_t kSpinLockHeld = 1;
static constexpr uint32_t kSpinLockCooperative = 2;
static constexpr uint32_t kSpinLockDisabledScheduling = 4;
diff --git a/abseil-cpp/absl/base/internal/spinlock_akaros.inc b/abseil-cpp/absl/base/internal/spinlock_akaros.inc
index bc46894..7b0cada 100644
--- a/abseil-cpp/absl/base/internal/spinlock_akaros.inc
+++ b/abseil-cpp/absl/base/internal/spinlock_akaros.inc
@@ -20,7 +20,7 @@
extern "C" {
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */,
int /* loop */, absl::base_internal::SchedulingMode /* mode */) {
// In Akaros, one must take care not to call anything that could cause a
@@ -29,7 +29,7 @@ ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
// arbitrary code.
}
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}
} // extern "C"
diff --git a/abseil-cpp/absl/base/internal/spinlock_linux.inc b/abseil-cpp/absl/base/internal/spinlock_linux.inc
index e31c6ed..fe8ba67 100644
--- a/abseil-cpp/absl/base/internal/spinlock_linux.inc
+++ b/abseil-cpp/absl/base/internal/spinlock_linux.inc
@@ -56,18 +56,15 @@ static_assert(sizeof(std::atomic<uint32_t>) == sizeof(int),
extern "C" {
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
- std::atomic<uint32_t> *w, uint32_t value, int loop,
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
+ std::atomic<uint32_t> *w, uint32_t value, int,
absl::base_internal::SchedulingMode) {
absl::base_internal::ErrnoSaver errno_saver;
- struct timespec tm;
- tm.tv_sec = 0;
- tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
- syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
+ syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, nullptr);
}
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(std::atomic<uint32_t> *w,
- bool all) {
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
+ std::atomic<uint32_t> *w, bool all) {
syscall(SYS_futex, w, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, all ? INT_MAX : 1, 0);
}
diff --git a/abseil-cpp/absl/base/internal/spinlock_posix.inc b/abseil-cpp/absl/base/internal/spinlock_posix.inc
index fcd21b1..4f6f887 100644
--- a/abseil-cpp/absl/base/internal/spinlock_posix.inc
+++ b/abseil-cpp/absl/base/internal/spinlock_posix.inc
@@ -25,7 +25,7 @@
extern "C" {
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,
absl::base_internal::SchedulingMode /* mode */) {
absl::base_internal::ErrnoSaver errno_saver;
@@ -40,7 +40,7 @@ ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
}
}
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}
} // extern "C"
diff --git a/abseil-cpp/absl/base/internal/spinlock_wait.h b/abseil-cpp/absl/base/internal/spinlock_wait.h
index 169bc74..9a1adcd 100644
--- a/abseil-cpp/absl/base/internal/spinlock_wait.h
+++ b/abseil-cpp/absl/base/internal/spinlock_wait.h
@@ -39,22 +39,22 @@ struct SpinLockWaitTransition {
// satisfying 0<=i<n && trans[i].done, atomically make the transition,
// then return the old value of *w. Make any other atomic transitions
// where !trans[i].done, but continue waiting.
+//
+// Wakeups for threads blocked on SpinLockWait do not respect priorities.
uint32_t SpinLockWait(std::atomic<uint32_t> *w, int n,
const SpinLockWaitTransition trans[],
SchedulingMode scheduling_mode);
-// If possible, wake some thread that has called SpinLockDelay(w, ...). If
-// "all" is true, wake all such threads. This call is a hint, and on some
-// systems it may be a no-op; threads calling SpinLockDelay() will always wake
-// eventually even if SpinLockWake() is never called.
+// If possible, wake some thread that has called SpinLockDelay(w, ...). If `all`
+// is true, wake all such threads. On some systems, this may be a no-op; on
+// those systems, threads calling SpinLockDelay() will always wake eventually
+// even if SpinLockWake() is never called.
void SpinLockWake(std::atomic<uint32_t> *w, bool all);
// Wait for an appropriate spin delay on iteration "loop" of a
// spin loop on location *w, whose previously observed value was "value".
// SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick,
-// or may wait for a delay that can be truncated by a call to SpinLockWake(w).
-// In all cases, it must return in bounded time even if SpinLockWake() is not
-// called.
+// or may wait for a call to SpinLockWake(w).
void SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop,
base_internal::SchedulingMode scheduling_mode);
@@ -73,21 +73,23 @@ ABSL_NAMESPACE_END
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
-void AbslInternalSpinLockWake(std::atomic<uint32_t> *w, bool all);
-void AbslInternalSpinLockDelay(
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(std::atomic<uint32_t> *w,
+ bool all);
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode scheduling_mode);
}
inline void absl::base_internal::SpinLockWake(std::atomic<uint32_t> *w,
bool all) {
- AbslInternalSpinLockWake(w, all);
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(w, all);
}
inline void absl::base_internal::SpinLockDelay(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode scheduling_mode) {
- AbslInternalSpinLockDelay(w, value, loop, scheduling_mode);
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)
+ (w, value, loop, scheduling_mode);
}
#endif // ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_
diff --git a/abseil-cpp/absl/base/internal/spinlock_win32.inc b/abseil-cpp/absl/base/internal/spinlock_win32.inc
index 78654b5..934c201 100644
--- a/abseil-cpp/absl/base/internal/spinlock_win32.inc
+++ b/abseil-cpp/absl/base/internal/spinlock_win32.inc
@@ -20,18 +20,21 @@
extern "C" {
-void AbslInternalSpinLockDelay(std::atomic<uint32_t>* /* lock_word */,
- uint32_t /* value */, int loop,
- absl::base_internal::SchedulingMode /* mode */) {
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
+ std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,
+ absl::base_internal::SchedulingMode /* mode */) {
if (loop == 0) {
} else if (loop == 1) {
Sleep(0);
} else {
- Sleep(absl::base_internal::SpinLockSuggestedDelayNS(loop) / 1000000);
+ // SpinLockSuggestedDelayNS() always returns a positive integer, so this
+ // static_cast is safe.
+ Sleep(static_cast<DWORD>(
+ absl::base_internal::SpinLockSuggestedDelayNS(loop) / 1000000));
}
}
-void AbslInternalSpinLockWake(std::atomic<uint32_t>* /* lock_word */,
- bool /* all */) {}
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
+ std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}
} // extern "C"
diff --git a/abseil-cpp/absl/base/internal/strerror.cc b/abseil-cpp/absl/base/internal/strerror.cc
index d66ba12..de91c05 100644
--- a/abseil-cpp/absl/base/internal/strerror.cc
+++ b/abseil-cpp/absl/base/internal/strerror.cc
@@ -51,7 +51,6 @@ const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
}
std::string StrErrorInternal(int errnum) {
- absl::base_internal::ErrnoSaver errno_saver;
char buf[100];
const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
if (*str == '\0') {
@@ -67,8 +66,8 @@ constexpr int kSysNerr = 135;
std::array<std::string, kSysNerr>* NewStrErrorTable() {
auto* table = new std::array<std::string, kSysNerr>;
- for (int i = 0; i < static_cast<int>(table->size()); ++i) {
- (*table)[i] = StrErrorInternal(i);
+ for (size_t i = 0; i < table->size(); ++i) {
+ (*table)[i] = StrErrorInternal(static_cast<int>(i));
}
return table;
}
@@ -76,9 +75,10 @@ std::array<std::string, kSysNerr>* NewStrErrorTable() {
} // namespace
std::string StrError(int errnum) {
+ absl::base_internal::ErrnoSaver errno_saver;
static const auto* table = NewStrErrorTable();
- if (errnum >= 0 && errnum < static_cast<int>(table->size())) {
- return (*table)[errnum];
+ if (errnum >= 0 && static_cast<size_t>(errnum) < table->size()) {
+ return (*table)[static_cast<size_t>(errnum)];
}
return StrErrorInternal(errnum);
}
diff --git a/abseil-cpp/absl/base/internal/strerror_test.cc b/abseil-cpp/absl/base/internal/strerror_test.cc
index a53da97..e32d5b5 100644
--- a/abseil-cpp/absl/base/internal/strerror_test.cc
+++ b/abseil-cpp/absl/base/internal/strerror_test.cc
@@ -62,12 +62,14 @@ TEST(StrErrorTest, MultipleThreads) {
++counter;
errno = ERANGE;
const std::string value = absl::base_internal::StrError(i);
+ // EXPECT_* could change errno. Stash it first.
+ int check_err = errno;
+ EXPECT_THAT(check_err, Eq(ERANGE));
// Only the GNU implementation is guaranteed to provide the
// string "Unknown error nnn". POSIX doesn't say anything.
if (!absl::StartsWith(value, "Unknown error ")) {
- EXPECT_THAT(absl::base_internal::StrError(i), Eq(expected_strings[i]));
+ EXPECT_THAT(value, Eq(expected_strings[i]));
}
- EXPECT_THAT(errno, Eq(ERANGE));
}
};
diff --git a/abseil-cpp/absl/base/internal/sysinfo.cc b/abseil-cpp/absl/base/internal/sysinfo.cc
index 349d926..8bcc4fa 100644
--- a/abseil-cpp/absl/base/internal/sysinfo.cc
+++ b/abseil-cpp/absl/base/internal/sysinfo.cc
@@ -41,6 +41,7 @@
#include <string.h>
#include <cassert>
+#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
@@ -61,14 +62,82 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
+namespace {
+
+#if defined(_WIN32)
+
+// Returns number of bits set in `bitMask`
+DWORD Win32CountSetBits(ULONG_PTR bitMask) {
+ for (DWORD bitSetCount = 0; ; ++bitSetCount) {
+ if (bitMask == 0) return bitSetCount;
+ bitMask &= bitMask - 1;
+ }
+}
+
+// Returns the number of logical CPUs using GetLogicalProcessorInformation(), or
+// 0 if the number of processors is not available or can not be computed.
+// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformation
+int Win32NumCPUs() {
+#pragma comment(lib, "kernel32.lib")
+ using Info = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
+
+ DWORD info_size = sizeof(Info);
+ Info* info(static_cast<Info*>(malloc(info_size)));
+ if (info == nullptr) return 0;
+
+ bool success = GetLogicalProcessorInformation(info, &info_size);
+ if (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ free(info);
+ info = static_cast<Info*>(malloc(info_size));
+ if (info == nullptr) return 0;
+ success = GetLogicalProcessorInformation(info, &info_size);
+ }
+
+ DWORD logicalProcessorCount = 0;
+ if (success) {
+ Info* ptr = info;
+ DWORD byteOffset = 0;
+ while (byteOffset + sizeof(Info) <= info_size) {
+ switch (ptr->Relationship) {
+ case RelationProcessorCore:
+ logicalProcessorCount += Win32CountSetBits(ptr->ProcessorMask);
+ break;
+
+ case RelationNumaNode:
+ case RelationCache:
+ case RelationProcessorPackage:
+ // Ignore other entries
+ break;
+
+ default:
+ // Ignore unknown entries
+ break;
+ }
+ byteOffset += sizeof(Info);
+ ptr++;
+ }
+ }
+ free(info);
+ return static_cast<int>(logicalProcessorCount);
+}
+
+#endif
+
+} // namespace
+
static int GetNumCPUs() {
#if defined(__myriad2__)
return 1;
+#elif defined(_WIN32)
+ const int hardware_concurrency = Win32NumCPUs();
+ return hardware_concurrency ? hardware_concurrency : 1;
+#elif defined(_AIX)
+ return sysconf(_SC_NPROCESSORS_ONLN);
#else
// Other possibilities:
// - Read /sys/devices/system/cpu/online and use cpumask_parse()
// - sysconf(_SC_NPROCESSORS_ONLN)
- return std::thread::hardware_concurrency();
+ return static_cast<int>(std::thread::hardware_concurrency());
#endif
}
@@ -91,7 +160,7 @@ static double GetNominalCPUFrequency() {
DWORD type = 0;
DWORD data = 0;
DWORD data_size = sizeof(data);
- auto result = RegQueryValueExA(key, "~MHz", 0, &type,
+ auto result = RegQueryValueExA(key, "~MHz", nullptr, &type,
reinterpret_cast<LPBYTE>(&data), &data_size);
RegCloseKey(key);
if (result == ERROR_SUCCESS && type == REG_DWORD &&
@@ -121,12 +190,21 @@ static double GetNominalCPUFrequency() {
// and the memory location pointed to by value is set to the value read.
static bool ReadLongFromFile(const char *file, long *value) {
bool ret = false;
- int fd = open(file, O_RDONLY);
+#if defined(_POSIX_C_SOURCE)
+ const int file_mode = (O_RDONLY | O_CLOEXEC);
+#else
+ const int file_mode = O_RDONLY;
+#endif
+
+ int fd = open(file, file_mode);
if (fd != -1) {
char line[1024];
char *err;
memset(line, '\0', sizeof(line));
- int len = read(fd, line, sizeof(line) - 1);
+ ssize_t len;
+ do {
+ len = read(fd, line, sizeof(line) - 1);
+ } while (len < 0 && errno == EINTR);
if (len <= 0) {
ret = false;
} else {
@@ -154,8 +232,8 @@ static int64_t ReadMonotonicClockNanos() {
int rc = clock_gettime(CLOCK_MONOTONIC, &t);
#endif
if (rc != 0) {
- perror("clock_gettime() failed");
- abort();
+ ABSL_INTERNAL_LOG(
+ FATAL, "clock_gettime() failed: (" + std::to_string(errno) + ")");
}
return int64_t{t.tv_sec} * 1000000000 + t.tv_nsec;
}
@@ -308,7 +386,7 @@ pid_t GetTID() {
#endif
pid_t GetTID() {
- return syscall(SYS_gettid);
+ return static_cast<pid_t>(syscall(SYS_gettid));
}
#elif defined(__akaros__)
@@ -343,81 +421,33 @@ pid_t GetTID() {
return tid;
}
-#else
+#elif defined(__APPLE__)
-// Fallback implementation of GetTID using pthread_getspecific.
-ABSL_CONST_INIT static once_flag tid_once;
-ABSL_CONST_INIT static pthread_key_t tid_key;
-ABSL_CONST_INIT static absl::base_internal::SpinLock tid_lock(
- absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
-
-// We set a bit per thread in this array to indicate that an ID is in
-// use. ID 0 is unused because it is the default value returned by
-// pthread_getspecific().
-ABSL_CONST_INIT static std::vector<uint32_t> *tid_array
- ABSL_GUARDED_BY(tid_lock) = nullptr;
-static constexpr int kBitsPerWord = 32; // tid_array is uint32_t.
-
-// Returns the TID to tid_array.
-static void FreeTID(void *v) {
- intptr_t tid = reinterpret_cast<intptr_t>(v);
- int word = tid / kBitsPerWord;
- uint32_t mask = ~(1u << (tid % kBitsPerWord));
- absl::base_internal::SpinLockHolder lock(&tid_lock);
- assert(0 <= word && static_cast<size_t>(word) < tid_array->size());
- (*tid_array)[word] &= mask;
+pid_t GetTID() {
+ uint64_t tid;
+ // `nullptr` here implies this thread. This only fails if the specified
+ // thread is invalid or the pointer-to-tid is null, so we needn't worry about
+ // it.
+ pthread_threadid_np(nullptr, &tid);
+ return static_cast<pid_t>(tid);
}
-static void InitGetTID() {
- if (pthread_key_create(&tid_key, FreeTID) != 0) {
- // The logging system calls GetTID() so it can't be used here.
- perror("pthread_key_create failed");
- abort();
- }
+#elif defined(__native_client__)
- // Initialize tid_array.
- absl::base_internal::SpinLockHolder lock(&tid_lock);
- tid_array = new std::vector<uint32_t>(1);
- (*tid_array)[0] = 1; // ID 0 is never-allocated.
-}
-
-// Return a per-thread small integer ID from pthread's thread-specific data.
pid_t GetTID() {
- absl::call_once(tid_once, InitGetTID);
-
- intptr_t tid = reinterpret_cast<intptr_t>(pthread_getspecific(tid_key));
- if (tid != 0) {
- return tid;
- }
-
- int bit; // tid_array[word] = 1u << bit;
- size_t word;
- {
- // Search for the first unused ID.
- absl::base_internal::SpinLockHolder lock(&tid_lock);
- // First search for a word in the array that is not all ones.
- word = 0;
- while (word < tid_array->size() && ~(*tid_array)[word] == 0) {
- ++word;
- }
- if (word == tid_array->size()) {
- tid_array->push_back(0); // No space left, add kBitsPerWord more IDs.
- }
- // Search for a zero bit in the word.
- bit = 0;
- while (bit < kBitsPerWord && (((*tid_array)[word] >> bit) & 1) != 0) {
- ++bit;
- }
- tid = (word * kBitsPerWord) + bit;
- (*tid_array)[word] |= 1u << bit; // Mark the TID as allocated.
- }
+ auto* thread = pthread_self();
+ static_assert(sizeof(pid_t) == sizeof(thread),
+ "In NaCL int expected to be the same size as a pointer");
+ return reinterpret_cast<pid_t>(thread);
+}
- if (pthread_setspecific(tid_key, reinterpret_cast<void *>(tid)) != 0) {
- perror("pthread_setspecific failed");
- abort();
- }
+#else
- return static_cast<pid_t>(tid);
+// Fallback implementation of `GetTID` using `pthread_self`.
+pid_t GetTID() {
+ // `pthread_t` need not be arithmetic per POSIX; platforms where it isn't
+ // should be handled above.
+ return static_cast<pid_t>(pthread_self());
}
#endif
@@ -426,7 +456,7 @@ pid_t GetTID() {
// userspace construct) to avoid unnecessary system calls. Without this caching,
// it can take roughly 98ns, while it takes roughly 1ns with this caching.
pid_t GetCachedTID() {
-#if ABSL_HAVE_THREAD_LOCAL
+#ifdef ABSL_HAVE_THREAD_LOCAL
static thread_local pid_t thread_id = GetTID();
return thread_id;
#else
diff --git a/abseil-cpp/absl/base/internal/sysinfo_test.cc b/abseil-cpp/absl/base/internal/sysinfo_test.cc
index fa8b88b..f305b6c 100644
--- a/abseil-cpp/absl/base/internal/sysinfo_test.cc
+++ b/abseil-cpp/absl/base/internal/sysinfo_test.cc
@@ -37,18 +37,6 @@ TEST(SysinfoTest, NumCPUs) {
<< "NumCPUs() should not have the default value of 0";
}
-TEST(SysinfoTest, NominalCPUFrequency) {
-#if !(defined(__aarch64__) && defined(__linux__)) && !defined(__EMSCRIPTEN__)
- EXPECT_GE(NominalCPUFrequency(), 1000.0)
- << "NominalCPUFrequency() did not return a reasonable value";
-#else
- // Aarch64 cannot read the CPU frequency from sysfs, so we get back 1.0.
- // Emscripten does not have a sysfs to read from at all.
- EXPECT_EQ(NominalCPUFrequency(), 1.0)
- << "CPU frequency detection was fixed! Please update unittest.";
-#endif
-}
-
TEST(SysinfoTest, GetTID) {
EXPECT_EQ(GetTID(), GetTID()); // Basic compile and equality test.
#ifdef __native_client__
diff --git a/abseil-cpp/absl/base/internal/thread_annotations.h b/abseil-cpp/absl/base/internal/thread_annotations.h
index 4dab6a9..8c5c67e 100644
--- a/abseil-cpp/absl/base/internal/thread_annotations.h
+++ b/abseil-cpp/absl/base/internal/thread_annotations.h
@@ -38,6 +38,13 @@
#ifndef ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
#define ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
+// ABSL_LEGACY_THREAD_ANNOTATIONS is a *temporary* compatibility macro that can
+// be defined on the compile command-line to restore the legacy spellings of the
+// thread annotations macros/functions. The macros in this file are available
+// under ABSL_ prefixed spellings in absl/base/thread_annotations.h. This macro
+// and the legacy spellings will be removed in the future.
+#ifdef ABSL_LEGACY_THREAD_ANNOTATIONS
+
#if defined(__clang__)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
@@ -268,4 +275,6 @@ inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
} // namespace thread_safety_analysis
+#endif // defined(ABSL_LEGACY_THREAD_ANNOTATIONS)
+
#endif // ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
diff --git a/abseil-cpp/absl/base/internal/thread_identity.cc b/abseil-cpp/absl/base/internal/thread_identity.cc
index d63a04a..252443e 100644
--- a/abseil-cpp/absl/base/internal/thread_identity.cc
+++ b/abseil-cpp/absl/base/internal/thread_identity.cc
@@ -14,7 +14,7 @@
#include "absl/base/internal/thread_identity.h"
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__MINGW32__)
#include <pthread.h>
#include <signal.h>
#endif
@@ -23,6 +23,7 @@
#include <cassert>
#include <memory>
+#include "absl/base/attributes.h"
#include "absl/base/call_once.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/spinlock.h"
@@ -53,19 +54,23 @@ void AllocateThreadIdentityKey(ThreadIdentityReclaimerFunction reclaimer) {
// exist within a process (via dlopen() or similar), references to
// thread_identity_ptr from each instance of the code will refer to
// *different* instances of this ptr.
-#ifdef __GNUC__
-__attribute__((visibility("protected")))
-#endif // __GNUC__
+// Apple platforms have the visibility attribute, but issue a compile warning
+// that protected visibility is unsupported.
+ABSL_CONST_INIT // Must come before __attribute__((visibility("protected")))
+#if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
+ __attribute__((visibility("protected")))
+#endif // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
#if ABSL_PER_THREAD_TLS
-// Prefer __thread to thread_local as benchmarks indicate it is a bit faster.
-ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr;
+ // Prefer __thread to thread_local as benchmarks indicate it is a bit
+ // faster.
+ ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr;
#elif defined(ABSL_HAVE_THREAD_LOCAL)
-thread_local ThreadIdentity* thread_identity_ptr = nullptr;
+ thread_local ThreadIdentity* thread_identity_ptr = nullptr;
#endif // ABSL_PER_THREAD_TLS
#endif // TLS or CPP11
-void SetCurrentThreadIdentity(
- ThreadIdentity* identity, ThreadIdentityReclaimerFunction reclaimer) {
+void SetCurrentThreadIdentity(ThreadIdentity* identity,
+ ThreadIdentityReclaimerFunction reclaimer) {
assert(CurrentThreadIdentityIfPresent() == nullptr);
// Associate our destructor.
// NOTE: This call to pthread_setspecific is currently the only immovable
@@ -75,7 +80,7 @@ void SetCurrentThreadIdentity(
absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,
reclaimer);
-#if defined(__EMSCRIPTEN__) || defined(__MINGW32__)
+#if defined(__EMSCRIPTEN__) || defined(__MINGW32__) || defined(__hexagon__)
// Emscripten and MinGW pthread implementations does not support signals.
// See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html
// for more information.
@@ -117,10 +122,10 @@ void SetCurrentThreadIdentity(
ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
// Please see the comment on `CurrentThreadIdentityIfPresent` in
-// thread_identity.h. Because DLLs cannot expose thread_local variables in
-// headers, we opt for the correct-but-slower option of placing the definition
-// of this function only in a translation unit inside DLL.
-#if defined(ABSL_BUILD_DLL) || defined(ABSL_CONSUME_DLL)
+// thread_identity.h. When we cannot expose thread_local variables in
+// headers, we opt for the correct-but-slower option of not inlining this
+// function.
+#ifndef ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT
ThreadIdentity* CurrentThreadIdentityIfPresent() { return thread_identity_ptr; }
#endif
#endif
@@ -130,7 +135,7 @@ void ClearCurrentThreadIdentity() {
ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
thread_identity_ptr = nullptr;
#elif ABSL_THREAD_IDENTITY_MODE == \
- ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
+ ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
// pthread_setspecific expected to clear value on destruction
assert(CurrentThreadIdentityIfPresent() == nullptr);
#endif
diff --git a/abseil-cpp/absl/base/internal/thread_identity.h b/abseil-cpp/absl/base/internal/thread_identity.h
index ceb109b..b6e917c 100644
--- a/abseil-cpp/absl/base/internal/thread_identity.h
+++ b/abseil-cpp/absl/base/internal/thread_identity.h
@@ -32,6 +32,7 @@
#include "absl/base/config.h"
#include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/optimization.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -61,38 +62,36 @@ struct PerThreadSynch {
return reinterpret_cast<ThreadIdentity*>(this);
}
- PerThreadSynch *next; // Circular waiter queue; initialized to 0.
- PerThreadSynch *skip; // If non-zero, all entries in Mutex queue
+ PerThreadSynch* next; // Circular waiter queue; initialized to 0.
+ PerThreadSynch* skip; // If non-zero, all entries in Mutex queue
// up to and including "skip" have same
// condition as this, and will be woken later
bool may_skip; // if false while on mutex queue, a mutex unlocker
// is using this PerThreadSynch as a terminator. Its
// skip field must not be filled in because the loop
// might then skip over the terminator.
-
- // The wait parameters of the current wait. waitp is null if the
- // thread is not waiting. Transitions from null to non-null must
- // occur before the enqueue commit point (state = kQueued in
- // Enqueue() and CondVarEnqueue()). Transitions from non-null to
- // null must occur after the wait is finished (state = kAvailable in
- // Mutex::Block() and CondVar::WaitCommon()). This field may be
- // changed only by the thread that describes this PerThreadSynch. A
- // special case is Fer(), which calls Enqueue() on another thread,
- // but with an identical SynchWaitParams pointer, thus leaving the
- // pointer unchanged.
- SynchWaitParams *waitp;
-
- bool suppress_fatal_errors; // If true, try to proceed even in the face of
- // broken invariants. This is used within fatal
- // signal handlers to improve the chances of
- // debug logging information being output
- // successfully.
-
- intptr_t readers; // Number of readers in mutex.
- int priority; // Priority of thread (updated every so often).
-
- // When priority will next be read (cycles).
- int64_t next_priority_read_cycles;
+ bool wake; // This thread is to be woken from a Mutex.
+ // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
+ // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
+ //
+ // The value of "x->cond_waiter" is meaningless if "x" is not on a
+ // Mutex waiter list.
+ bool cond_waiter;
+ bool maybe_unlocking; // Valid at head of Mutex waiter queue;
+ // true if UnlockSlow could be searching
+ // for a waiter to wake. Used for an optimization
+ // in Enqueue(). true is always a valid value.
+ // Can be reset to false when the unlocker or any
+ // writer releases the lock, or a reader fully
+ // releases the lock. It may not be set to false
+ // by a reader that decrements the count to
+ // non-zero. protected by mutex spinlock
+ bool suppress_fatal_errors; // If true, try to proceed even in the face
+ // of broken invariants. This is used within
+ // fatal signal handlers to improve the
+ // chances of debug logging information being
+ // output successfully.
+ int priority; // Priority of thread (updated every so often).
// State values:
// kAvailable: This PerThreadSynch is available.
@@ -105,36 +104,37 @@ struct PerThreadSynch {
//
// Transitions from kAvailable to kQueued require no barrier, they
// are externally ordered by the Mutex.
- enum State {
- kAvailable,
- kQueued
- };
+ enum State { kAvailable, kQueued };
std::atomic<State> state;
- bool maybe_unlocking; // Valid at head of Mutex waiter queue;
- // true if UnlockSlow could be searching
- // for a waiter to wake. Used for an optimization
- // in Enqueue(). true is always a valid value.
- // Can be reset to false when the unlocker or any
- // writer releases the lock, or a reader fully releases
- // the lock. It may not be set to false by a reader
- // that decrements the count to non-zero.
- // protected by mutex spinlock
+ // The wait parameters of the current wait. waitp is null if the
+ // thread is not waiting. Transitions from null to non-null must
+ // occur before the enqueue commit point (state = kQueued in
+ // Enqueue() and CondVarEnqueue()). Transitions from non-null to
+ // null must occur after the wait is finished (state = kAvailable in
+ // Mutex::Block() and CondVar::WaitCommon()). This field may be
+ // changed only by the thread that describes this PerThreadSynch. A
+ // special case is Fer(), which calls Enqueue() on another thread,
+ // but with an identical SynchWaitParams pointer, thus leaving the
+ // pointer unchanged.
+ SynchWaitParams* waitp;
- bool wake; // This thread is to be woken from a Mutex.
+ intptr_t readers; // Number of readers in mutex.
- // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
- // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
- //
- // The value of "x->cond_waiter" is meaningless if "x" is not on a
- // Mutex waiter list.
- bool cond_waiter;
+ // When priority will next be read (cycles).
+ int64_t next_priority_read_cycles;
// Locks held; used during deadlock detection.
// Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
- SynchLocksHeld *all_locks;
+ SynchLocksHeld* all_locks;
};
+// The instances of this class are allocated in NewThreadIdentity() with an
+// alignment of PerThreadSynch::kAlignment.
+//
+// NOTE: The layout of fields in this structure is critical, please do not
+// add, remove, or modify the field placements without fully auditing the
+// layout.
struct ThreadIdentity {
// Must be the first member. The Mutex implementation requires that
// the PerThreadSynch object associated with each thread is
@@ -144,7 +144,7 @@ struct ThreadIdentity {
// Private: Reserved for absl::synchronization_internal::Waiter.
struct WaiterState {
- char data[128];
+ alignas(void*) char data[256];
} waiter_state;
// Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().
@@ -167,7 +167,10 @@ struct ThreadIdentity {
//
// Does not malloc(*), and is async-signal safe.
// [*] Technically pthread_setspecific() does malloc on first use; however this
-// is handled internally within tcmalloc's initialization already.
+// is handled internally within tcmalloc's initialization already. Note that
+// darwin does *not* use tcmalloc, so this can catch you if using MallocHooks
+// on Apple platforms. Whatever function is calling your MallocHooks will need
+// to watch for recursion on Apple platforms.
//
// New ThreadIdentity objects can be constructed and associated with a thread
// by calling GetOrCreateCurrentThreadIdentity() in per-thread-sem.h.
@@ -189,29 +192,31 @@ void ClearCurrentThreadIdentity();
// May be chosen at compile time via: -DABSL_FORCE_THREAD_IDENTITY_MODE=<mode
// index>
#ifdef ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
-#error ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC cannot be direcly set
+#error ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC cannot be directly set
#else
#define ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC 0
#endif
#ifdef ABSL_THREAD_IDENTITY_MODE_USE_TLS
-#error ABSL_THREAD_IDENTITY_MODE_USE_TLS cannot be direcly set
+#error ABSL_THREAD_IDENTITY_MODE_USE_TLS cannot be directly set
#else
#define ABSL_THREAD_IDENTITY_MODE_USE_TLS 1
#endif
#ifdef ABSL_THREAD_IDENTITY_MODE_USE_CPP11
-#error ABSL_THREAD_IDENTITY_MODE_USE_CPP11 cannot be direcly set
+#error ABSL_THREAD_IDENTITY_MODE_USE_CPP11 cannot be directly set
#else
#define ABSL_THREAD_IDENTITY_MODE_USE_CPP11 2
#endif
#ifdef ABSL_THREAD_IDENTITY_MODE
-#error ABSL_THREAD_IDENTITY_MODE cannot be direcly set
+#error ABSL_THREAD_IDENTITY_MODE cannot be directly set
#elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE)
#define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
#elif defined(_WIN32) && !defined(__MINGW32__)
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
+#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
+#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
(__GOOGLE_GRTE_VERSION__ >= 20140228L)
// Support for async-safe TLS was specifically added in GRTEv4. It's not
@@ -235,13 +240,18 @@ ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
#error Thread-local storage not detected on this platform
#endif
-// thread_local variables cannot be in headers exposed by DLLs. However, it is
-// important for performance reasons in general that
-// `CurrentThreadIdentityIfPresent` be inlined. This is not possible across a
-// DLL boundary so, with DLLs, we opt to have the function not be inlined. Note
+// thread_local variables cannot be in headers exposed by DLLs or in certain
+// build configurations on Apple platforms. However, it is important for
+// performance reasons in general that `CurrentThreadIdentityIfPresent` be
+// inlined. In the other cases we opt to have the function not be inlined. Note
// that `CurrentThreadIdentityIfPresent` is declared above so we can exclude
-// this entire inline definition when compiling as a DLL.
-#if !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL)
+// this entire inline definition.
+#if !defined(__APPLE__) && !defined(ABSL_BUILD_DLL) && \
+ !defined(ABSL_CONSUME_DLL)
+#define ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT 1
+#endif
+
+#ifdef ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT
inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
return thread_identity_ptr;
}
diff --git a/abseil-cpp/absl/base/internal/thread_identity_test.cc b/abseil-cpp/absl/base/internal/thread_identity_test.cc
index 46a6f74..5f17553 100644
--- a/abseil-cpp/absl/base/internal/thread_identity_test.cc
+++ b/abseil-cpp/absl/base/internal/thread_identity_test.cc
@@ -95,7 +95,7 @@ TEST(ThreadIdentityTest, BasicIdentityWorksThreaded) {
}
TEST(ThreadIdentityTest, ReusedThreadIdentityMutexTest) {
- // This test repeatly creates and joins a series of threads, each of
+ // This test repeatedly creates and joins a series of threads, each of
// which acquires and releases shared Mutex locks. This verifies
// Mutex operations work correctly under a reused
// ThreadIdentity. Note that the most likely failure mode of this
diff --git a/abseil-cpp/absl/base/internal/throw_delegate.cc b/abseil-cpp/absl/base/internal/throw_delegate.cc
index c055f75..337e870 100644
--- a/abseil-cpp/absl/base/internal/throw_delegate.cc
+++ b/abseil-cpp/absl/base/internal/throw_delegate.cc
@@ -18,6 +18,7 @@
#include <functional>
#include <new>
#include <stdexcept>
+
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
@@ -25,83 +26,177 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
-namespace {
-template <typename T>
-[[noreturn]] void Throw(const T& error) {
+// NOTE: The exception types, like `std::logic_error`, do not exist on all
+// platforms. (For example, the Android NDK does not have them.)
+// Therefore, their use must be guarded by `#ifdef` or equivalent.
+
+void ThrowStdLogicError(const std::string& what_arg) {
#ifdef ABSL_HAVE_EXCEPTIONS
- throw error;
+ throw std::logic_error(what_arg);
#else
- ABSL_RAW_LOG(FATAL, "%s", error.what());
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
std::abort();
#endif
}
-} // namespace
-
-void ThrowStdLogicError(const std::string& what_arg) {
- Throw(std::logic_error(what_arg));
-}
void ThrowStdLogicError(const char* what_arg) {
- Throw(std::logic_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::logic_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdInvalidArgument(const std::string& what_arg) {
- Throw(std::invalid_argument(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::invalid_argument(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdInvalidArgument(const char* what_arg) {
- Throw(std::invalid_argument(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::invalid_argument(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdDomainError(const std::string& what_arg) {
- Throw(std::domain_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::domain_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdDomainError(const char* what_arg) {
- Throw(std::domain_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::domain_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdLengthError(const std::string& what_arg) {
- Throw(std::length_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::length_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdLengthError(const char* what_arg) {
- Throw(std::length_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::length_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdOutOfRange(const std::string& what_arg) {
- Throw(std::out_of_range(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::out_of_range(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdOutOfRange(const char* what_arg) {
- Throw(std::out_of_range(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::out_of_range(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdRuntimeError(const std::string& what_arg) {
- Throw(std::runtime_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::runtime_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdRuntimeError(const char* what_arg) {
- Throw(std::runtime_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::runtime_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdRangeError(const std::string& what_arg) {
- Throw(std::range_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::range_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdRangeError(const char* what_arg) {
- Throw(std::range_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::range_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdOverflowError(const std::string& what_arg) {
- Throw(std::overflow_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::overflow_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdOverflowError(const char* what_arg) {
- Throw(std::overflow_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::overflow_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdUnderflowError(const std::string& what_arg) {
- Throw(std::underflow_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::underflow_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdUnderflowError(const char* what_arg) {
- Throw(std::underflow_error(what_arg));
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::underflow_error(what_arg);
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
-void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
+void ThrowStdBadFunctionCall() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::bad_function_call();
+#else
+ std::abort();
+#endif
+}
-void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
+void ThrowStdBadAlloc() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw std::bad_alloc();
+#else
+ std::abort();
+#endif
+}
} // namespace base_internal
ABSL_NAMESPACE_END
diff --git a/abseil-cpp/absl/base/internal/unaligned_access.h b/abseil-cpp/absl/base/internal/unaligned_access.h
index dd5250d..093dd9b 100644
--- a/abseil-cpp/absl/base/internal/unaligned_access.h
+++ b/abseil-cpp/absl/base/internal/unaligned_access.h
@@ -31,80 +31,6 @@
// The unaligned API is C++ only. The declarations use C++ features
// (namespaces, inline) which are absent or incompatible in C.
#if defined(__cplusplus)
-
-#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
- defined(ABSL_HAVE_THREAD_SANITIZER) || defined(ABSL_HAVE_MEMORY_SANITIZER)
-// Consider we have an unaligned load/store of 4 bytes from address 0x...05.
-// AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
-// will miss a bug if 08 is the first unaddressable byte.
-// ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
-// miss a race between this access and some other accesses to 08.
-// MemorySanitizer will correctly propagate the shadow on unaligned stores
-// and correctly report bugs on unaligned loads, but it may not properly
-// update and report the origin of the uninitialized memory.
-// For all three tools, replacing an unaligned access with a tool-specific
-// callback solves the problem.
-
-// Make sure uint16_t/uint32_t/uint64_t are defined.
-#include <stdint.h>
-
-extern "C" {
-uint16_t __sanitizer_unaligned_load16(const void *p);
-uint32_t __sanitizer_unaligned_load32(const void *p);
-uint64_t __sanitizer_unaligned_load64(const void *p);
-void __sanitizer_unaligned_store16(void *p, uint16_t v);
-void __sanitizer_unaligned_store32(void *p, uint32_t v);
-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) {
- return __sanitizer_unaligned_load16(p);
-}
-
-inline uint32_t UnalignedLoad32(const void *p) {
- return __sanitizer_unaligned_load32(p);
-}
-
-inline uint64_t UnalignedLoad64(const void *p) {
- return __sanitizer_unaligned_load64(p);
-}
-
-inline void UnalignedStore16(void *p, uint16_t v) {
- __sanitizer_unaligned_store16(p, v);
-}
-
-inline void UnalignedStore32(void *p, uint32_t v) {
- __sanitizer_unaligned_store32(p, v);
-}
-
-inline void UnalignedStore64(void *p, uint64_t v) {
- __sanitizer_unaligned_store64(p, v);
-}
-
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
- (absl::base_internal::UnalignedLoad16(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
- (absl::base_internal::UnalignedLoad32(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
- (absl::base_internal::UnalignedLoad64(_p))
-
-#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
- (absl::base_internal::UnalignedStore16(_p, _val))
-#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
- (absl::base_internal::UnalignedStore32(_p, _val))
-#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
- (absl::base_internal::UnalignedStore64(_p, _val))
-
-#else
-
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
@@ -151,8 +77,6 @@ ABSL_NAMESPACE_END
#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
(absl::base_internal::UnalignedStore64(_p, _val))
-#endif
-
#endif // defined(__cplusplus), end of unaligned API
#endif // ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_
diff --git a/abseil-cpp/absl/base/internal/unscaledcycleclock.cc b/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
index f1e7bbe..05e0e7b 100644
--- a/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
+++ b/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
@@ -24,8 +24,13 @@
#ifdef __GLIBC__
#include <sys/platform/ppc.h>
#elif defined(__FreeBSD__)
-#include <sys/sysctl.h>
+// clang-format off
+// This order does actually matter =(.
#include <sys/types.h>
+#include <sys/sysctl.h>
+// clang-format on
+
+#include "absl/base/call_once.h"
#endif
#endif
@@ -49,12 +54,6 @@ double UnscaledCycleClock::Frequency() {
#elif defined(__x86_64__)
-int64_t UnscaledCycleClock::Now() {
- uint64_t low, high;
- __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
- return (high << 32) | low;
-}
-
double UnscaledCycleClock::Frequency() {
return base_internal::NominalCPUFrequency();
}
@@ -72,13 +71,12 @@ int64_t UnscaledCycleClock::Now() {
#else
int32_t tbu, tbl, tmp;
asm volatile(
- "0:\n"
"mftbu %[hi32]\n"
"mftb %[lo32]\n"
"mftbu %[tmp]\n"
"cmpw %[tmp],%[hi32]\n"
- "bne 0b\n"
- : [ hi32 ] "=r"(tbu), [ lo32 ] "=r"(tbl), [ tmp ] "=r"(tmp));
+ "bne $-16\n" // Retry on failure.
+ : [hi32] "=r"(tbu), [lo32] "=r"(tbl), [tmp] "=r"(tmp));
return (static_cast<int64_t>(tbu) << 32) | tbl;
#endif
#endif
@@ -87,6 +85,10 @@ int64_t UnscaledCycleClock::Now() {
double UnscaledCycleClock::Frequency() {
#ifdef __GLIBC__
return __ppc_get_timebase_freq();
+#elif defined(_AIX)
+ // This is the same constant value as returned by
+ // __ppc_get_timebase_freq().
+ return static_cast<double>(512000000);
#elif defined(__FreeBSD__)
static once_flag init_timebase_frequency_once;
static double timebase_frequency = 0.0;
@@ -119,13 +121,23 @@ double UnscaledCycleClock::Frequency() {
return aarch64_timer_frequency;
}
+#elif defined(__riscv)
+
+int64_t UnscaledCycleClock::Now() {
+ int64_t virtual_timer_value;
+ asm volatile("rdcycle %0" : "=r"(virtual_timer_value));
+ return virtual_timer_value;
+}
+
+double UnscaledCycleClock::Frequency() {
+ return base_internal::NominalCPUFrequency();
+}
+
#elif defined(_M_IX86) || defined(_M_X64)
#pragma intrinsic(__rdtsc)
-int64_t UnscaledCycleClock::Now() {
- return __rdtsc();
-}
+int64_t UnscaledCycleClock::Now() { return __rdtsc(); }
double UnscaledCycleClock::Frequency() {
return base_internal::NominalCPUFrequency();
diff --git a/abseil-cpp/absl/base/internal/unscaledcycleclock.h b/abseil-cpp/absl/base/internal/unscaledcycleclock.h
index 82f2c87..cc1276b 100644
--- a/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+++ b/abseil-cpp/absl/base/internal/unscaledcycleclock.h
@@ -42,49 +42,11 @@
#include <TargetConditionals.h>
#endif
-#include "absl/base/port.h"
-
-// The following platforms have an implementation of a hardware counter.
-#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
- defined(__powerpc__) || defined(__ppc__) || \
- defined(_M_IX86) || defined(_M_X64)
-#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
-#else
-#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
-#endif
-
-// The following platforms often disable access to the hardware
-// counter (through a sandbox) even if the underlying hardware has a
-// usable counter. The CycleTimer interface also requires a *scaled*
-// CycleClock that runs at atleast 1 MHz. We've found some Android
-// ARM64 devices where this is not the case, so we disable it by
-// default on Android ARM64.
-#if defined(__native_client__) || \
- (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
- (defined(__ANDROID__) && defined(__aarch64__))
-#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0
-#else
-#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 1
-#endif
-
-// UnscaledCycleClock is an optional internal feature.
-// Use "#if ABSL_USE_UNSCALED_CYCLECLOCK" to test for its presence.
-// Can be overridden at compile-time via -DABSL_USE_UNSCALED_CYCLECLOCK=0|1
-#if !defined(ABSL_USE_UNSCALED_CYCLECLOCK)
-#define ABSL_USE_UNSCALED_CYCLECLOCK \
- (ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION && \
- ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT)
-#endif
+#include "absl/base/config.h"
+#include "absl/base/internal/unscaledcycleclock_config.h"
#if ABSL_USE_UNSCALED_CYCLECLOCK
-// This macro can be used to test if UnscaledCycleClock::Frequency()
-// is NominalCPUFrequency() on a particular platform.
-#if (defined(__i386__) || defined(__x86_64__) || \
- defined(_M_IX86) || defined(_M_X64))
-#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
-#endif
-
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal {
@@ -115,6 +77,16 @@ class UnscaledCycleClock {
friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency;
};
+#if defined(__x86_64__)
+
+inline int64_t UnscaledCycleClock::Now() {
+ uint64_t low, high;
+ __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
+ return static_cast<int64_t>((high << 32) | low);
+}
+
+#endif
+
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/abseil-cpp/absl/base/internal/unscaledcycleclock_config.h b/abseil-cpp/absl/base/internal/unscaledcycleclock_config.h
new file mode 100644
index 0000000..24b324a
--- /dev/null
+++ b/abseil-cpp/absl/base/internal/unscaledcycleclock_config.h
@@ -0,0 +1,62 @@
+// Copyright 2022 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_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_
+#define ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_
+
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
+// The following platforms have an implementation of a hardware counter.
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
+ defined(__powerpc__) || defined(__ppc__) || defined(__riscv) || \
+ defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
+#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
+#else
+#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
+#endif
+
+// The following platforms often disable access to the hardware
+// counter (through a sandbox) even if the underlying hardware has a
+// usable counter. The CycleTimer interface also requires a *scaled*
+// CycleClock that runs at atleast 1 MHz. We've found some Android
+// ARM64 devices where this is not the case, so we disable it by
+// default on Android ARM64.
+#if defined(__native_client__) || (defined(__APPLE__)) || \
+ (defined(__ANDROID__) && defined(__aarch64__))
+#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0
+#else
+#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 1
+#endif
+
+// UnscaledCycleClock is an optional internal feature.
+// Use "#if ABSL_USE_UNSCALED_CYCLECLOCK" to test for its presence.
+// Can be overridden at compile-time via -DABSL_USE_UNSCALED_CYCLECLOCK=0|1
+#if !defined(ABSL_USE_UNSCALED_CYCLECLOCK)
+#define ABSL_USE_UNSCALED_CYCLECLOCK \
+ (ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION && \
+ ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT)
+#endif
+
+#if ABSL_USE_UNSCALED_CYCLECLOCK
+// This macro can be used to test if UnscaledCycleClock::Frequency()
+// is NominalCPUFrequency() on a particular platform.
+#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \
+ defined(_M_IX86) || defined(_M_X64))
+#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
+#endif
+#endif
+
+#endif // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_
diff --git a/abseil-cpp/absl/base/invoke_test.cc b/abseil-cpp/absl/base/invoke_test.cc
index bcdef36..7be26f6 100644
--- a/abseil-cpp/absl/base/invoke_test.cc
+++ b/abseil-cpp/absl/base/invoke_test.cc
@@ -31,6 +31,14 @@ namespace {
int Function(int a, int b) { return a - b; }
+void VoidFunction(int& a, int& b) {
+ a += b;
+ b = a - b;
+ a -= b;
+}
+
+int ZeroArgFunction() { return -1937; }
+
int Sink(std::unique_ptr<int> p) {
return *p;
}
@@ -223,6 +231,100 @@ TEST(InvokeTest, SfinaeFriendly) {
EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
}
+TEST(IsInvocableRTest, CallableExactMatch) {
+ static_assert(
+ base_internal::is_invocable_r<int, decltype(Function), int, int>::value,
+ "Should be true for exact match of types on a free function");
+}
+
+TEST(IsInvocableRTest, CallableArgumentConversionMatch) {
+ static_assert(
+ base_internal::is_invocable_r<int, decltype(Function), char, int>::value,
+ "Should be true for convertible argument type");
+}
+
+TEST(IsInvocableRTest, CallableReturnConversionMatch) {
+ static_assert(base_internal::is_invocable_r<double, decltype(Function), int,
+ int>::value,
+ "Should be true for convertible return type");
+}
+
+TEST(IsInvocableRTest, CallableReturnVoid) {
+ static_assert(base_internal::is_invocable_r<void, decltype(VoidFunction),
+ int&, int&>::value,
+ "Should be true for void expected and actual return types");
+ static_assert(
+ base_internal::is_invocable_r<void, decltype(Function), int, int>::value,
+ "Should be true for void expected and non-void actual return types");
+}
+
+TEST(IsInvocableRTest, CallableRefQualifierMismatch) {
+ static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
+ int&, const int&>::value,
+ "Should be false for reference constness mismatch");
+ static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
+ int&&, int&>::value,
+ "Should be false for reference value category mismatch");
+}
+
+TEST(IsInvocableRTest, CallableArgumentTypeMismatch) {
+ static_assert(!base_internal::is_invocable_r<int, decltype(Function),
+ std::string, int>::value,
+ "Should be false for argument type mismatch");
+}
+
+TEST(IsInvocableRTest, CallableReturnTypeMismatch) {
+ static_assert(!base_internal::is_invocable_r<std::string, decltype(Function),
+ int, int>::value,
+ "Should be false for return type mismatch");
+}
+
+TEST(IsInvocableRTest, CallableTooFewArgs) {
+ static_assert(
+ !base_internal::is_invocable_r<int, decltype(Function), int>::value,
+ "Should be false for too few arguments");
+}
+
+TEST(IsInvocableRTest, CallableTooManyArgs) {
+ static_assert(!base_internal::is_invocable_r<int, decltype(Function), int,
+ int, int>::value,
+ "Should be false for too many arguments");
+}
+
+TEST(IsInvocableRTest, MemberFunctionAndReference) {
+ static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
+ Class&, int, int>::value,
+ "Should be true for exact match of types on a member function "
+ "and class reference");
+}
+
+TEST(IsInvocableRTest, MemberFunctionAndPointer) {
+ static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
+ Class*, int, int>::value,
+ "Should be true for exact match of types on a member function "
+ "and class pointer");
+}
+
+TEST(IsInvocableRTest, DataMemberAndReference) {
+ static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
+ Class&>::value,
+ "Should be true for exact match of types on a data member and "
+ "class reference");
+}
+
+TEST(IsInvocableRTest, DataMemberAndPointer) {
+ static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
+ Class*>::value,
+ "Should be true for exact match of types on a data member and "
+ "class pointer");
+}
+
+TEST(IsInvocableRTest, CallableZeroArgs) {
+ static_assert(
+ base_internal::is_invocable_r<int, decltype(ZeroArgFunction)>::value,
+ "Should be true for exact match for a zero-arg free function");
+}
+
} // namespace
} // namespace base_internal
ABSL_NAMESPACE_END
diff --git a/abseil-cpp/absl/base/log_severity.cc b/abseil-cpp/absl/base/log_severity.cc
index 72312af..60a8fc1 100644
--- a/abseil-cpp/absl/base/log_severity.cc
+++ b/abseil-cpp/absl/base/log_severity.cc
@@ -16,6 +16,8 @@
#include <ostream>
+#include "absl/base/attributes.h"
+
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -23,5 +25,31 @@ 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<int>(s) << ")";
}
+
+std::ostream& operator<<(std::ostream& os, absl::LogSeverityAtLeast s) {
+ switch (s) {
+ case absl::LogSeverityAtLeast::kInfo:
+ case absl::LogSeverityAtLeast::kWarning:
+ case absl::LogSeverityAtLeast::kError:
+ case absl::LogSeverityAtLeast::kFatal:
+ return os << ">=" << static_cast<absl::LogSeverity>(s);
+ case absl::LogSeverityAtLeast::kInfinity:
+ return os << "INFINITY";
+ }
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, absl::LogSeverityAtMost s) {
+ switch (s) {
+ case absl::LogSeverityAtMost::kInfo:
+ case absl::LogSeverityAtMost::kWarning:
+ case absl::LogSeverityAtMost::kError:
+ case absl::LogSeverityAtMost::kFatal:
+ return os << "<=" << static_cast<absl::LogSeverity>(s);
+ case absl::LogSeverityAtMost::kNegativeInfinity:
+ return os << "NEGATIVE_INFINITY";
+ }
+ return os;
+}
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/abseil-cpp/absl/base/log_severity.h b/abseil-cpp/absl/base/log_severity.h
index 65a3b16..8bdca38 100644
--- a/abseil-cpp/absl/base/log_severity.h
+++ b/abseil-cpp/absl/base/log_severity.h
@@ -12,8 +12,8 @@
// 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_
+#ifndef ABSL_BASE_LOG_SEVERITY_H_
+#define ABSL_BASE_LOG_SEVERITY_H_
#include <array>
#include <ostream>
@@ -36,7 +36,7 @@ ABSL_NAMESPACE_BEGIN
// such values to a defined severity level, however in some cases values other
// than the defined levels are useful for comparison.
//
-// Exmaple:
+// Example:
//
// // Effectively disables all logging:
// SetMinLogLevel(static_cast<absl::LogSeverity>(100));
@@ -115,7 +115,58 @@ constexpr absl::LogSeverity NormalizeLogSeverity(int s) {
// unspecified; do not rely on it.
std::ostream& operator<<(std::ostream& os, absl::LogSeverity s);
+// Enums representing a lower bound for LogSeverity. APIs that only operate on
+// messages of at least a certain level (for example, `SetMinLogLevel()`) use
+// this type to specify that level. absl::LogSeverityAtLeast::kInfinity is
+// a level above all threshold levels and therefore no log message will
+// ever meet this threshold.
+enum class LogSeverityAtLeast : int {
+ kInfo = static_cast<int>(absl::LogSeverity::kInfo),
+ kWarning = static_cast<int>(absl::LogSeverity::kWarning),
+ kError = static_cast<int>(absl::LogSeverity::kError),
+ kFatal = static_cast<int>(absl::LogSeverity::kFatal),
+ kInfinity = 1000,
+};
+
+std::ostream& operator<<(std::ostream& os, absl::LogSeverityAtLeast s);
+
+// Enums representing an upper bound for LogSeverity. APIs that only operate on
+// messages of at most a certain level (for example, buffer all messages at or
+// below a certain level) use this type to specify that level.
+// absl::LogSeverityAtMost::kNegativeInfinity is a level below all threshold
+// levels and therefore will exclude all log messages.
+enum class LogSeverityAtMost : int {
+ kNegativeInfinity = -1000,
+ kInfo = static_cast<int>(absl::LogSeverity::kInfo),
+ kWarning = static_cast<int>(absl::LogSeverity::kWarning),
+ kError = static_cast<int>(absl::LogSeverity::kError),
+ kFatal = static_cast<int>(absl::LogSeverity::kFatal),
+};
+
+std::ostream& operator<<(std::ostream& os, absl::LogSeverityAtMost s);
+
+#define COMPOP(op1, op2, T) \
+ constexpr bool operator op1(absl::T lhs, absl::LogSeverity rhs) { \
+ return static_cast<absl::LogSeverity>(lhs) op1 rhs; \
+ } \
+ constexpr bool operator op2(absl::LogSeverity lhs, absl::T rhs) { \
+ return lhs op2 static_cast<absl::LogSeverity>(rhs); \
+ }
+
+// Comparisons between `LogSeverity` and `LogSeverityAtLeast`/
+// `LogSeverityAtMost` are only supported in one direction.
+// Valid checks are:
+// LogSeverity >= LogSeverityAtLeast
+// LogSeverity < LogSeverityAtLeast
+// LogSeverity <= LogSeverityAtMost
+// LogSeverity > LogSeverityAtMost
+COMPOP(>, <, LogSeverityAtLeast)
+COMPOP(<=, >=, LogSeverityAtLeast)
+COMPOP(<, >, LogSeverityAtMost)
+COMPOP(>=, <=, LogSeverityAtMost)
+#undef COMPOP
+
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#endif // ABSL_BASE_LOG_SEVERITY_H_
diff --git a/abseil-cpp/absl/base/log_severity_test.cc b/abseil-cpp/absl/base/log_severity_test.cc
index 2c6872b..16091a5 100644
--- a/abseil-cpp/absl/base/log_severity_test.cc
+++ b/abseil-cpp/absl/base/log_severity_test.cc
@@ -35,7 +35,8 @@ using ::testing::IsTrue;
using ::testing::TestWithParam;
using ::testing::Values;
-std::string StreamHelper(absl::LogSeverity value) {
+template <typename T>
+std::string StreamHelper(T value) {
std::ostringstream stream;
stream << value;
return stream.str();
@@ -52,9 +53,9 @@ TEST(StreamTest, Works) {
Eq("absl::LogSeverity(4)"));
}
-static_assert(
- absl::flags_internal::FlagUseOneWordStorage<absl::LogSeverity>::value,
- "Flags of type absl::LogSeverity ought to be lock-free.");
+static_assert(absl::flags_internal::FlagUseValueAndInitBitStorage<
+ absl::LogSeverity>::value,
+ "Flags of type absl::LogSeverity ought to be lock-free.");
using ParseFlagFromOutOfRangeIntegerTest = TestWithParam<int64_t>;
INSTANTIATE_TEST_SUITE_P(
@@ -201,4 +202,44 @@ TEST_P(UnparseFlagToOtherIntegerTest, ReturnsExpectedValueAndRoundTrips) {
IsTrue());
EXPECT_THAT(reparsed_value, Eq(to_unparse));
}
+
+TEST(LogThresholdTest, LogSeverityAtLeastTest) {
+ EXPECT_LT(absl::LogSeverity::kError, absl::LogSeverityAtLeast::kFatal);
+ EXPECT_GT(absl::LogSeverityAtLeast::kError, absl::LogSeverity::kInfo);
+
+ EXPECT_LE(absl::LogSeverityAtLeast::kInfo, absl::LogSeverity::kError);
+ EXPECT_GE(absl::LogSeverity::kError, absl::LogSeverityAtLeast::kInfo);
+}
+
+TEST(LogThresholdTest, LogSeverityAtMostTest) {
+ EXPECT_GT(absl::LogSeverity::kError, absl::LogSeverityAtMost::kWarning);
+ EXPECT_LT(absl::LogSeverityAtMost::kError, absl::LogSeverity::kFatal);
+
+ EXPECT_GE(absl::LogSeverityAtMost::kFatal, absl::LogSeverity::kError);
+ EXPECT_LE(absl::LogSeverity::kWarning, absl::LogSeverityAtMost::kError);
+}
+
+TEST(LogThresholdTest, Extremes) {
+ EXPECT_LT(absl::LogSeverity::kFatal, absl::LogSeverityAtLeast::kInfinity);
+ EXPECT_GT(absl::LogSeverity::kInfo,
+ absl::LogSeverityAtMost::kNegativeInfinity);
+}
+
+TEST(LogThresholdTest, Output) {
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kInfo), Eq(">=INFO"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kWarning),
+ Eq(">=WARNING"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kError), Eq(">=ERROR"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kFatal), Eq(">=FATAL"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtLeast::kInfinity),
+ Eq("INFINITY"));
+
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kInfo), Eq("<=INFO"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kWarning), Eq("<=WARNING"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kError), Eq("<=ERROR"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kFatal), Eq("<=FATAL"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverityAtMost::kNegativeInfinity),
+ Eq("NEGATIVE_INFINITY"));
+}
+
} // namespace
diff --git a/abseil-cpp/absl/base/macros.h b/abseil-cpp/absl/base/macros.h
index 02dd9ff..f33cd19 100644
--- a/abseil-cpp/absl/base/macros.h
+++ b/abseil-cpp/absl/base/macros.h
@@ -103,17 +103,11 @@ ABSL_NAMESPACE_END
// aborts the program in release mode (when NDEBUG is defined). The
// implementation should abort the program as quickly as possible and ideally it
// should not be possible to ignore the abort request.
-#if (ABSL_HAVE_BUILTIN(__builtin_trap) && \
- ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \
- (defined(__GNUC__) && !defined(__clang__))
-#define ABSL_INTERNAL_HARDENING_ABORT() \
- do { \
- __builtin_trap(); \
- __builtin_unreachable(); \
+#define ABSL_INTERNAL_HARDENING_ABORT() \
+ do { \
+ ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
+ ABSL_INTERNAL_UNREACHABLE_IMPL(); \
} while (false)
-#else
-#define ABSL_INTERNAL_HARDENING_ABORT() abort()
-#endif
// ABSL_HARDENING_ASSERT()
//
diff --git a/abseil-cpp/absl/base/nullability.h b/abseil-cpp/absl/base/nullability.h
new file mode 100644
index 0000000..6f49b6f
--- /dev/null
+++ b/abseil-cpp/absl/base/nullability.h
@@ -0,0 +1,224 @@
+// Copyright 2023 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.
+//
+// -----------------------------------------------------------------------------
+// File: nullability.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines a set of "templated annotations" for designating the
+// expected nullability of pointers. These annotations allow you to designate
+// pointers in one of three classification states:
+//
+// * "Non-null" (for pointers annotated `Nonnull<T>`), indicating that it is
+// invalid for the given pointer to ever be null.
+// * "Nullable" (for pointers annotated `Nullable<T>`), indicating that it is
+// valid for the given pointer to be null.
+// * "Unknown" (for pointers annotated `NullabilityUnknown<T>`), indicating
+// that the given pointer has not been yet classified as either nullable or
+// non-null. This is the default state of unannotated pointers.
+//
+// NOTE: unannotated pointers implicitly bear the annotation
+// `NullabilityUnknown<T>`; you should rarely, if ever, see this annotation used
+// in the codebase explicitly.
+//
+// -----------------------------------------------------------------------------
+// Nullability and Contracts
+// -----------------------------------------------------------------------------
+//
+// These nullability annotations allow you to more clearly specify contracts on
+// software components by narrowing the *preconditions*, *postconditions*, and
+// *invariants* of pointer state(s) in any given interface. It then depends on
+// context who is responsible for fulfilling the annotation's requirements.
+//
+// For example, a function may receive a pointer argument. Designating that
+// pointer argument as "non-null" tightens the precondition of the contract of
+// that function. It is then the responsibility of anyone calling such a
+// function to ensure that the passed pointer is not null.
+//
+// Similarly, a function may have a pointer as a return value. Designating that
+// return value as "non-null" tightens the postcondition of the contract of that
+// function. In this case, however, it is the responsibility of the function
+// itself to ensure that the returned pointer is not null.
+//
+// Clearly defining these contracts allows providers (and consumers) of such
+// pointers to have more confidence in their null state. If a function declares
+// a return value as "non-null", for example, the caller should not need to
+// check whether the returned value is `nullptr`; it can simply assume the
+// pointer is valid.
+//
+// Of course most interfaces already have expectations on the nullability state
+// of pointers, and these expectations are, in effect, a contract; often,
+// however, those contracts are either poorly or partially specified, assumed,
+// or misunderstood. These nullability annotations are designed to allow you to
+// formalize those contracts within the codebase.
+//
+// -----------------------------------------------------------------------------
+// Using Nullability Annotations
+// -----------------------------------------------------------------------------
+//
+// It is important to note that these annotations are not distinct strong
+// *types*. They are alias templates defined to be equal to the underlying
+// pointer type. A pointer annotated `Nonnull<T*>`, for example, is simply a
+// pointer of type `T*`. Each annotation acts as a form of documentation about
+// the contract for the given pointer. Each annotation requires providers or
+// consumers of these pointers across API boundaries to take appropriate steps
+// when setting or using these pointers:
+//
+// * "Non-null" pointers should never be null. It is the responsibility of the
+// provider of this pointer to ensure that the pointer may never be set to
+// null. Consumers of such pointers can treat such pointers as non-null.
+// * "Nullable" pointers may or may not be null. Consumers of such pointers
+// should precede any usage of that pointer (e.g. a dereference operation)
+// with a a `nullptr` check.
+// * "Unknown" pointers may be either "non-null" or "nullable" but have not been
+// definitively determined to be in either classification state. Providers of
+// such pointers across API boundaries should determine -- over time -- to
+// annotate the pointer in either of the above two states. Consumers of such
+// pointers across an API boundary should continue to treat such pointers as
+// they currently do.
+//
+// Example:
+//
+// // PaySalary() requires the passed pointer to an `Employee` to be non-null.
+// void PaySalary(absl::Nonnull<Employee *> e) {
+// pay(e->salary); // OK to dereference
+// }
+//
+// // CompleteTransaction() guarantees the returned pointer to an `Account` to
+// // be non-null.
+// absl::Nonnull<Account *> balance CompleteTransaction(double fee) {
+// ...
+// }
+//
+// // Note that specifying a nullability annotation does not prevent someone
+// // from violating the contract:
+//
+// Nullable<Employee *> find(Map& employees, std::string_view name);
+//
+// void g(Map& employees) {
+// Employee *e = find(employees, "Pat");
+// // `e` can now be null.
+// PaySalary(e); // Violates contract, but compiles!
+// }
+//
+// Nullability annotations, in other words, are useful for defining and
+// narrowing contracts; *enforcement* of those contracts depends on use and any
+// additional (static or dynamic analysis) tooling.
+//
+// NOTE: The "unknown" annotation state indicates that a pointer's contract has
+// not yet been positively identified. The unknown state therefore acts as a
+// form of documentation of your technical debt, and a codebase that adopts
+// nullability annotations should aspire to annotate every pointer as either
+// "non-null" or "nullable".
+//
+// -----------------------------------------------------------------------------
+// Applicability of Nullability Annotations
+// -----------------------------------------------------------------------------
+//
+// By default, nullability annotations are applicable to raw and smart
+// pointers. User-defined types can indicate compatibility with nullability
+// annotations by providing an `absl_nullability_compatible` nested type. The
+// actual definition of this inner type is not relevant as it is used merely as
+// a marker. It is common to use a using declaration of
+// `absl_nullability_compatible` set to void.
+//
+// // Example:
+// struct MyPtr {
+// using absl_nullability_compatible = void;
+// ...
+// };
+//
+// DISCLAIMER:
+// ===========================================================================
+// These nullability annotations are primarily a human readable signal about the
+// intended contract of the pointer. They are not *types* and do not currently
+// provide any correctness guarantees. For example, a pointer annotated as
+// `Nonnull<T*>` is *not guaranteed* to be non-null, and the compiler won't
+// alert or prevent assignment of a `Nullable<T*>` to a `Nonnull<T*>`.
+// ===========================================================================
+#ifndef ABSL_BASE_NULLABILITY_H_
+#define ABSL_BASE_NULLABILITY_H_
+
+#include "absl/base/internal/nullability_impl.h"
+
+namespace absl {
+
+// absl::Nonnull
+//
+// The indicated pointer is never null. It is the responsibility of the provider
+// of this pointer across an API boundary to ensure that the pointer is never be
+// set to null. Consumers of this pointer across an API boundary may safely
+// dereference the pointer.
+//
+// Example:
+//
+// // `employee` is designated as not null.
+// void PaySalary(absl::Nonnull<Employee *> employee) {
+// pay(*employee); // OK to dereference
+// }
+template <typename T>
+using Nonnull = nullability_internal::NonnullImpl<T>;
+
+// absl::Nullable
+//
+// The indicated pointer may, by design, be either null or non-null. Consumers
+// of this pointer across an API boundary should perform a `nullptr` check
+// before performing any operation using the pointer.
+//
+// Example:
+//
+// // `employee` may be null.
+// void PaySalary(absl::Nullable<Employee *> employee) {
+// if (employee != nullptr) {
+// Pay(*employee); // OK to dereference
+// }
+// }
+template <typename T>
+using Nullable = nullability_internal::NullableImpl<T>;
+
+// absl::NullabilityUnknown (default)
+//
+// The indicated pointer has not yet been determined to be definitively
+// "non-null" or "nullable." Providers of such pointers across API boundaries
+// should, over time, annotate such pointers as either "non-null" or "nullable."
+// Consumers of these pointers across an API boundary should treat such pointers
+// with the same caution they treat currently unannotated pointers. Most
+// existing code will have "unknown" pointers, which should eventually be
+// migrated into one of the above two nullability states: `Nonnull<T>` or
+// `Nullable<T>`.
+//
+// NOTE: Because this annotation is the global default state, pointers without
+// any annotation are assumed to have "unknown" semantics. This assumption is
+// designed to minimize churn and reduce clutter within the codebase.
+//
+// Example:
+//
+// // `employee`s nullability state is unknown.
+// void PaySalary(absl::NullabilityUnknown<Employee *> employee) {
+// Pay(*employee); // Potentially dangerous. API provider should investigate.
+// }
+//
+// Note that a pointer without an annotation, by default, is assumed to have the
+// annotation `NullabilityUnknown`.
+//
+// // `employee`s nullability state is unknown.
+// void PaySalary(Employee* employee) {
+// Pay(*employee); // Potentially dangerous. API provider should investigate.
+// }
+template <typename T>
+using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>;
+
+} // namespace absl
+
+#endif // ABSL_BASE_NULLABILITY_H_
diff --git a/abseil-cpp/absl/base/nullability_test.cc b/abseil-cpp/absl/base/nullability_test.cc
new file mode 100644
index 0000000..028ea6c
--- /dev/null
+++ b/abseil-cpp/absl/base/nullability_test.cc
@@ -0,0 +1,129 @@
+// Copyright 2023 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/base/nullability.h"
+
+#include <cassert>
+#include <memory>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+
+namespace {
+using ::absl::Nonnull;
+using ::absl::NullabilityUnknown;
+using ::absl::Nullable;
+
+void funcWithNonnullArg(Nonnull<int*> /*arg*/) {}
+template <typename T>
+void funcWithDeducedNonnullArg(Nonnull<T*> /*arg*/) {}
+
+TEST(NonnullTest, NonnullArgument) {
+ int var = 0;
+ funcWithNonnullArg(&var);
+ funcWithDeducedNonnullArg(&var);
+}
+
+Nonnull<int*> funcWithNonnullReturn() {
+ static int var = 0;
+ return &var;
+}
+
+TEST(NonnullTest, NonnullReturn) {
+ auto var = funcWithNonnullReturn();
+ (void)var;
+}
+
+TEST(PassThroughTest, PassesThroughRawPointerToInt) {
+ EXPECT_TRUE((std::is_same<Nonnull<int*>, int*>::value));
+ EXPECT_TRUE((std::is_same<Nullable<int*>, int*>::value));
+ EXPECT_TRUE((std::is_same<NullabilityUnknown<int*>, int*>::value));
+}
+
+TEST(PassThroughTest, PassesThroughRawPointerToVoid) {
+ EXPECT_TRUE((std::is_same<Nonnull<void*>, void*>::value));
+ EXPECT_TRUE((std::is_same<Nullable<void*>, void*>::value));
+ EXPECT_TRUE((std::is_same<NullabilityUnknown<void*>, void*>::value));
+}
+
+TEST(PassThroughTest, PassesThroughUniquePointerToInt) {
+ using T = std::unique_ptr<int>;
+ EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value));
+ EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+ EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughSharedPointerToInt) {
+ using T = std::shared_ptr<int>;
+ EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value));
+ EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+ EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughSharedPointerToVoid) {
+ using T = std::shared_ptr<void>;
+ EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value));
+ EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+ EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughPointerToMemberObject) {
+ using T = decltype(&std::pair<int, int>::first);
+ EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value));
+ EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+ EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughPointerToMemberFunction) {
+ using T = decltype(&std::unique_ptr<int>::reset);
+ EXPECT_TRUE((std::is_same<Nonnull<T>, T>::value));
+ EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+ EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+} // namespace
+
+// Nullable ADL lookup test
+namespace util {
+// Helper for NullableAdlTest. Returns true, denoting that argument-dependent
+// lookup found this implementation of DidAdlWin. Must be in namespace
+// util itself, not a nested anonymous namespace.
+template <typename T>
+bool DidAdlWin(T*) {
+ return true;
+}
+
+// Because this type is defined in namespace util, an unqualified call to
+// DidAdlWin with a pointer to MakeAdlWin will find the above implementation.
+struct MakeAdlWin {};
+} // namespace util
+
+namespace {
+// Returns false, denoting that ADL did not inspect namespace util. If it
+// had, the better match (T*) above would have won out over the (...) here.
+bool DidAdlWin(...) { return false; }
+
+TEST(NullableAdlTest, NullableAddsNothingToArgumentDependentLookup) {
+ // Treatment: util::Nullable<int*> contributes nothing to ADL because
+ // int* itself doesn't.
+ EXPECT_FALSE(DidAdlWin((int*)nullptr));
+ EXPECT_FALSE(DidAdlWin((Nullable<int*>)nullptr));
+
+ // Control: Argument-dependent lookup does find the implementation in
+ // namespace util when the underlying pointee type resides there.
+ EXPECT_TRUE(DidAdlWin((util::MakeAdlWin*)nullptr));
+ EXPECT_TRUE(DidAdlWin((Nullable<util::MakeAdlWin*>)nullptr));
+}
+} // namespace
diff --git a/abseil-cpp/absl/base/optimization.h b/abseil-cpp/absl/base/optimization.h
index 2e31376..ad0121a 100644
--- a/abseil-cpp/absl/base/optimization.h
+++ b/abseil-cpp/absl/base/optimization.h
@@ -22,13 +22,15 @@
#ifndef ABSL_BASE_OPTIMIZATION_H_
#define ABSL_BASE_OPTIMIZATION_H_
+#include <assert.h>
+
#include "absl/base/config.h"
// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION
//
-// Instructs the compiler to avoid optimizing tail-call recursion. Use of this
-// macro is useful when you wish to preserve the existing function order within
-// a stack trace for logging, debugging, or profiling purposes.
+// Instructs the compiler to avoid optimizing tail-call recursion. This macro is
+// useful when you wish to preserve the existing function order within a stack
+// trace for logging, debugging, or profiling purposes.
//
// Example:
//
@@ -89,6 +91,7 @@
#define ABSL_CACHELINE_SIZE 64
#endif
#endif
+#endif
#ifndef ABSL_CACHELINE_SIZE
// A reasonable default guess. Note that overestimates tend to waste more
@@ -104,9 +107,10 @@
// Cacheline aligning objects properly allows constructive memory sharing and
// prevents destructive (or "false") memory sharing.
//
-// NOTE: this macro should be replaced with usage of `alignas()` using
+// NOTE: callers should replace uses of this macro with `alignas()` using
// `std::hardware_constructive_interference_size` and/or
-// `std::hardware_destructive_interference_size` when available within C++17.
+// `std::hardware_destructive_interference_size` when C++17 becomes available to
+// them.
//
// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
// for more information.
@@ -138,12 +142,11 @@
// the generated machine code.
// 3) Prefer applying this attribute to individual variables. Avoid
// applying it to types. This tends to localize the effect.
+#if defined(__clang__) || defined(__GNUC__)
#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE)))
#elif defined(_MSC_VER)
-#define ABSL_CACHELINE_SIZE 64
#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE))
#else
-#define ABSL_CACHELINE_SIZE 64
#define ABSL_CACHELINE_ALIGNED
#endif
@@ -178,45 +181,105 @@
#define ABSL_PREDICT_TRUE(x) (x)
#endif
-// ABSL_INTERNAL_ASSUME(cond)
-// Informs the compiler than a condition is always true and that it can assume
-// it to be true for optimization purposes. The call has undefined behavior if
-// the condition is false.
+// `ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL()` aborts the program in the fastest
+// possible way, with no attempt at logging. One use is to implement hardening
+// aborts with ABSL_OPTION_HARDENED. Since this is an internal symbol, it
+// should not be used directly outside of Abseil.
+#if ABSL_HAVE_BUILTIN(__builtin_trap) || \
+ (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() __builtin_trap()
+#else
+#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() abort()
+#endif
+
+// `ABSL_INTERNAL_UNREACHABLE_IMPL()` is the platform specific directive to
+// indicate that a statement is unreachable, and to allow the compiler to
+// optimize accordingly. Clients should use `ABSL_UNREACHABLE()`, which is
+// defined below.
+#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
+#define ABSL_INTERNAL_UNREACHABLE_IMPL() std::unreachable()
+#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
+#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_unreachable()
+#elif ABSL_HAVE_BUILTIN(__builtin_assume)
+#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_assume(false)
+#elif defined(_MSC_VER)
+#define ABSL_INTERNAL_UNREACHABLE_IMPL() __assume(false)
+#else
+#define ABSL_INTERNAL_UNREACHABLE_IMPL()
+#endif
+
+// `ABSL_UNREACHABLE()` is an unreachable statement. A program which reaches
+// one has undefined behavior, and the compiler may optimize accordingly.
+#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
+// Abort in hardened mode to avoid dangerous undefined behavior.
+#define ABSL_UNREACHABLE() \
+ do { \
+ ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
+ ABSL_INTERNAL_UNREACHABLE_IMPL(); \
+ } while (false)
+#else
+// The assert only fires in debug mode to aid in debugging.
+// When NDEBUG is defined, reaching ABSL_UNREACHABLE() is undefined behavior.
+#define ABSL_UNREACHABLE() \
+ do { \
+ /* NOLINTNEXTLINE: misc-static-assert */ \
+ assert(false && "ABSL_UNREACHABLE reached"); \
+ ABSL_INTERNAL_UNREACHABLE_IMPL(); \
+ } while (false)
+#endif
+
+// ABSL_ASSUME(cond)
+//
+// Informs the compiler that a condition is always true and that it can assume
+// it to be true for optimization purposes.
+//
+// WARNING: If the condition is false, the program can produce undefined and
+// potentially dangerous behavior.
+//
// In !NDEBUG mode, the condition is checked with an assert().
-// NOTE: The expression must not have side effects, as it will only be evaluated
-// in some compilation modes and not others.
+//
+// NOTE: The expression must not have side effects, as it may only be evaluated
+// in some compilation modes and not others. Some compilers may issue a warning
+// if the compiler cannot prove the expression has no side effects. For example,
+// the expression should not use a function call since the compiler cannot prove
+// that a function call does not have side effects.
//
// Example:
//
// int x = ...;
-// ABSL_INTERNAL_ASSUME(x >= 0);
+// ABSL_ASSUME(x >= 0);
// // The compiler can optimize the division to a simple right shift using the
// // assumption specified above.
// int y = x / 16;
//
#if !defined(NDEBUG)
-#define ABSL_INTERNAL_ASSUME(cond) assert(cond)
+#define ABSL_ASSUME(cond) assert(cond)
#elif ABSL_HAVE_BUILTIN(__builtin_assume)
-#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond)
+#define ABSL_ASSUME(cond) __builtin_assume(cond)
+#elif defined(_MSC_VER)
+#define ABSL_ASSUME(cond) __assume(cond)
+#elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
+#define ABSL_ASSUME(cond) \
+ do { \
+ if (!(cond)) std::unreachable(); \
+ } while (false)
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
-#define ABSL_INTERNAL_ASSUME(cond) \
+#define ABSL_ASSUME(cond) \
do { \
if (!(cond)) __builtin_unreachable(); \
- } while (0)
-#elif defined(_MSC_VER)
-#define ABSL_INTERNAL_ASSUME(cond) __assume(cond)
+ } while (false)
#else
-#define ABSL_INTERNAL_ASSUME(cond) \
+#define ABSL_ASSUME(cond) \
do { \
static_cast<void>(false && (cond)); \
- } while (0)
+ } while (false)
#endif
// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
// This macro forces small unique name on a static file level symbols like
// static local variables or static functions. This is intended to be used in
// macro definitions to optimize the cost of generated code. Do NOT use it on
-// symbols exported from translation unit since it may casue a link time
+// symbols exported from translation unit since it may cause a link time
// conflict.
//
// Example:
diff --git a/abseil-cpp/absl/base/options.h b/abseil-cpp/absl/base/options.h
index 6a0fb07..09b98ee 100644
--- a/abseil-cpp/absl/base/options.h
+++ b/abseil-cpp/absl/base/options.h
@@ -67,12 +67,6 @@
#ifndef ABSL_BASE_OPTIONS_H_
#define ABSL_BASE_OPTIONS_H_
-// Include a standard library header to allow configuration based on the
-// standard library in use.
-#ifdef __cplusplus
-#include <ciso646>
-#endif
-
// -----------------------------------------------------------------------------
// Type Compatibility Options
// -----------------------------------------------------------------------------
@@ -100,7 +94,7 @@
// User code should not inspect this macro. To check in the preprocessor if
// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY.
-#define ABSL_OPTION_USE_STD_ANY 2
+#define ABSL_OPTION_USE_STD_ANY 1
// ABSL_OPTION_USE_STD_OPTIONAL
@@ -127,7 +121,7 @@
// absl::optional is a typedef of std::optional, use the feature macro
// ABSL_USES_STD_OPTIONAL.
-#define ABSL_OPTION_USE_STD_OPTIONAL 2
+#define ABSL_OPTION_USE_STD_OPTIONAL 1
// ABSL_OPTION_USE_STD_STRING_VIEW
@@ -154,7 +148,7 @@
// absl::string_view is a typedef of std::string_view, use the feature macro
// ABSL_USES_STD_STRING_VIEW.
-#define ABSL_OPTION_USE_STD_STRING_VIEW 2
+#define ABSL_OPTION_USE_STD_STRING_VIEW 1
// ABSL_OPTION_USE_STD_VARIANT
//
@@ -180,7 +174,7 @@
// absl::variant is a typedef of std::variant, use the feature macro
// ABSL_USES_STD_VARIANT.
-#define ABSL_OPTION_USE_STD_VARIANT 2
+#define ABSL_OPTION_USE_STD_VARIANT 1
// ABSL_OPTION_USE_INLINE_NAMESPACE
@@ -206,7 +200,7 @@
// allowed.
#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
-#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_2020_09_23
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20230802
// ABSL_OPTION_HARDENED
//
diff --git a/abseil-cpp/absl/base/policy_checks.h b/abseil-cpp/absl/base/policy_checks.h
index 06b3243..372e848 100644
--- a/abseil-cpp/absl/base/policy_checks.h
+++ b/abseil-cpp/absl/base/policy_checks.h
@@ -44,17 +44,17 @@
// Toolchain Check
// -----------------------------------------------------------------------------
-// We support MSVC++ 14.0 update 2 and later.
+// We support Visual Studio 2019 (MSVC++ 16.0) and later.
// This minimum will go up.
-#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__)
-#error "This package requires Visual Studio 2015 Update 2 or higher."
+#if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__)
+#error "This package requires Visual Studio 2019 (MSVC++ 16.0) or higher."
#endif
-// We support gcc 4.7 and later.
+// We support GCC 7 and later.
// This minimum will go up.
#if defined(__GNUC__) && !defined(__clang__)
-#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
-#error "This package requires gcc 4.7 or higher."
+#if __GNUC__ < 7
+#error "This package requires GCC 7 or higher."
#endif
#endif
@@ -69,13 +69,15 @@
// C++ Version Check
// -----------------------------------------------------------------------------
-// Enforce C++11 as the minimum. Note that Visual Studio has not
-// advanced __cplusplus despite being good enough for our purposes, so
-// so we exempt it from the check.
-#if defined(__cplusplus) && !defined(_MSC_VER)
-#if __cplusplus < 201103L
-#error "C++ versions less than C++11 are not supported."
-#endif
+// Enforce C++14 as the minimum.
+#if defined(_MSVC_LANG)
+#if _MSVC_LANG < 201402L
+#error "C++ versions less than C++14 are not supported."
+#endif // _MSVC_LANG < 201402L
+#elif defined(__cplusplus)
+#if __cplusplus < 201402L
+#error "C++ versions less than C++14 are not supported."
+#endif // __cplusplus < 201402L
#endif
// -----------------------------------------------------------------------------
diff --git a/abseil-cpp/absl/base/port.h b/abseil-cpp/absl/base/port.h
index 6c28068..5bc4d6c 100644
--- a/abseil-cpp/absl/base/port.h
+++ b/abseil-cpp/absl/base/port.h
@@ -14,7 +14,6 @@
//
// This files is a forwarding header for other headers containing various
// portability macros and functions.
-// This file is used for both C and C++!
#ifndef ABSL_BASE_PORT_H_
#define ABSL_BASE_PORT_H_
diff --git a/abseil-cpp/absl/base/prefetch.h b/abseil-cpp/absl/base/prefetch.h
new file mode 100644
index 0000000..de7a180
--- /dev/null
+++ b/abseil-cpp/absl/base/prefetch.h
@@ -0,0 +1,198 @@
+// Copyright 2023 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.
+//
+// -----------------------------------------------------------------------------
+// File: prefetch.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines prefetch functions to prefetch memory contents
+// into the first level cache (L1) for the current CPU. The prefetch logic
+// offered in this header is limited to prefetching first level cachelines
+// only, and is aimed at relatively 'simple' prefetching logic.
+//
+#ifndef ABSL_BASE_PREFETCH_H_
+#define ABSL_BASE_PREFETCH_H_
+
+#include "absl/base/config.h"
+
+#if defined(ABSL_INTERNAL_HAVE_SSE)
+#include <xmmintrin.h>
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1900 && \
+ (defined(_M_X64) || defined(_M_IX86))
+#include <intrin.h>
+#pragma intrinsic(_mm_prefetch)
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Moves data into the L1 cache before it is read, or "prefetches" it.
+//
+// The value of `addr` is the address of the memory to prefetch. If
+// the target and compiler support it, data prefetch instructions are
+// generated. If the prefetch is done some time before the memory is
+// read, it may be in the cache by the time the read occurs.
+//
+// This method prefetches data with the highest degree of temporal locality;
+// data is prefetched where possible into all levels of the cache.
+//
+// Incorrect or gratuitous use of this function can degrade performance.
+// Use this function only when representative benchmarks show an improvement.
+//
+// Example:
+//
+// // Computes incremental checksum for `data`.
+// int ComputeChecksum(int sum, absl::string_view data);
+//
+// // Computes cumulative checksum for all values in `data`
+// int ComputeChecksum(absl::Span<const std::string> data) {
+// int sum = 0;
+// auto it = data.begin();
+// auto pit = data.begin();
+// auto end = data.end();
+// for (int dist = 8; dist > 0 && pit != data.end(); --dist, ++pit) {
+// absl::PrefetchToLocalCache(pit->data());
+// }
+// for (; pit != end; ++pit, ++it) {
+// sum = ComputeChecksum(sum, *it);
+// absl::PrefetchToLocalCache(pit->data());
+// }
+// for (; it != end; ++it) {
+// sum = ComputeChecksum(sum, *it);
+// }
+// return sum;
+// }
+//
+void PrefetchToLocalCache(const void* addr);
+
+// Moves data into the L1 cache before it is read, or "prefetches" it.
+//
+// This function is identical to `PrefetchToLocalCache()` except that it has
+// non-temporal locality: the fetched data should not be left in any of the
+// cache tiers. This is useful for cases where the data is used only once /
+// short term, for example, invoking a destructor on an object.
+//
+// Incorrect or gratuitous use of this function can degrade performance.
+// Use this function only when representative benchmarks show an improvement.
+//
+// Example:
+//
+// template <typename Iterator>
+// void DestroyPointers(Iterator begin, Iterator end) {
+// size_t distance = std::min(8U, bars.size());
+//
+// int dist = 8;
+// auto prefetch_it = begin;
+// while (prefetch_it != end && --dist;) {
+// absl::PrefetchToLocalCacheNta(*prefetch_it++);
+// }
+// while (prefetch_it != end) {
+// delete *begin++;
+// absl::PrefetchToLocalCacheNta(*prefetch_it++);
+// }
+// while (begin != end) {
+// delete *begin++;
+// }
+// }
+//
+void PrefetchToLocalCacheNta(const void* addr);
+
+// Moves data into the L1 cache with the intent to modify it.
+//
+// This function is similar to `PrefetchToLocalCache()` except that it
+// prefetches cachelines with an 'intent to modify' This typically includes
+// invalidating cache entries for this address in all other cache tiers, and an
+// exclusive access intent.
+//
+// Incorrect or gratuitous use of this function can degrade performance. As this
+// function can invalidate cached cachelines on other caches and computer cores,
+// incorrect usage of this function can have an even greater negative impact
+// than incorrect regular prefetches.
+// Use this function only when representative benchmarks show an improvement.
+//
+// Example:
+//
+// void* Arena::Allocate(size_t size) {
+// void* ptr = AllocateBlock(size);
+// absl::PrefetchToLocalCacheForWrite(p);
+// return ptr;
+// }
+//
+void PrefetchToLocalCacheForWrite(const void* addr);
+
+#if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
+
+#define ABSL_HAVE_PREFETCH 1
+
+// See __builtin_prefetch:
+// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
+//
+inline void PrefetchToLocalCache(const void* addr) {
+ __builtin_prefetch(addr, 0, 3);
+}
+
+inline void PrefetchToLocalCacheNta(const void* addr) {
+ __builtin_prefetch(addr, 0, 0);
+}
+
+inline void PrefetchToLocalCacheForWrite(const void* addr) {
+ // [x86] gcc/clang don't generate PREFETCHW for __builtin_prefetch(.., 1)
+ // unless -march=broadwell or newer; this is not generally the default, so we
+ // manually emit prefetchw. PREFETCHW is recognized as a no-op on older Intel
+ // processors and has been present on AMD processors since the K6-2.
+#if defined(__x86_64__)
+ asm("prefetchw (%0)" : : "r"(addr));
+#else
+ __builtin_prefetch(addr, 1, 3);
+#endif
+}
+
+#elif defined(ABSL_INTERNAL_HAVE_SSE)
+
+#define ABSL_HAVE_PREFETCH 1
+
+inline void PrefetchToLocalCache(const void* addr) {
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0);
+}
+
+inline void PrefetchToLocalCacheNta(const void* addr) {
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA);
+}
+
+inline void PrefetchToLocalCacheForWrite(const void* addr) {
+#if defined(_MM_HINT_ET0)
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_ET0);
+#elif !defined(_MSC_VER) && defined(__x86_64__)
+ // _MM_HINT_ET0 is not universally supported. As we commented further
+ // up, PREFETCHW is recognized as a no-op on older Intel processors
+ // and has been present on AMD processors since the K6-2. We have this
+ // disabled for MSVC compilers as this miscompiles on older MSVC compilers.
+ asm("prefetchw (%0)" : : "r"(addr));
+#endif
+}
+
+#else
+
+inline void PrefetchToLocalCache(const void* addr) {}
+inline void PrefetchToLocalCacheNta(const void* addr) {}
+inline void PrefetchToLocalCacheForWrite(const void* addr) {}
+
+#endif
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_PREFETCH_H_
diff --git a/abseil-cpp/absl/base/prefetch_test.cc b/abseil-cpp/absl/base/prefetch_test.cc
new file mode 100644
index 0000000..ee21989
--- /dev/null
+++ b/abseil-cpp/absl/base/prefetch_test.cc
@@ -0,0 +1,64 @@
+// Copyright 2023 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/base/prefetch.h"
+
+#include <memory>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+// Below tests exercise the functions only to guarantee they compile and execute
+// correctly. We make no attempt at verifying any prefetch instructions being
+// generated and executed: we assume the various implementation in terms of
+// __builtin_prefetch() or x86 intrinsics to be correct and well tested.
+
+TEST(PrefetchTest, PrefetchToLocalCache_StackA) {
+ char buf[100] = {};
+ absl::PrefetchToLocalCache(buf);
+ absl::PrefetchToLocalCacheNta(buf);
+ absl::PrefetchToLocalCacheForWrite(buf);
+}
+
+TEST(PrefetchTest, PrefetchToLocalCache_Heap) {
+ auto memory = std::make_unique<char[]>(200 << 10);
+ memset(memory.get(), 0, 200 << 10);
+ absl::PrefetchToLocalCache(memory.get());
+ absl::PrefetchToLocalCacheNta(memory.get());
+ absl::PrefetchToLocalCacheForWrite(memory.get());
+ absl::PrefetchToLocalCache(memory.get() + (50 << 10));
+ absl::PrefetchToLocalCacheNta(memory.get() + (50 << 10));
+ absl::PrefetchToLocalCacheForWrite(memory.get() + (50 << 10));
+ absl::PrefetchToLocalCache(memory.get() + (100 << 10));
+ absl::PrefetchToLocalCacheNta(memory.get() + (100 << 10));
+ absl::PrefetchToLocalCacheForWrite(memory.get() + (100 << 10));
+ absl::PrefetchToLocalCache(memory.get() + (150 << 10));
+ absl::PrefetchToLocalCacheNta(memory.get() + (150 << 10));
+ absl::PrefetchToLocalCacheForWrite(memory.get() + (150 << 10));
+}
+
+TEST(PrefetchTest, PrefetchToLocalCache_Nullptr) {
+ absl::PrefetchToLocalCache(nullptr);
+ absl::PrefetchToLocalCacheNta(nullptr);
+ absl::PrefetchToLocalCacheForWrite(nullptr);
+}
+
+TEST(PrefetchTest, PrefetchToLocalCache_InvalidPtr) {
+ absl::PrefetchToLocalCache(reinterpret_cast<const void*>(0x785326532L));
+ absl::PrefetchToLocalCacheNta(reinterpret_cast<const void*>(0x785326532L));
+ absl::PrefetchToLocalCacheForWrite(reinterpret_cast<const void*>(0x78532L));
+}
+
+} // namespace
diff --git a/abseil-cpp/absl/base/spinlock_test_common.cc b/abseil-cpp/absl/base/spinlock_test_common.cc
index dee266e..52ecf58 100644
--- a/abseil-cpp/absl/base/spinlock_test_common.cc
+++ b/abseil-cpp/absl/base/spinlock_test_common.cc
@@ -34,7 +34,7 @@
#include "absl/synchronization/blocking_counter.h"
#include "absl/synchronization/notification.h"
-constexpr int32_t kNumThreads = 10;
+constexpr uint32_t kNumThreads = 10;
constexpr int32_t kIters = 1000;
namespace absl {
@@ -48,14 +48,14 @@ struct SpinLockTest {
int64_t wait_end_time) {
return SpinLock::EncodeWaitCycles(wait_start_time, wait_end_time);
}
- static uint64_t DecodeWaitCycles(uint32_t lock_value) {
+ static int64_t DecodeWaitCycles(uint32_t lock_value) {
return SpinLock::DecodeWaitCycles(lock_value);
}
};
namespace {
-static constexpr int kArrayLength = 10;
+static constexpr size_t kArrayLength = 10;
static uint32_t values[kArrayLength];
ABSL_CONST_INIT static SpinLock static_cooperative_spinlock(
@@ -79,11 +79,11 @@ static uint32_t Hash32(uint32_t a, uint32_t c) {
return c;
}
-static void TestFunction(int thread_salt, SpinLock* spinlock) {
+static void TestFunction(uint32_t thread_salt, SpinLock* spinlock) {
for (int i = 0; i < kIters; i++) {
SpinLockHolder h(spinlock);
- for (int j = 0; j < kArrayLength; j++) {
- const int index = (j + thread_salt) % kArrayLength;
+ for (size_t j = 0; j < kArrayLength; j++) {
+ const size_t index = (j + thread_salt) % kArrayLength;
values[index] = Hash32(values[index], thread_salt);
std::this_thread::yield();
}
@@ -92,7 +92,8 @@ static void TestFunction(int thread_salt, SpinLock* spinlock) {
static void ThreadedTest(SpinLock* spinlock) {
std::vector<std::thread> threads;
- for (int i = 0; i < kNumThreads; ++i) {
+ threads.reserve(kNumThreads);
+ for (uint32_t i = 0; i < kNumThreads; ++i) {
threads.push_back(std::thread(TestFunction, i, spinlock));
}
for (auto& thread : threads) {
@@ -100,7 +101,7 @@ static void ThreadedTest(SpinLock* spinlock) {
}
SpinLockHolder h(spinlock);
- for (int i = 1; i < kArrayLength; i++) {
+ for (size_t i = 1; i < kArrayLength; i++) {
EXPECT_EQ(values[0], values[i]);
}
}
@@ -132,28 +133,28 @@ TEST(SpinLock, WaitCyclesEncoding) {
// but the lower kProfileTimestampShift will be dropped.
const int kMaxCyclesShift =
32 - kLockwordReservedShift + kProfileTimestampShift;
- const uint64_t kMaxCycles = (int64_t{1} << kMaxCyclesShift) - 1;
+ const int64_t kMaxCycles = (int64_t{1} << kMaxCyclesShift) - 1;
// These bits should be zero after encoding.
const uint32_t kLockwordReservedMask = (1 << kLockwordReservedShift) - 1;
// These bits are dropped when wait cycles are encoded.
- const uint64_t kProfileTimestampMask = (1 << kProfileTimestampShift) - 1;
+ const int64_t kProfileTimestampMask = (1 << kProfileTimestampShift) - 1;
// Test a bunch of random values
std::default_random_engine generator;
// Shift to avoid overflow below.
- std::uniform_int_distribution<uint64_t> time_distribution(
- 0, std::numeric_limits<uint64_t>::max() >> 4);
- std::uniform_int_distribution<uint64_t> cycle_distribution(0, kMaxCycles);
+ std::uniform_int_distribution<int64_t> time_distribution(
+ 0, std::numeric_limits<int64_t>::max() >> 3);
+ std::uniform_int_distribution<int64_t> cycle_distribution(0, kMaxCycles);
for (int i = 0; i < 100; i++) {
int64_t start_time = time_distribution(generator);
int64_t cycles = cycle_distribution(generator);
int64_t end_time = start_time + cycles;
uint32_t lock_value = SpinLockTest::EncodeWaitCycles(start_time, end_time);
- EXPECT_EQ(0, lock_value & kLockwordReservedMask);
- uint64_t decoded = SpinLockTest::DecodeWaitCycles(lock_value);
+ EXPECT_EQ(0u, lock_value & kLockwordReservedMask);
+ int64_t decoded = SpinLockTest::DecodeWaitCycles(lock_value);
EXPECT_EQ(0, decoded & kProfileTimestampMask);
EXPECT_EQ(cycles & ~kProfileTimestampMask, decoded);
}
@@ -177,21 +178,21 @@ TEST(SpinLock, WaitCyclesEncoding) {
// Test clamping
uint32_t max_value =
SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles);
- uint64_t max_value_decoded = SpinLockTest::DecodeWaitCycles(max_value);
- uint64_t expected_max_value_decoded = kMaxCycles & ~kProfileTimestampMask;
+ int64_t max_value_decoded = SpinLockTest::DecodeWaitCycles(max_value);
+ int64_t expected_max_value_decoded = kMaxCycles & ~kProfileTimestampMask;
EXPECT_EQ(expected_max_value_decoded, max_value_decoded);
const int64_t step = (1 << kProfileTimestampShift);
uint32_t after_max_value =
SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles + step);
- uint64_t after_max_value_decoded =
+ int64_t after_max_value_decoded =
SpinLockTest::DecodeWaitCycles(after_max_value);
EXPECT_EQ(expected_max_value_decoded, after_max_value_decoded);
uint32_t before_max_value = SpinLockTest::EncodeWaitCycles(
start_time, start_time + kMaxCycles - step);
- uint64_t before_max_value_decoded =
- SpinLockTest::DecodeWaitCycles(before_max_value);
+ int64_t before_max_value_decoded =
+ SpinLockTest::DecodeWaitCycles(before_max_value);
EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
}
diff --git a/abseil-cpp/absl/base/thread_annotations.h b/abseil-cpp/absl/base/thread_annotations.h
index e23fff1..bc8a620 100644
--- a/abseil-cpp/absl/base/thread_annotations.h
+++ b/abseil-cpp/absl/base/thread_annotations.h
@@ -154,8 +154,8 @@
// 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
+// Documents the locks that cannot be held by callers of this function, as they
+// might be acquired by this function (Abseil's `Mutex` locks are
// non-reentrant).
#if ABSL_HAVE_ATTRIBUTE(locks_excluded)
#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
@@ -317,7 +317,7 @@ namespace base_internal {
// Takes a reference to a guarded data member, and returns an unguarded
// reference.
-// Do not used this function directly, use ABSL_TS_UNCHECKED_READ instead.
+// Do not use this function directly, use ABSL_TS_UNCHECKED_READ instead.
template <typename T>
inline const T& ts_unchecked_read(const T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS {
return v;
diff --git a/abseil-cpp/absl/base/throw_delegate_test.cc b/abseil-cpp/absl/base/throw_delegate_test.cc
index 5ba4ce5..e74362b 100644
--- a/abseil-cpp/absl/base/throw_delegate_test.cc
+++ b/abseil-cpp/absl/base/throw_delegate_test.cc
@@ -78,29 +78,97 @@ void ExpectThrowNoWhat(void (*f)()) {
#endif
}
-TEST(ThrowHelper, Test) {
- // Not using EXPECT_THROW because we want to check the .what() message too.
+TEST(ThrowDelegate, ThrowStdLogicErrorChar) {
ExpectThrowChar<std::logic_error>(ThrowStdLogicError);
+}
+
+TEST(ThrowDelegate, ThrowStdInvalidArgumentChar) {
ExpectThrowChar<std::invalid_argument>(ThrowStdInvalidArgument);
+}
+
+TEST(ThrowDelegate, ThrowStdDomainErrorChar) {
ExpectThrowChar<std::domain_error>(ThrowStdDomainError);
+}
+
+TEST(ThrowDelegate, ThrowStdLengthErrorChar) {
ExpectThrowChar<std::length_error>(ThrowStdLengthError);
+}
+
+TEST(ThrowDelegate, ThrowStdOutOfRangeChar) {
ExpectThrowChar<std::out_of_range>(ThrowStdOutOfRange);
+}
+
+TEST(ThrowDelegate, ThrowStdRuntimeErrorChar) {
ExpectThrowChar<std::runtime_error>(ThrowStdRuntimeError);
+}
+
+TEST(ThrowDelegate, ThrowStdRangeErrorChar) {
ExpectThrowChar<std::range_error>(ThrowStdRangeError);
+}
+
+TEST(ThrowDelegate, ThrowStdOverflowErrorChar) {
ExpectThrowChar<std::overflow_error>(ThrowStdOverflowError);
+}
+
+TEST(ThrowDelegate, ThrowStdUnderflowErrorChar) {
ExpectThrowChar<std::underflow_error>(ThrowStdUnderflowError);
+}
+TEST(ThrowDelegate, ThrowStdLogicErrorString) {
ExpectThrowString<std::logic_error>(ThrowStdLogicError);
+}
+
+TEST(ThrowDelegate, ThrowStdInvalidArgumentString) {
ExpectThrowString<std::invalid_argument>(ThrowStdInvalidArgument);
+}
+
+TEST(ThrowDelegate, ThrowStdDomainErrorString) {
ExpectThrowString<std::domain_error>(ThrowStdDomainError);
+}
+
+TEST(ThrowDelegate, ThrowStdLengthErrorString) {
ExpectThrowString<std::length_error>(ThrowStdLengthError);
+}
+
+TEST(ThrowDelegate, ThrowStdOutOfRangeString) {
ExpectThrowString<std::out_of_range>(ThrowStdOutOfRange);
+}
+
+TEST(ThrowDelegate, ThrowStdRuntimeErrorString) {
ExpectThrowString<std::runtime_error>(ThrowStdRuntimeError);
+}
+
+TEST(ThrowDelegate, ThrowStdRangeErrorString) {
ExpectThrowString<std::range_error>(ThrowStdRangeError);
+}
+
+TEST(ThrowDelegate, ThrowStdOverflowErrorString) {
ExpectThrowString<std::overflow_error>(ThrowStdOverflowError);
+}
+
+TEST(ThrowDelegate, ThrowStdUnderflowErrorString) {
ExpectThrowString<std::underflow_error>(ThrowStdUnderflowError);
+}
+
+TEST(ThrowDelegate, ThrowStdBadFunctionCallNoWhat) {
+#ifdef ABSL_HAVE_EXCEPTIONS
+ try {
+ ThrowStdBadFunctionCall();
+ FAIL() << "Didn't throw";
+ } catch (const std::bad_function_call&) {
+ }
+#ifdef _LIBCPP_VERSION
+ catch (const std::exception&) {
+ // https://reviews.llvm.org/D92397 causes issues with the vtable for
+ // std::bad_function_call when using libc++ as a shared library.
+ }
+#endif
+#else
+ EXPECT_DEATH_IF_SUPPORTED(ThrowStdBadFunctionCall(), "");
+#endif
+}
- ExpectThrowNoWhat<std::bad_function_call>(ThrowStdBadFunctionCall);
+TEST(ThrowDelegate, ThrowStdBadAllocNoWhat) {
ExpectThrowNoWhat<std::bad_alloc>(ThrowStdBadAlloc);
}