Update webrtc's abseil-cpp
Copy external/abseil-cpp into webrtc to update to version 20211102.0 to pick up changes that fix compiling against musl libc. Bug: 190084016 Test: m USE_HOST_MUSL=true host-native Test: m checkbuild Change-Id: I0ab600cd8db93a55eda8358cdbecd21c2f78d8fb
This commit is contained in:
41
third_party/abseil-cpp/.github/ISSUE_TEMPLATE/00-bug_report.md
vendored
Normal file
41
third_party/abseil-cpp/.github/ISSUE_TEMPLATE/00-bug_report.md
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
|
||||
Include a clear and concise description of what the problem is, including what
|
||||
you expected to happen, and what actually happened.
|
||||
|
||||
**Steps to reproduce the bug**
|
||||
|
||||
It's important that we are able to reproduce the problem that you are
|
||||
experiencing. Please provide all code and relevant steps to reproduce the
|
||||
problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links
|
||||
to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the
|
||||
problem are also helpful.
|
||||
|
||||
**What version of Abseil are you using?**
|
||||
|
||||
**What operating system and version are you using**
|
||||
|
||||
If you are using a Linux distribution please include the name and version of the
|
||||
distribution as well.
|
||||
|
||||
**What compiler and version are you using?**
|
||||
|
||||
Please include the output of `gcc -v` or `clang -v`, or the equivalent for your
|
||||
compiler.
|
||||
|
||||
**What build system are you using?**
|
||||
|
||||
Please include the output of `bazel --version` or `cmake --version`, or the
|
||||
equivalent for your build system.
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context about the problem here.
|
||||
7
third_party/abseil-cpp/.github/ISSUE_TEMPLATE/90-question.md
vendored
Normal file
7
third_party/abseil-cpp/.github/ISSUE_TEMPLATE/90-question.md
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Question
|
||||
about: Have a question? Ask us anything! :-)
|
||||
title: ''
|
||||
labels: 'question'
|
||||
assignees: ''
|
||||
---
|
||||
1
third_party/abseil-cpp/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
third_party/abseil-cpp/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
blank_issues_enabled: true
|
||||
29
third_party/abseil-cpp/Android.bp
vendored
29
third_party/abseil-cpp/Android.bp
vendored
@ -54,14 +54,12 @@ cc_library_host_static {
|
||||
name: "libwebrtc_absl_base",
|
||||
defaults: ["libwebrtc_absl_defaults"],
|
||||
srcs: [
|
||||
"absl/base/dynamic_annotations.cc",
|
||||
"absl/base/internal/cycleclock.cc",
|
||||
"absl/base/internal/exponential_biased.cc",
|
||||
"absl/base/internal/low_level_alloc.cc",
|
||||
"absl/base/internal/periodic_sampler.cc",
|
||||
"absl/base/internal/raw_logging.cc",
|
||||
"absl/base/internal/spinlock.cc",
|
||||
"absl/base/internal/spinlock_wait.cc",
|
||||
"absl/base/internal/strerror.cc",
|
||||
"absl/base/internal/sysinfo.cc",
|
||||
"absl/base/internal/thread_identity.cc",
|
||||
"absl/base/internal/throw_delegate.cc",
|
||||
@ -102,17 +100,19 @@ cc_library_host_static {
|
||||
name: "libwebrtc_absl_flags",
|
||||
defaults: ["libwebrtc_absl_defaults"],
|
||||
srcs: [
|
||||
"absl/flags/commandlineflag.cc",
|
||||
"absl/flags/usage_config.cc",
|
||||
"absl/flags/marshalling.cc",
|
||||
"absl/flags/usage.cc",
|
||||
"absl/flags/flag.cc",
|
||||
"absl/flags/parse.cc",
|
||||
"absl/flags/internal/commandlineflag.cc",
|
||||
"absl/flags/internal/flag.cc",
|
||||
"absl/flags/internal/private_handle_accessor.cc",
|
||||
"absl/flags/internal/program_name.cc",
|
||||
"absl/flags/internal/registry.cc",
|
||||
"absl/flags/internal/usage.cc",
|
||||
"absl/flags/internal/type_erased.cc",
|
||||
"absl/flags/flag_test_defs.cc",
|
||||
"absl/flags/reflection.cc",
|
||||
],
|
||||
}
|
||||
|
||||
@ -122,6 +122,7 @@ cc_library_host_static {
|
||||
srcs: [
|
||||
"absl/hash/internal/city.cc",
|
||||
"absl/hash/internal/hash.cc",
|
||||
"absl/hash/internal/low_level_hash.cc",
|
||||
],
|
||||
}
|
||||
|
||||
@ -131,12 +132,21 @@ cc_library_host_static {
|
||||
srcs: ["absl/numeric/int128.cc"],
|
||||
}
|
||||
|
||||
cc_library_host_static {
|
||||
name: "libwebrtc_absl_profiling",
|
||||
srcs: [
|
||||
"absl/profiling/internal/exponential_biased.cc",
|
||||
"absl/profiling/internal/periodic_sampler.cc",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_host_static {
|
||||
name: "libwebrtc_absl_status",
|
||||
defaults: ["libwebrtc_absl_defaults"],
|
||||
srcs: [
|
||||
"absl/status/status.cc",
|
||||
"absl/status/status_payload_printer.cc",
|
||||
"absl/status/statusor.cc",
|
||||
],
|
||||
}
|
||||
|
||||
@ -150,6 +160,15 @@ cc_library_host_static {
|
||||
"absl/strings/escaping.cc",
|
||||
"absl/strings/internal/charconv_bigint.cc",
|
||||
"absl/strings/internal/charconv_parse.cc",
|
||||
"absl/strings/internal/cord_internal.cc",
|
||||
"absl/strings/internal/cord_rep_btree.cc",
|
||||
"absl/strings/internal/cord_rep_btree_navigator.cc",
|
||||
"absl/strings/internal/cord_rep_btree_reader.cc",
|
||||
"absl/strings/internal/cord_rep_consume.cc",
|
||||
"absl/strings/internal/cord_rep_ring.cc",
|
||||
"absl/strings/internal/cordz_functions.cc",
|
||||
"absl/strings/internal/cordz_handle.cc",
|
||||
"absl/strings/internal/cordz_info.cc",
|
||||
"absl/strings/internal/escaping.cc",
|
||||
"absl/strings/internal/memutil.cc",
|
||||
"absl/strings/internal/ostringstream.cc",
|
||||
|
||||
25
third_party/abseil-cpp/BUILD.bazel
vendored
Normal file
25
third_party/abseil-cpp/BUILD.bazel
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright 2020 The Abseil Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
# Expose license for external usage through bazel.
|
||||
exports_files([
|
||||
"AUTHORS",
|
||||
"LICENSE",
|
||||
])
|
||||
73
third_party/abseil-cpp/CMake/AbseilDll.cmake
vendored
73
third_party/abseil-cpp/CMake/AbseilDll.cmake
vendored
@ -1,4 +1,5 @@
|
||||
include(CMakeParseArguments)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(ABSL_INTERNAL_DLL_FILES
|
||||
"algorithm/algorithm.h"
|
||||
@ -8,17 +9,15 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"base/casts.h"
|
||||
"base/config.h"
|
||||
"base/const_init.h"
|
||||
"base/dynamic_annotations.cc"
|
||||
"base/dynamic_annotations.h"
|
||||
"base/internal/atomic_hook.h"
|
||||
"base/internal/bits.h"
|
||||
"base/internal/cycleclock.cc"
|
||||
"base/internal/cycleclock.h"
|
||||
"base/internal/direct_mmap.h"
|
||||
"base/internal/dynamic_annotations.h"
|
||||
"base/internal/endian.h"
|
||||
"base/internal/errno_saver.h"
|
||||
"base/internal/exponential_biased.cc"
|
||||
"base/internal/exponential_biased.h"
|
||||
"base/internal/fast_type_id.h"
|
||||
"base/internal/hide_ptr.h"
|
||||
"base/internal/identity.h"
|
||||
"base/internal/invoke.h"
|
||||
@ -27,14 +26,14 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"base/internal/low_level_alloc.h"
|
||||
"base/internal/low_level_scheduling.h"
|
||||
"base/internal/per_thread_tls.h"
|
||||
"base/internal/periodic_sampler.cc"
|
||||
"base/internal/periodic_sampler.h"
|
||||
"base/internal/pretty_function.h"
|
||||
"base/internal/raw_logging.cc"
|
||||
"base/internal/raw_logging.h"
|
||||
"base/internal/scheduling_mode.h"
|
||||
"base/internal/scoped_set_env.cc"
|
||||
"base/internal/scoped_set_env.h"
|
||||
"base/internal/strerror.h"
|
||||
"base/internal/strerror.cc"
|
||||
"base/internal/spinlock.cc"
|
||||
"base/internal/spinlock.h"
|
||||
"base/internal/spinlock_wait.cc"
|
||||
@ -58,6 +57,8 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"base/policy_checks.h"
|
||||
"base/port.h"
|
||||
"base/thread_annotations.h"
|
||||
"cleanup/cleanup.h"
|
||||
"cleanup/internal/cleanup.h"
|
||||
"container/btree_map.h"
|
||||
"container/btree_set.h"
|
||||
"container/fixed_array.h"
|
||||
@ -119,27 +120,35 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"hash/internal/hash.h"
|
||||
"hash/internal/hash.cc"
|
||||
"hash/internal/spy_hash_state.h"
|
||||
"hash/internal/low_level_hash.h"
|
||||
"hash/internal/low_level_hash.cc"
|
||||
"memory/memory.h"
|
||||
"meta/type_traits.h"
|
||||
"numeric/bits.h"
|
||||
"numeric/int128.cc"
|
||||
"numeric/int128.h"
|
||||
"numeric/internal/bits.h"
|
||||
"numeric/internal/representation.h"
|
||||
"profiling/internal/exponential_biased.cc"
|
||||
"profiling/internal/exponential_biased.h"
|
||||
"profiling/internal/periodic_sampler.cc"
|
||||
"profiling/internal/periodic_sampler.h"
|
||||
"profiling/internal/sample_recorder.h"
|
||||
"random/bernoulli_distribution.h"
|
||||
"random/beta_distribution.h"
|
||||
"random/bit_gen_ref.h"
|
||||
"random/discrete_distribution.cc"
|
||||
"random/discrete_distribution.h"
|
||||
"random/distribution_format_traits.h"
|
||||
"random/distributions.h"
|
||||
"random/exponential_distribution.h"
|
||||
"random/gaussian_distribution.cc"
|
||||
"random/gaussian_distribution.h"
|
||||
"random/internal/distributions.h"
|
||||
"random/internal/distribution_caller.h"
|
||||
"random/internal/fast_uniform_bits.h"
|
||||
"random/internal/fastmath.h"
|
||||
"random/internal/gaussian_distribution_gentables.cc"
|
||||
"random/internal/fast_uniform_bits.h"
|
||||
"random/internal/generate_real.h"
|
||||
"random/internal/iostream_state_saver.h"
|
||||
"random/internal/mock_helpers.h"
|
||||
"random/internal/nonsecure_base.h"
|
||||
"random/internal/pcg_engine.h"
|
||||
"random/internal/platform.h"
|
||||
@ -152,6 +161,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"random/internal/randen_engine.h"
|
||||
"random/internal/randen_hwaes.cc"
|
||||
"random/internal/randen_hwaes.h"
|
||||
"random/internal/randen_round_keys.cc"
|
||||
"random/internal/randen_slow.cc"
|
||||
"random/internal/randen_slow.h"
|
||||
"random/internal/randen_traits.h"
|
||||
@ -172,8 +182,12 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"random/uniform_int_distribution.h"
|
||||
"random/uniform_real_distribution.h"
|
||||
"random/zipf_distribution.h"
|
||||
"status/internal/status_internal.h"
|
||||
"status/internal/statusor_internal.h"
|
||||
"status/status.h"
|
||||
"status/status.cc"
|
||||
"status/statusor.h"
|
||||
"status/statusor.cc"
|
||||
"status/status_payload_printer.h"
|
||||
"status/status_payload_printer.cc"
|
||||
"strings/ascii.cc"
|
||||
@ -184,12 +198,37 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"strings/cord.h"
|
||||
"strings/escaping.cc"
|
||||
"strings/escaping.h"
|
||||
"strings/internal/cord_internal.h"
|
||||
"strings/internal/charconv_bigint.cc"
|
||||
"strings/internal/charconv_bigint.h"
|
||||
"strings/internal/charconv_parse.cc"
|
||||
"strings/internal/charconv_parse.h"
|
||||
"strings/internal/cord_internal.cc"
|
||||
"strings/internal/cord_internal.h"
|
||||
"strings/internal/cord_rep_consume.h"
|
||||
"strings/internal/cord_rep_consume.cc"
|
||||
"strings/internal/cord_rep_btree.cc"
|
||||
"strings/internal/cord_rep_btree.h"
|
||||
"strings/internal/cord_rep_btree_navigator.cc"
|
||||
"strings/internal/cord_rep_btree_navigator.h"
|
||||
"strings/internal/cord_rep_btree_reader.cc"
|
||||
"strings/internal/cord_rep_btree_reader.h"
|
||||
"strings/internal/cord_rep_flat.h"
|
||||
"strings/internal/cord_rep_ring.cc"
|
||||
"strings/internal/cord_rep_ring.h"
|
||||
"strings/internal/cord_rep_ring_reader.h"
|
||||
"strings/internal/cordz_functions.cc"
|
||||
"strings/internal/cordz_functions.h"
|
||||
"strings/internal/cordz_handle.cc"
|
||||
"strings/internal/cordz_handle.h"
|
||||
"strings/internal/cordz_info.cc"
|
||||
"strings/internal/cordz_info.h"
|
||||
"strings/internal/cordz_sample_token.cc"
|
||||
"strings/internal/cordz_sample_token.h"
|
||||
"strings/internal/cordz_statistics.h"
|
||||
"strings/internal/cordz_update_scope.h"
|
||||
"strings/internal/cordz_update_tracker.h"
|
||||
"strings/internal/stl_type_traits.h"
|
||||
"strings/internal/string_constant.h"
|
||||
"strings/match.cc"
|
||||
"strings/match.h"
|
||||
"strings/numbers.cc"
|
||||
@ -244,6 +283,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"synchronization/notification.h"
|
||||
"synchronization/internal/create_thread_identity.cc"
|
||||
"synchronization/internal/create_thread_identity.h"
|
||||
"synchronization/internal/futex.h"
|
||||
"synchronization/internal/graphcycles.cc"
|
||||
"synchronization/internal/graphcycles.h"
|
||||
"synchronization/internal/kernel_timeout.h"
|
||||
@ -292,6 +332,8 @@ set(ABSL_INTERNAL_DLL_FILES
|
||||
"types/internal/conformance_aliases.h"
|
||||
"types/internal/conformance_archetype.h"
|
||||
"types/internal/conformance_profile.h"
|
||||
"types/internal/parentheses.h"
|
||||
"types/internal/transform_args.h"
|
||||
"types/internal/variant.h"
|
||||
"types/optional.h"
|
||||
"types/internal/optional.h"
|
||||
@ -416,6 +458,7 @@ set(ABSL_INTERNAL_DLL_TARGETS
|
||||
"raw_hash_set"
|
||||
"layout"
|
||||
"tracked"
|
||||
"sample_recorder"
|
||||
)
|
||||
|
||||
function(absl_internal_dll_contains)
|
||||
@ -479,7 +522,7 @@ function(absl_make_dll)
|
||||
abseil_dll
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
|
||||
$<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
@ -497,8 +540,8 @@ function(absl_make_dll)
|
||||
${ABSL_CC_LIB_DEFINES}
|
||||
)
|
||||
install(TARGETS abseil_dll EXPORT ${PROJECT_NAME}Targets
|
||||
RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
135
third_party/abseil-cpp/CMake/AbseilHelpers.cmake
vendored
135
third_party/abseil-cpp/CMake/AbseilHelpers.cmake
vendored
@ -17,13 +17,14 @@
|
||||
include(CMakeParseArguments)
|
||||
include(AbseilConfigureCopts)
|
||||
include(AbseilDll)
|
||||
include(AbseilInstallDirs)
|
||||
|
||||
# The IDE folder for Abseil that will be used if Abseil is included in a CMake
|
||||
# project that sets
|
||||
# set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
# For example, Visual Studio supports folders.
|
||||
set(ABSL_IDE_FOLDER Abseil)
|
||||
if(NOT DEFINED ABSL_IDE_FOLDER)
|
||||
set(ABSL_IDE_FOLDER Abseil)
|
||||
endif()
|
||||
|
||||
# absl_cc_library()
|
||||
#
|
||||
@ -39,7 +40,7 @@ set(ABSL_IDE_FOLDER Abseil)
|
||||
# LINKOPTS: List of link options
|
||||
# PUBLIC: Add this so that this library will be exported under absl::
|
||||
# Also in IDE, target will appear in Abseil folder while non PUBLIC will be in Abseil/internal.
|
||||
# TESTONLY: When added, this target will only be built if user passes -DABSL_RUN_TESTS=ON to CMake.
|
||||
# TESTONLY: When added, this target will only be built if BUILD_TESTING=ON.
|
||||
#
|
||||
# Note:
|
||||
# By default, absl_cc_library will always create a library named absl_${NAME},
|
||||
@ -81,7 +82,7 @@ function(absl_cc_library)
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
if(ABSL_CC_LIB_TESTONLY AND NOT ABSL_RUN_TESTS)
|
||||
if(ABSL_CC_LIB_TESTONLY AND NOT BUILD_TESTING)
|
||||
return()
|
||||
endif()
|
||||
|
||||
@ -102,7 +103,7 @@ function(absl_cc_library)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if("${ABSL_CC_SRCS}" STREQUAL "")
|
||||
if(ABSL_CC_SRCS STREQUAL "")
|
||||
set(ABSL_CC_LIB_IS_INTERFACE 1)
|
||||
else()
|
||||
set(ABSL_CC_LIB_IS_INTERFACE 0)
|
||||
@ -120,7 +121,11 @@ function(absl_cc_library)
|
||||
# 4. "static" -- This target does not depend on the DLL and should be built
|
||||
# statically.
|
||||
if (${ABSL_BUILD_DLL})
|
||||
absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll)
|
||||
if(ABSL_ENABLE_INSTALL)
|
||||
absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll)
|
||||
else()
|
||||
absl_internal_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_dll)
|
||||
endif()
|
||||
if (${_in_dll})
|
||||
# This target should be replaced by the DLL
|
||||
set(_build_type "dll")
|
||||
@ -135,8 +140,54 @@ function(absl_cc_library)
|
||||
set(_build_type "static")
|
||||
endif()
|
||||
|
||||
# Generate a pkg-config file for every library:
|
||||
if((_build_type STREQUAL "static" OR _build_type STREQUAL "shared")
|
||||
AND ABSL_ENABLE_INSTALL)
|
||||
if(NOT ABSL_CC_LIB_TESTONLY)
|
||||
if(absl_VERSION)
|
||||
set(PC_VERSION "${absl_VERSION}")
|
||||
else()
|
||||
set(PC_VERSION "head")
|
||||
endif()
|
||||
foreach(dep ${ABSL_CC_LIB_DEPS})
|
||||
if(${dep} MATCHES "^absl::(.*)")
|
||||
# Join deps with commas.
|
||||
if(PC_DEPS)
|
||||
set(PC_DEPS "${PC_DEPS},")
|
||||
endif()
|
||||
set(PC_DEPS "${PC_DEPS} absl_${CMAKE_MATCH_1} = ${PC_VERSION}")
|
||||
endif()
|
||||
endforeach()
|
||||
foreach(cflag ${ABSL_CC_LIB_COPTS})
|
||||
if(${cflag} MATCHES "^(-Wno|/wd)")
|
||||
# These flags are needed to suppress warnings that might fire in our headers.
|
||||
set(PC_CFLAGS "${PC_CFLAGS} ${cflag}")
|
||||
elseif(${cflag} MATCHES "^(-W|/w[1234eo])")
|
||||
# Don't impose our warnings on others.
|
||||
else()
|
||||
set(PC_CFLAGS "${PC_CFLAGS} ${cflag}")
|
||||
endif()
|
||||
endforeach()
|
||||
FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" CONTENT "\
|
||||
prefix=${CMAKE_INSTALL_PREFIX}\n\
|
||||
exec_prefix=\${prefix}\n\
|
||||
libdir=${CMAKE_INSTALL_FULL_LIBDIR}\n\
|
||||
includedir=${CMAKE_INSTALL_FULL_INCLUDEDIR}\n\
|
||||
\n\
|
||||
Name: absl_${_NAME}\n\
|
||||
Description: Abseil ${_NAME} library\n\
|
||||
URL: https://abseil.io/\n\
|
||||
Version: ${PC_VERSION}\n\
|
||||
Requires:${PC_DEPS}\n\
|
||||
Libs: -L\${libdir} $<JOIN:${ABSL_CC_LIB_LINKOPTS}, > $<$<NOT:$<BOOL:${ABSL_CC_LIB_IS_INTERFACE}>>:-labsl_${_NAME}>\n\
|
||||
Cflags: -I\${includedir}${PC_CFLAGS}\n")
|
||||
INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT ABSL_CC_LIB_IS_INTERFACE)
|
||||
if(${_build_type} STREQUAL "dll_dep")
|
||||
if(_build_type STREQUAL "dll_dep")
|
||||
# This target depends on the DLL. When adding dependencies to this target,
|
||||
# any depended-on-target which is contained inside the DLL is replaced
|
||||
# with a dependency on the DLL.
|
||||
@ -165,7 +216,7 @@ function(absl_cc_library)
|
||||
"${_gtest_link_define}"
|
||||
)
|
||||
|
||||
elseif(${_build_type} STREQUAL "static" OR ${_build_type} STREQUAL "shared")
|
||||
elseif(_build_type STREQUAL "static" OR _build_type STREQUAL "shared")
|
||||
add_library(${_NAME} "")
|
||||
target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
|
||||
target_link_libraries(${_NAME}
|
||||
@ -188,7 +239,7 @@ function(absl_cc_library)
|
||||
target_include_directories(${_NAME}
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
|
||||
$<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
target_compile_options(${_NAME}
|
||||
PRIVATE ${ABSL_CC_LIB_COPTS})
|
||||
@ -203,9 +254,23 @@ function(absl_cc_library)
|
||||
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)
|
||||
endif()
|
||||
|
||||
# INTERFACE libraries can't have the CXX_STANDARD property set
|
||||
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
|
||||
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
if(ABSL_PROPAGATE_CXX_STD)
|
||||
# Abseil libraries require C++11 as the current minimum standard.
|
||||
# Top-level application CMake projects should ensure a consistent C++
|
||||
# standard for all compiled sources by setting CMAKE_CXX_STANDARD.
|
||||
target_compile_features(${_NAME} PUBLIC cxx_std_11)
|
||||
else()
|
||||
# Note: This is legacy (before CMake 3.8) behavior. Setting the
|
||||
# target-level CXX_STANDARD property to ABSL_CXX_STANDARD (which is
|
||||
# initialized by CMAKE_CXX_STANDARD) should have no real effect, since
|
||||
# that is the default value anyway.
|
||||
#
|
||||
# CXX_STANDARD_REQUIRED does guard against the top-level CMake project
|
||||
# not having enabled CMAKE_CXX_STANDARD_REQUIRED (which prevents
|
||||
# "decaying" to an older standard if the requested one isn't available).
|
||||
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
|
||||
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
# When being installed, we lose the absl_ prefix. We want to put it back
|
||||
# to have properly named lib files. This is a no-op when we are not being
|
||||
@ -213,6 +278,7 @@ function(absl_cc_library)
|
||||
if(ABSL_ENABLE_INSTALL)
|
||||
set_target_properties(${_NAME} PROPERTIES
|
||||
OUTPUT_NAME "absl_${_NAME}"
|
||||
SOVERSION "2111.0.0"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
@ -221,10 +287,10 @@ function(absl_cc_library)
|
||||
target_include_directories(${_NAME}
|
||||
INTERFACE
|
||||
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
|
||||
$<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
if (${_build_type} STREQUAL "dll")
|
||||
if (_build_type STREQUAL "dll")
|
||||
set(ABSL_CC_LIB_DEPS abseil_dll)
|
||||
endif()
|
||||
|
||||
@ -235,15 +301,25 @@ function(absl_cc_library)
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
)
|
||||
target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
|
||||
|
||||
if(ABSL_PROPAGATE_CXX_STD)
|
||||
# Abseil libraries require C++11 as the current minimum standard.
|
||||
# Top-level application CMake projects should ensure a consistent C++
|
||||
# standard for all compiled sources by setting CMAKE_CXX_STANDARD.
|
||||
target_compile_features(${_NAME} INTERFACE cxx_std_11)
|
||||
|
||||
# (INTERFACE libraries can't have the CXX_STANDARD property set, so there
|
||||
# is no legacy behavior else case).
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# TODO currently we don't install googletest alongside abseil sources, so
|
||||
# installed abseil can't be tested.
|
||||
if(NOT ABSL_CC_LIB_TESTONLY AND ABSL_ENABLE_INSTALL)
|
||||
install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets
|
||||
RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -284,11 +360,11 @@ endfunction()
|
||||
# "awesome_test.cc"
|
||||
# DEPS
|
||||
# absl::awesome
|
||||
# gmock
|
||||
# gtest_main
|
||||
# GTest::gmock
|
||||
# GTest::gtest_main
|
||||
# )
|
||||
function(absl_cc_test)
|
||||
if(NOT ABSL_RUN_TESTS)
|
||||
if(NOT BUILD_TESTING)
|
||||
return()
|
||||
endif()
|
||||
|
||||
@ -338,8 +414,23 @@ function(absl_cc_test)
|
||||
# Add all Abseil targets to a folder in the IDE for organization.
|
||||
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
|
||||
|
||||
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
|
||||
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
if(ABSL_PROPAGATE_CXX_STD)
|
||||
# Abseil libraries require C++11 as the current minimum standard.
|
||||
# Top-level application CMake projects should ensure a consistent C++
|
||||
# standard for all compiled sources by setting CMAKE_CXX_STANDARD.
|
||||
target_compile_features(${_NAME} PUBLIC cxx_std_11)
|
||||
else()
|
||||
# Note: This is legacy (before CMake 3.8) behavior. Setting the
|
||||
# target-level CXX_STANDARD property to ABSL_CXX_STANDARD (which is
|
||||
# initialized by CMAKE_CXX_STANDARD) should have no real effect, since
|
||||
# that is the default value anyway.
|
||||
#
|
||||
# CXX_STANDARD_REQUIRED does guard against the top-level CMake project
|
||||
# not having enabled CMAKE_CXX_STANDARD_REQUIRED (which prevents
|
||||
# "decaying" to an older standard if the requested one isn't available).
|
||||
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
|
||||
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
add_test(NAME ${_NAME} COMMAND ${_NAME})
|
||||
endfunction()
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# absl_VERSION is only set if we are an LTS release being installed, in which
|
||||
# case it may be into a system directory and so we need to make subdirectories
|
||||
# for each installed version of Abseil. This mechanism is implemented in
|
||||
# Abseil's internal Copybara (https://github.com/google/copybara) workflows and
|
||||
# isn't visible in the CMake buildsystem itself.
|
||||
|
||||
if(absl_VERSION)
|
||||
set(ABSL_SUBDIR "${PROJECT_NAME}_${PROJECT_VERSION}")
|
||||
set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}/${ABSL_SUBDIR}")
|
||||
set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${ABSL_SUBDIR}")
|
||||
set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/{ABSL_SUBDIR}")
|
||||
set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}/${ABSL_SUBDIR}")
|
||||
else()
|
||||
set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}")
|
||||
set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
@ -1,15 +1,14 @@
|
||||
cmake_minimum_required(VERSION 2.8.2)
|
||||
|
||||
project(googletest-download NONE)
|
||||
project(googletest-external NONE)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG master
|
||||
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
|
||||
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
|
||||
URL "${absl_gtest_download_url}" # May be empty
|
||||
SOURCE_DIR "${absl_gtest_src_dir}"
|
||||
BINARY_DIR "${absl_gtest_build_dir}"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
)
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
# Downloads and unpacks googletest at configure time. Based on the instructions
|
||||
# at https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project
|
||||
# Integrates googletest at configure time. Based on the instructions at
|
||||
# https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project
|
||||
|
||||
# Download the latest googletest from Github master
|
||||
# Set up the external googletest project, downloading the latest from Github
|
||||
# master if requested.
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in
|
||||
${CMAKE_BINARY_DIR}/googletest-download/CMakeLists.txt
|
||||
${CMAKE_BINARY_DIR}/googletest-external/CMakeLists.txt
|
||||
)
|
||||
|
||||
set(ABSL_SAVE_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
@ -14,17 +15,17 @@ if (BUILD_SHARED_LIBS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1")
|
||||
endif()
|
||||
|
||||
# Configure and build the downloaded googletest source
|
||||
# Configure and build the googletest source.
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external )
|
||||
if(result)
|
||||
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external)
|
||||
if(result)
|
||||
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||
endif()
|
||||
@ -37,6 +38,4 @@ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Add googletest directly to our build. This defines the gtest and gtest_main
|
||||
# targets.
|
||||
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
|
||||
${CMAKE_BINARY_DIR}/googletest-build
|
||||
EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(${absl_gtest_src_dir} ${absl_gtest_build_dir} EXCLUDE_FROM_ALL)
|
||||
|
||||
96
third_party/abseil-cpp/CMake/README.md
vendored
96
third_party/abseil-cpp/CMake/README.md
vendored
@ -34,15 +34,16 @@ to include Abseil directly in your CMake project.
|
||||
4. Add the **absl::** target you wish to use to the
|
||||
[`target_link_libraries()`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html)
|
||||
section of your executable or of your library.<br>
|
||||
Here is a short CMakeLists.txt example of a project file using Abseil.
|
||||
Here is a short CMakeLists.txt example of an application project using Abseil.
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(my_project)
|
||||
cmake_minimum_required(VERSION 3.8.2)
|
||||
project(my_app_project)
|
||||
|
||||
# Pick the C++ standard to compile with.
|
||||
# Abseil currently supports C++11, C++14, and C++17.
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_subdirectory(abseil-cpp)
|
||||
|
||||
@ -50,9 +51,47 @@ add_executable(my_exe source.cpp)
|
||||
target_link_libraries(my_exe absl::base absl::synchronization absl::strings)
|
||||
```
|
||||
|
||||
Note that if you are developing a library designed for use by other clients, you
|
||||
should instead leave `CMAKE_CXX_STANDARD` unset (or only set if being built as
|
||||
the current top-level CMake project) and configure the minimum required C++
|
||||
standard at the target level. If you require a later minimum C++ standard than
|
||||
Abseil does, it's a good idea to also enforce that `CMAKE_CXX_STANDARD` (which
|
||||
will control Abseil library targets) is set to at least that minimum. For
|
||||
example:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.8.2)
|
||||
project(my_lib_project)
|
||||
|
||||
# Leave C++ standard up to the root application, so set it only if this is the
|
||||
# current top-level CMake project.
|
||||
if(CMAKE_SOURCE_DIR STREQUAL my_lib_project_SOURCE_DIR)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
add_subdirectory(abseil-cpp)
|
||||
|
||||
add_library(my_lib source.cpp)
|
||||
target_link_libraries(my_lib absl::base absl::synchronization absl::strings)
|
||||
|
||||
# Enforce that my_lib requires C++17. Important to document for clients that they
|
||||
# must set CMAKE_CXX_STANDARD to 17 or higher for proper Abseil ABI compatibility
|
||||
# (since otherwise, Abseil library targets could be compiled with a lower C++
|
||||
# standard than my_lib).
|
||||
target_compile_features(my_lib PUBLIC cxx_std_17)
|
||||
if(CMAKE_CXX_STANDARD LESS 17)
|
||||
message(FATAL_ERROR
|
||||
"my_lib_project requires CMAKE_CXX_STANDARD >= 17 (got: ${CMAKE_CXX_STANDARD})")
|
||||
endif()
|
||||
```
|
||||
|
||||
Then the top-level application project that uses your library is responsible for
|
||||
setting a consistent `CMAKE_CXX_STANDARD` that is sufficiently high.
|
||||
|
||||
### Running Abseil Tests with CMake
|
||||
|
||||
Use the `-DABSL_RUN_TESTS=ON` flag to run Abseil tests. Note that if the `-DBUILD_TESTING=OFF` flag is passed then Abseil tests will not be run.
|
||||
Use the `-DBUILD_TESTING=ON` flag to run Abseil tests.
|
||||
|
||||
You will need to provide Abseil with a Googletest dependency. There are two
|
||||
options for how to do this:
|
||||
@ -70,7 +109,7 @@ For example, to run just the Abseil tests, you could use this script:
|
||||
cd path/to/abseil-cpp
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DABSL_USE_GOOGLETEST_HEAD=ON -DABSL_RUN_TESTS=ON ..
|
||||
cmake -DBUILD_TESTING=ON -DABSL_USE_GOOGLETEST_HEAD=ON ..
|
||||
make -j
|
||||
ctest
|
||||
```
|
||||
@ -93,9 +132,54 @@ absl::flags
|
||||
absl::memory
|
||||
absl::meta
|
||||
absl::numeric
|
||||
absl::random
|
||||
absl::random_random
|
||||
absl::strings
|
||||
absl::synchronization
|
||||
absl::time
|
||||
absl::utility
|
||||
```
|
||||
|
||||
## Traditional CMake Set-Up
|
||||
|
||||
For larger projects, it may make sense to use the traditional CMake set-up where you build and install projects separately.
|
||||
|
||||
First, you'd need to build and install Google Test:
|
||||
```
|
||||
cmake -S /source/googletest -B /build/googletest -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/installation/dir -DBUILD_GMOCK=ON
|
||||
cmake --build /build/googletest --target install
|
||||
```
|
||||
|
||||
Then you need to configure and build Abseil. Make sure you enable `ABSL_USE_EXTERNAL_GOOGLETEST` and `ABSL_FIND_GOOGLETEST`. You also need to enable `ABSL_ENABLE_INSTALL` so that you can install Abseil itself.
|
||||
```
|
||||
cmake -S /source/abseil-cpp -B /build/abseil-cpp -DCMAKE_PREFIX_PATH=/installation/dir -DCMAKE_INSTALL_PREFIX=/installation/dir -DABSL_ENABLE_INSTALL=ON -DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON
|
||||
cmake --build /temporary/build/abseil-cpp
|
||||
```
|
||||
|
||||
(`CMAKE_PREFIX_PATH` is where you already have Google Test installed; `CMAKE_INSTALL_PREFIX` is where you want to have Abseil installed; they can be different.)
|
||||
|
||||
Run the tests:
|
||||
```
|
||||
ctest --test-dir /temporary/build/abseil-cpp
|
||||
```
|
||||
|
||||
And finally install:
|
||||
```
|
||||
cmake --build /temporary/build/abseil-cpp --target install
|
||||
```
|
||||
|
||||
# CMake Option Synposis
|
||||
|
||||
## Enable Standard CMake Installation
|
||||
|
||||
`-DABSL_ENABLE_INSTALL=ON`
|
||||
|
||||
## Google Test Options
|
||||
|
||||
`-DBUILD_TESTING=ON` must be set to enable testing
|
||||
|
||||
- Have Abseil download and build Google Test for you: `-DABSL_USE_EXTERNAL_GOOGLETEST=OFF` (default)
|
||||
- Download and build latest Google Test: `-DABSL_USE_GOOGLETEST_HEAD=ON`
|
||||
- Download specific Google Test version (ZIP archive): `-DABSL_GOOGLETEST_DOWNLOAD_URL=https://.../version.zip`
|
||||
- Use Google Test from specific local directory: `-DABSL_LOCAL_GOOGLETEST_DIR=/path/to/googletest`
|
||||
- Use Google Test included elsewhere in your project: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON`
|
||||
- Use standard CMake `find_package(CTest)` to find installed Google Test: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON`
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
# absl CMake configuration file.
|
||||
|
||||
include(FindThreads)
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Threads)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
|
||||
@ -18,10 +18,8 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(absl_cmake_testing CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
add_executable(simple simple.cc)
|
||||
|
||||
find_package(absl REQUIRED)
|
||||
|
||||
target_link_libraries(simple absl::strings)
|
||||
target_link_libraries(simple absl::strings absl::config)
|
||||
|
||||
@ -14,8 +14,17 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <iostream>
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/strings/substitute.h"
|
||||
|
||||
#if !defined(ABSL_LTS_RELEASE_VERSION) || ABSL_LTS_RELEASE_VERSION != 99998877
|
||||
#error ABSL_LTS_RELEASE_VERSION is not set correctly.
|
||||
#endif
|
||||
|
||||
#if !defined(ABSL_LTS_RELEASE_PATCH_LEVEL) || ABSL_LTS_RELEASE_PATCH_LEVEL != 0
|
||||
#error ABSL_LTS_RELEASE_PATCH_LEVEL is not set correctly.
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
std::cout << absl::Substitute("Arg $0: $1\n", i, argv[i]);
|
||||
|
||||
164
third_party/abseil-cpp/CMake/install_test_project/test.sh
vendored
Normal file → Executable file
164
third_party/abseil-cpp/CMake/install_test_project/test.sh
vendored
Normal file → Executable file
@ -13,70 +13,60 @@
|
||||
# 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.
|
||||
|
||||
# "Unit" and integration tests for Absl CMake installation
|
||||
|
||||
# TODO(absl-team): This script isn't fully hermetic because
|
||||
# -DABSL_USE_GOOGLETEST_HEAD=ON means that this script isn't pinned to a fixed
|
||||
# version of GoogleTest. This means that an upstream change to GoogleTest could
|
||||
# break this test. Fix this by allowing this script to pin to a known-good
|
||||
# version of GoogleTest.
|
||||
#
|
||||
# Unit and integration tests for Abseil LTS CMake installation
|
||||
|
||||
# Fail on any error. Treat unset variables an error. Print commands as executed.
|
||||
set -euox pipefail
|
||||
|
||||
install_absl() {
|
||||
pushd "${absl_build_dir}"
|
||||
if [[ "${#}" -eq 1 ]]; then
|
||||
cmake -DCMAKE_INSTALL_PREFIX="${1}" "${absl_dir}"
|
||||
else
|
||||
cmake "${absl_dir}"
|
||||
fi
|
||||
cmake --build . --target install -- -j
|
||||
popd
|
||||
}
|
||||
|
||||
uninstall_absl() {
|
||||
xargs rm < "${absl_build_dir}"/install_manifest.txt
|
||||
rm -rf "${absl_build_dir}"
|
||||
mkdir -p "${absl_build_dir}"
|
||||
}
|
||||
|
||||
lts_install=""
|
||||
|
||||
while getopts ":l" lts; do
|
||||
case "${lts}" in
|
||||
l )
|
||||
lts_install="true"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
absl_dir=/abseil-cpp
|
||||
absl_build_dir=/buildfs/absl-build
|
||||
absl_build_dir=/buildfs
|
||||
googletest_builddir=/googletest_builddir
|
||||
project_dir="${absl_dir}"/CMake/install_test_project
|
||||
project_build_dir=/buildfs/project-build
|
||||
|
||||
mkdir -p "${absl_build_dir}"
|
||||
build_shared_libs="OFF"
|
||||
if [ "${LINK_TYPE:-}" = "DYNAMIC" ]; then
|
||||
build_shared_libs="ON"
|
||||
fi
|
||||
|
||||
# Build and install GoogleTest
|
||||
mkdir "${googletest_builddir}"
|
||||
pushd "${googletest_builddir}"
|
||||
curl -L "${ABSL_GOOGLETEST_DOWNLOAD_URL}" --output "${ABSL_GOOGLETEST_COMMIT}".zip
|
||||
unzip "${ABSL_GOOGLETEST_COMMIT}".zip
|
||||
pushd "googletest-${ABSL_GOOGLETEST_COMMIT}"
|
||||
mkdir build
|
||||
pushd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS="${build_shared_libs}" ..
|
||||
make -j $(nproc)
|
||||
make install
|
||||
ldconfig
|
||||
popd
|
||||
popd
|
||||
popd
|
||||
|
||||
# Run the LTS transformations
|
||||
./create_lts.py 99998877
|
||||
|
||||
# Build and install Abseil
|
||||
pushd "${absl_build_dir}"
|
||||
cmake "${absl_dir}" \
|
||||
-DABSL_USE_EXTERNAL_GOOGLETEST=ON \
|
||||
-DABSL_FIND_GOOGLETEST=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DBUILD_TESTING=ON \
|
||||
-DBUILD_SHARED_LIBS="${build_shared_libs}"
|
||||
make -j $(nproc)
|
||||
ctest -j $(nproc)
|
||||
make install
|
||||
ldconfig
|
||||
popd
|
||||
|
||||
# Test the project against the installed Abseil
|
||||
mkdir -p "${project_build_dir}"
|
||||
|
||||
if [[ "${lts_install}" ]]; then
|
||||
install_dir="/usr/local"
|
||||
else
|
||||
install_dir="${project_build_dir}"/install
|
||||
fi
|
||||
mkdir -p "${install_dir}"
|
||||
|
||||
# Test build, install, and link against installed abseil
|
||||
pushd "${project_build_dir}"
|
||||
if [[ "${lts_install}" ]]; then
|
||||
install_absl
|
||||
cmake "${project_dir}"
|
||||
else
|
||||
install_absl "${install_dir}"
|
||||
cmake "${project_dir}" -DCMAKE_PREFIX_PATH="${install_dir}"
|
||||
fi
|
||||
|
||||
cmake "${project_dir}"
|
||||
cmake --build . --target simple
|
||||
|
||||
output="$(${project_build_dir}/simple "printme" 2>&1)"
|
||||
@ -88,57 +78,35 @@ fi
|
||||
|
||||
popd
|
||||
|
||||
# Test that we haven't accidentally made absl::abslblah
|
||||
pushd "${install_dir}"
|
||||
|
||||
# Starting in CMake 3.12 the default install dir is lib$bit_width
|
||||
if [[ -d lib64 ]]; then
|
||||
libdir="lib64"
|
||||
elif [[ -d lib ]]; then
|
||||
libdir="lib"
|
||||
else
|
||||
echo "ls *, */*, */*/*:"
|
||||
ls *
|
||||
ls */*
|
||||
ls */*/*
|
||||
echo "unknown lib dir"
|
||||
fi
|
||||
|
||||
if [[ "${lts_install}" ]]; then
|
||||
# LTS versions append the date of the release to the subdir.
|
||||
# 9999/99/99 is the dummy date used in the local_lts workflow.
|
||||
absl_subdir="absl_99999999"
|
||||
else
|
||||
absl_subdir="absl"
|
||||
fi
|
||||
|
||||
if ! grep absl::strings "${libdir}/cmake/${absl_subdir}/abslTargets.cmake"; then
|
||||
cat "${libdir}"/cmake/absl/abslTargets.cmake
|
||||
if ! grep absl::strings "/usr/local/lib/cmake/absl/abslTargets.cmake"; then
|
||||
cat "/usr/local/lib/cmake/absl/abslTargets.cmake"
|
||||
echo "CMake targets named incorrectly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
uninstall_absl
|
||||
popd
|
||||
pushd "${HOME}"
|
||||
cat > hello-abseil.cc << EOF
|
||||
#include <cstdlib>
|
||||
|
||||
if [[ ! "${lts_install}" ]]; then
|
||||
# Test that we warn if installed without a prefix or a system prefix
|
||||
output="$(install_absl 2>&1)"
|
||||
if [[ "${output}" != *"Please set CMAKE_INSTALL_PREFIX"* ]]; then
|
||||
echo "Install without prefix didn't warn as expected. Output:"
|
||||
echo "${output}"
|
||||
exit 1
|
||||
fi
|
||||
uninstall_absl
|
||||
#include "absl/strings/str_format.h"
|
||||
|
||||
output="$(install_absl /usr 2>&1)"
|
||||
if [[ "${output}" != *"Please set CMAKE_INSTALL_PREFIX"* ]]; then
|
||||
echo "Install with /usr didn't warn as expected. Output:"
|
||||
echo "${output}"
|
||||
exit 1
|
||||
fi
|
||||
uninstall_absl
|
||||
int main(int argc, char **argv) {
|
||||
absl::PrintF("Hello Abseil!\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
EOF
|
||||
|
||||
if [ "${LINK_TYPE:-}" != "DYNAMIC" ]; then
|
||||
pc_args=($(pkg-config --cflags --libs --static absl_str_format))
|
||||
g++ -static -o hello-abseil hello-abseil.cc "${pc_args[@]}"
|
||||
else
|
||||
pc_args=($(pkg-config --cflags --libs absl_str_format))
|
||||
g++ -o hello-abseil hello-abseil.cc "${pc_args[@]}"
|
||||
fi
|
||||
hello="$(./hello-abseil)"
|
||||
[[ "${hello}" == "Hello Abseil!" ]]
|
||||
|
||||
popd
|
||||
|
||||
echo "Install test complete!"
|
||||
exit 0
|
||||
|
||||
135
third_party/abseil-cpp/CMakeLists.txt
vendored
135
third_party/abseil-cpp/CMakeLists.txt
vendored
@ -22,15 +22,36 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# Compiler id for Apple Clang is now AppleClang.
|
||||
cmake_policy(SET CMP0025 NEW)
|
||||
if (POLICY CMP0025)
|
||||
cmake_policy(SET CMP0025 NEW)
|
||||
endif (POLICY CMP0025)
|
||||
|
||||
# if command can use IN_LIST
|
||||
cmake_policy(SET CMP0057 NEW)
|
||||
if (POLICY CMP0057)
|
||||
cmake_policy(SET CMP0057 NEW)
|
||||
endif (POLICY CMP0057)
|
||||
|
||||
# Project version variables are the empty std::string if version is unspecified
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
# Project version variables are the empty string if version is unspecified
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
endif (POLICY CMP0048)
|
||||
|
||||
project(absl CXX)
|
||||
# option() honor variables
|
||||
if (POLICY CMP0077)
|
||||
cmake_policy(SET CMP0077 NEW)
|
||||
endif (POLICY CMP0077)
|
||||
|
||||
# Allow the user to specify the MSVC runtime
|
||||
if (POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif (POLICY CMP0091)
|
||||
|
||||
# Set BUILD_TESTING to OFF by default.
|
||||
# This must come before the project() and include(CTest) lines.
|
||||
OPTION(BUILD_TESTING "Build tests" OFF)
|
||||
|
||||
project(absl LANGUAGES CXX VERSION 20211102)
|
||||
include(CTest)
|
||||
|
||||
# Output directory is correct by default for most build setups. However, when
|
||||
# building Abseil as a DLL, it is important to have the DLL in the same
|
||||
@ -40,10 +61,17 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
# when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp))
|
||||
# in the source tree of a project that uses it, install rules are disabled.
|
||||
if(NOT "^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
|
||||
set(ABSL_ENABLE_INSTALL FALSE)
|
||||
if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
option(ABSL_ENABLE_INSTALL "Enable install rule" OFF)
|
||||
else()
|
||||
set(ABSL_ENABLE_INSTALL TRUE)
|
||||
option(ABSL_ENABLE_INSTALL "Enable install rule" ON)
|
||||
endif()
|
||||
|
||||
option(ABSL_PROPAGATE_CXX_STD
|
||||
"Use CMake C++ standard meta features (e.g. cxx_std_11) that propagate to targets that link to Abseil"
|
||||
OFF) # TODO: Default to ON for CMake 3.8 and greater.
|
||||
if((${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.8) AND (NOT ABSL_PROPAGATE_CXX_STD))
|
||||
message(WARNING "A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON for CMake 3.8 and up. We recommend enabling this option to ensure your project still builds correctly.")
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH
|
||||
@ -51,8 +79,8 @@ list(APPEND CMAKE_MODULE_PATH
|
||||
${CMAKE_CURRENT_LIST_DIR}/absl/copts
|
||||
)
|
||||
|
||||
include(AbseilInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
include(AbseilDll)
|
||||
include(AbseilHelpers)
|
||||
|
||||
@ -81,56 +109,87 @@ endif()
|
||||
## pthread
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
|
||||
option(ABSL_USE_EXTERNAL_GOOGLETEST
|
||||
"If ON, Abseil will assume that the targets for GoogleTest are already provided by the including project. This makes sense when Abseil is used with add_subproject." OFF)
|
||||
|
||||
cmake_dependent_option(ABSL_FIND_GOOGLETEST
|
||||
"If ON, Abseil will use find_package(GTest) rather than assuming that GoogleTest is already provided by the including project."
|
||||
ON
|
||||
"ABSL_USE_EXTERNAL_GOOGLETEST"
|
||||
OFF)
|
||||
|
||||
|
||||
option(ABSL_USE_GOOGLETEST_HEAD
|
||||
"If ON, abseil will download HEAD from googletest at config time." OFF)
|
||||
"If ON, abseil will download HEAD from GoogleTest at config time." OFF)
|
||||
|
||||
option(ABSL_RUN_TESTS "If ON, Abseil tests will be run." OFF)
|
||||
set(ABSL_GOOGLETEST_DOWNLOAD_URL "" CACHE STRING "If set, download GoogleTest from this URL")
|
||||
|
||||
if(${ABSL_RUN_TESTS})
|
||||
# enable CTest. This will set BUILD_TESTING to ON unless otherwise specified
|
||||
# on the command line
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
endif()
|
||||
set(ABSL_LOCAL_GOOGLETEST_DIR "/usr/src/googletest" CACHE PATH
|
||||
"If ABSL_USE_GOOGLETEST_HEAD is OFF and ABSL_GOOGLETEST_URL is not set, specifies the directory of a local GoogleTest checkout."
|
||||
)
|
||||
|
||||
## check targets
|
||||
if(BUILD_TESTING)
|
||||
|
||||
if(${ABSL_USE_GOOGLETEST_HEAD})
|
||||
include(CMake/Googletest/DownloadGTest.cmake)
|
||||
set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src)
|
||||
## check targets
|
||||
if (ABSL_USE_EXTERNAL_GOOGLETEST)
|
||||
if (ABSL_FIND_GOOGLETEST)
|
||||
find_package(GTest REQUIRED)
|
||||
else()
|
||||
if (NOT TARGET gtest AND NOT TARGET GTest::gtest)
|
||||
message(FATAL_ERROR "ABSL_USE_EXTERNAL_GOOGLETEST is ON and ABSL_FIND_GOOGLETEST is OFF, which means that the top-level project must build the Google Test project. However, the target gtest was not found.")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build)
|
||||
if(ABSL_USE_GOOGLETEST_HEAD AND ABSL_GOOGLETEST_DOWNLOAD_URL)
|
||||
message(FATAL_ERROR "Do not set both ABSL_USE_GOOGLETEST_HEAD and ABSL_GOOGLETEST_DOWNLOAD_URL")
|
||||
endif()
|
||||
if(ABSL_USE_GOOGLETEST_HEAD)
|
||||
set(absl_gtest_download_url "https://github.com/google/googletest/archive/master.zip")
|
||||
elseif(ABSL_GOOGLETEST_DOWNLOAD_URL)
|
||||
set(absl_gtest_download_url ${ABSL_GOOGLETEST_DOWNLOAD_URL})
|
||||
endif()
|
||||
if(absl_gtest_download_url)
|
||||
set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src)
|
||||
else()
|
||||
set(absl_gtest_src_dir ${ABSL_LOCAL_GOOGLETEST_DIR})
|
||||
endif()
|
||||
include(CMake/Googletest/DownloadGTest.cmake)
|
||||
endif()
|
||||
|
||||
check_target(gtest)
|
||||
check_target(gtest_main)
|
||||
check_target(gmock)
|
||||
if (NOT ABSL_FIND_GOOGLETEST)
|
||||
# When Google Test is included directly rather than through find_package, the aliases are missing.
|
||||
add_library(GTest::gtest ALIAS gtest)
|
||||
add_library(GTest::gtest_main ALIAS gtest_main)
|
||||
add_library(GTest::gmock ALIAS gmock)
|
||||
add_library(GTest::gmock_main ALIAS gmock_main)
|
||||
endif()
|
||||
|
||||
list(APPEND ABSL_TEST_COMMON_LIBRARIES
|
||||
gtest_main
|
||||
gtest
|
||||
gmock
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
check_target(GTest::gtest)
|
||||
check_target(GTest::gtest_main)
|
||||
check_target(GTest::gmock)
|
||||
check_target(GTest::gmock_main)
|
||||
endif()
|
||||
|
||||
add_subdirectory(absl)
|
||||
|
||||
if(ABSL_ENABLE_INSTALL)
|
||||
|
||||
|
||||
# install as a subdirectory only
|
||||
install(EXPORT ${PROJECT_NAME}Targets
|
||||
NAMESPACE absl::
|
||||
DESTINATION "${ABSL_INSTALL_CONFIGDIR}"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
configure_package_config_file(
|
||||
CMake/abslConfig.cmake.in
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION "${ABSL_INSTALL_CONFIGDIR}"
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
DESTINATION "${ABSL_INSTALL_CONFIGDIR}"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
# Abseil only has a version in LTS releases. This mechanism is accomplished
|
||||
@ -143,14 +202,16 @@ if(ABSL_ENABLE_INSTALL)
|
||||
)
|
||||
|
||||
install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
DESTINATION ${ABSL_INSTALL_CONFIGDIR}
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
endif() # absl_VERSION
|
||||
|
||||
install(DIRECTORY absl
|
||||
DESTINATION ${ABSL_INSTALL_INCLUDEDIR}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING
|
||||
PATTERN "*.inc"
|
||||
PATTERN "*.h"
|
||||
)
|
||||
PATTERN "copts" EXCLUDE
|
||||
PATTERN "testdata" EXCLUDE
|
||||
)
|
||||
endif() # ABSL_ENABLE_INSTALL
|
||||
|
||||
5
third_party/abseil-cpp/FAQ.md
vendored
5
third_party/abseil-cpp/FAQ.md
vendored
@ -27,7 +27,10 @@ compiler, there several ways to do this:
|
||||
file](https://docs.bazel.build/versions/master/guide.html#bazelrc)
|
||||
|
||||
If you are using CMake as the build system, you'll need to add a line like
|
||||
`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. See the
|
||||
`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. If you
|
||||
are developing a library designed to be used by other clients, you should
|
||||
instead leave `CMAKE_CXX_STANDARD` unset and configure the minimum C++ standard
|
||||
required by each of your library targets via `target_compile_features`. See the
|
||||
[CMake build
|
||||
instructions](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md)
|
||||
for more information.
|
||||
|
||||
15
third_party/abseil-cpp/LTS.md
vendored
15
third_party/abseil-cpp/LTS.md
vendored
@ -1,15 +0,0 @@
|
||||
# Long Term Support (LTS) Branches
|
||||
|
||||
This repository contains periodic snapshots of the Abseil codebase that are
|
||||
Long Term Support (LTS) branches. An LTS branch allows you to use a known
|
||||
version of Abseil without interfering with other projects which may also, in
|
||||
turn, use Abseil. (For more information about our releases, see the
|
||||
[Abseil Release Management](https://abseil.io/about/releases) guide.)
|
||||
|
||||
## LTS Branches
|
||||
|
||||
The following lists LTS branches and the dates on which they have been released:
|
||||
|
||||
* [LTS Branch December 18, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_12_18/)
|
||||
* [LTS Branch June 20, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_06_20/)
|
||||
* [LTS Branch August 8, 2019](https://github.com/abseil/abseil-cpp/tree/lts_2019_08_08/)
|
||||
6
third_party/abseil-cpp/METADATA
vendored
6
third_party/abseil-cpp/METADATA
vendored
@ -10,9 +10,9 @@ third_party {
|
||||
}
|
||||
url {
|
||||
type: GIT
|
||||
value: "https://github.googlesource.com/abseil/abseil-cpp/+/refs/heads/lts_2020_02_25"
|
||||
value: "https://github.com/abseil/abseil-cpp"
|
||||
}
|
||||
version: "fcb104594b0bb4b8ac306cb2f55ecdad40974683"
|
||||
last_upgrade_date { year: 2020 month: 04 day: 27 }
|
||||
version: "20211102.0"
|
||||
last_upgrade_date { year: 2021 month: 12 day: 21 }
|
||||
}
|
||||
|
||||
|
||||
42
third_party/abseil-cpp/README.md
vendored
42
third_party/abseil-cpp/README.md
vendored
@ -9,7 +9,9 @@ standard library.
|
||||
- [About Abseil](#about)
|
||||
- [Quickstart](#quickstart)
|
||||
- [Building Abseil](#build)
|
||||
- [Support](#support)
|
||||
- [Codemap](#codemap)
|
||||
- [Releases](#releases)
|
||||
- [License](#license)
|
||||
- [Links](#links)
|
||||
|
||||
@ -42,14 +44,22 @@ the Abseil code, running tests, and getting a simple binary working.
|
||||
<a name="build"></a>
|
||||
## Building Abseil
|
||||
|
||||
[Bazel](https://bazel.build) is the official build system for Abseil,
|
||||
which is supported on most major platforms (Linux, Windows, macOS, for example)
|
||||
and compilers. See the [quickstart](https://abseil.io/docs/cpp/quickstart) for
|
||||
more information on building Abseil using the Bazel build system.
|
||||
[Bazel](https://bazel.build) and [CMake](https://cmake.org/) are the official
|
||||
build systems for Abseil.
|
||||
|
||||
<a name="cmake"></a>
|
||||
If you require CMake support, please check the
|
||||
[CMake build instructions](CMake/README.md).
|
||||
See the [quickstart](https://abseil.io/docs/cpp/quickstart) for more information
|
||||
on building Abseil using the Bazel build system.
|
||||
|
||||
If you require CMake support, please check the [CMake build
|
||||
instructions](CMake/README.md) and [CMake
|
||||
Quickstart](https://abseil.io/docs/cpp/quickstart-cmake).
|
||||
|
||||
## Support
|
||||
|
||||
Abseil is officially supported on many platforms. See the [Abseil
|
||||
platform support
|
||||
guide](https://abseil.io/docs/cpp/platforms/platforms) for details on
|
||||
supported operating systems, compilers, CPUs, etc.
|
||||
|
||||
## Codemap
|
||||
|
||||
@ -62,6 +72,9 @@ Abseil contains the following C++ library components:
|
||||
* [`algorithm`](absl/algorithm/)
|
||||
<br /> The `algorithm` library contains additions to the C++ `<algorithm>`
|
||||
library and container-based versions of such algorithms.
|
||||
* [`cleanup`](absl/cleanup/)
|
||||
<br /> The `cleanup` library contains the control-flow-construct-like type
|
||||
`absl::Cleanup` which is used for executing a callback on scope exit.
|
||||
* [`container`](absl/container/)
|
||||
<br /> The `container` library contains additional STL-style containers,
|
||||
including Abseil's unordered "Swiss table" containers.
|
||||
@ -79,6 +92,12 @@ Abseil contains the following C++ library components:
|
||||
available within C++14 and C++17 versions of the C++ `<type_traits>` library.
|
||||
* [`numeric`](absl/numeric/)
|
||||
<br /> The `numeric` library contains C++11-compatible 128-bit integers.
|
||||
* [`profiling`](absl/profiling/)
|
||||
<br /> The `profiling` library contains utility code for profiling C++
|
||||
entities. It is currently a private dependency of other Abseil libraries.
|
||||
* [`status`](absl/status/)
|
||||
<br /> The `status` contains abstractions for error handling, specifically
|
||||
`absl::Status` and `absl::StatusOr<T>`.
|
||||
* [`strings`](absl/strings/)
|
||||
<br /> The `strings` library contains a variety of strings routines and
|
||||
utilities, including a C++11-compatible version of the C++17
|
||||
@ -97,6 +116,15 @@ Abseil contains the following C++ library components:
|
||||
* [`utility`](absl/utility/)
|
||||
<br /> The `utility` library contains utility and helper code.
|
||||
|
||||
## Releases
|
||||
|
||||
Abseil recommends users "live-at-head" (update to the latest commit from the
|
||||
master branch as often as possible). However, we realize this philosophy doesn't
|
||||
work for every project, so we also provide [Long Term Support
|
||||
Releases](https://github.com/abseil/abseil-cpp/releases) to which we backport
|
||||
fixes for severe bugs. See our [release
|
||||
management](https://abseil.io/about/releases) document for more details.
|
||||
|
||||
## License
|
||||
|
||||
The Abseil C++ library is licensed under the terms of the Apache
|
||||
|
||||
31
third_party/abseil-cpp/WORKSPACE
vendored
31
third_party/abseil-cpp/WORKSPACE
vendored
@ -15,31 +15,30 @@
|
||||
#
|
||||
|
||||
workspace(name = "com_google_absl")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
# GoogleTest/GoogleMock framework. Used by most unit-tests.
|
||||
http_archive(
|
||||
name = "com_google_googletest",
|
||||
urls = ["https://github.com/google/googletest/archive/b6cd405286ed8635ece71c72f118e659f4ade3fb.zip"], # 2019-01-07
|
||||
strip_prefix = "googletest-b6cd405286ed8635ece71c72f118e659f4ade3fb",
|
||||
sha256 = "ff7a82736e158c077e76188232eac77913a15dac0b22508c390ab3f88e6d6d86",
|
||||
name = "com_google_googletest", # 2021-07-09T13:28:13Z
|
||||
sha256 = "12ef65654dc01ab40f6f33f9d02c04f2097d2cd9fbe48dc6001b29543583b0ad",
|
||||
strip_prefix = "googletest-8d51ffdfab10b3fba636ae69bc03da4b54f8c235",
|
||||
# Keep this URL in sync with ABSL_GOOGLETEST_COMMIT in ci/cmake_common.sh.
|
||||
urls = ["https://github.com/google/googletest/archive/8d51ffdfab10b3fba636ae69bc03da4b54f8c235.zip"],
|
||||
)
|
||||
|
||||
# Google benchmark.
|
||||
http_archive(
|
||||
name = "com_github_google_benchmark",
|
||||
urls = ["https://github.com/google/benchmark/archive/16703ff83c1ae6d53e5155df3bb3ab0bc96083be.zip"],
|
||||
strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be",
|
||||
sha256 = "59f918c8ccd4d74b6ac43484467b500f1d64b40cc1010daa055375b322a43ba3",
|
||||
name = "com_github_google_benchmark", # 2021-09-20T09:19:51Z
|
||||
sha256 = "62e2f2e6d8a744d67e4bbc212fcfd06647080de4253c97ad5c6749e09faf2cb0",
|
||||
strip_prefix = "benchmark-0baacde3618ca617da95375e0af13ce1baadea47",
|
||||
urls = ["https://github.com/google/benchmark/archive/0baacde3618ca617da95375e0af13ce1baadea47.zip"],
|
||||
)
|
||||
|
||||
# C++ rules for Bazel.
|
||||
# Bazel platform rules.
|
||||
http_archive(
|
||||
name = "rules_cc",
|
||||
sha256 = "9a446e9dd9c1bb180c86977a8dc1e9e659550ae732ae58bd2e8fd51e15b2c91d",
|
||||
strip_prefix = "rules_cc-262ebec3c2296296526740db4aefce68c80de7fa",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip",
|
||||
"https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip",
|
||||
],
|
||||
name = "platforms",
|
||||
sha256 = "b601beaf841244de5c5a50d2b2eddd34839788000fa1be4260ce6603ca0d8eb7",
|
||||
strip_prefix = "platforms-98939346da932eef0b54cf808622f5bb0928f00b",
|
||||
urls = ["https://github.com/bazelbuild/platforms/archive/98939346da932eef0b54cf808622f5bb0928f00b.zip"],
|
||||
)
|
||||
|
||||
59
third_party/abseil-cpp/absl/BUILD.bazel
vendored
59
third_party/abseil-cpp/absl/BUILD.bazel
vendored
@ -12,44 +12,49 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
load(
|
||||
":compiler_config_setting.bzl",
|
||||
"create_llvm_config",
|
||||
)
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
licenses(["notice"])
|
||||
|
||||
create_llvm_config(
|
||||
name = "llvm_compiler",
|
||||
config_setting(
|
||||
name = "clang_compiler",
|
||||
flag_values = {
|
||||
"@bazel_tools//tools/cpp:compiler": "clang",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "msvc_compiler",
|
||||
flag_values = {
|
||||
"@bazel_tools//tools/cpp:compiler": "msvc-cl",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "clang-cl_compiler",
|
||||
flag_values = {
|
||||
"@bazel_tools//tools/cpp:compiler": "clang-cl",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "osx",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:osx",
|
||||
"@platforms//os:osx",
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "ios",
|
||||
constraint_values = [
|
||||
"@bazel_tools//platforms:ios",
|
||||
"@platforms//os:ios",
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
values = {
|
||||
"cpu": "x64_windows",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "ppc",
|
||||
values = {
|
||||
@ -57,3 +62,19 @@ config_setting(
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "wasm",
|
||||
values = {
|
||||
"cpu": "wasm32",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "fuchsia",
|
||||
values = {
|
||||
"cpu": "fuchsia",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
2
third_party/abseil-cpp/absl/CMakeLists.txt
vendored
2
third_party/abseil-cpp/absl/CMakeLists.txt
vendored
@ -16,6 +16,7 @@
|
||||
|
||||
add_subdirectory(base)
|
||||
add_subdirectory(algorithm)
|
||||
add_subdirectory(cleanup)
|
||||
add_subdirectory(container)
|
||||
add_subdirectory(debugging)
|
||||
add_subdirectory(flags)
|
||||
@ -24,6 +25,7 @@ add_subdirectory(hash)
|
||||
add_subdirectory(memory)
|
||||
add_subdirectory(meta)
|
||||
add_subdirectory(numeric)
|
||||
add_subdirectory(profiling)
|
||||
add_subdirectory(random)
|
||||
add_subdirectory(status)
|
||||
add_subdirectory(strings)
|
||||
|
||||
4
third_party/abseil-cpp/absl/abseil.podspec.gen.py
vendored
Normal file → Executable file
4
third_party/abseil-cpp/absl/abseil.podspec.gen.py
vendored
Normal file → Executable file
@ -40,8 +40,8 @@ Pod::Spec.new do |s|
|
||||
'USE_HEADERMAP' => 'NO',
|
||||
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
|
||||
}
|
||||
s.ios.deployment_target = '7.0'
|
||||
s.osx.deployment_target = '10.9'
|
||||
s.ios.deployment_target = '9.0'
|
||||
s.osx.deployment_target = '10.10'
|
||||
s.tvos.deployment_target = '9.0'
|
||||
s.watchos.deployment_target = '2.0'
|
||||
"""
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
|
||||
load(
|
||||
"//absl:copts/configure_copts.bzl",
|
||||
"ABSL_DEFAULT_COPTS",
|
||||
@ -24,14 +23,16 @@ load(
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "algorithm",
|
||||
hdrs = ["algorithm.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = ["//absl/base:config"],
|
||||
deps = [
|
||||
"//absl/base:config",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
|
||||
@ -35,7 +35,7 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::algorithm
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -65,5 +65,5 @@ absl_cc_test(
|
||||
absl::core_headers
|
||||
absl::memory
|
||||
absl::span
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
279
third_party/abseil-cpp/absl/algorithm/container.h
vendored
279
third_party/abseil-cpp/absl/algorithm/container.h
vendored
@ -90,10 +90,10 @@ using ContainerPointerType =
|
||||
// lookup of std::begin and std::end, i.e.
|
||||
// using std::begin;
|
||||
// using std::end;
|
||||
// std::foo(begin(c), end(c);
|
||||
// std::foo(begin(c), end(c));
|
||||
// becomes
|
||||
// std::foo(container_algorithm_internal::begin(c),
|
||||
// container_algorithm_internal::end(c));
|
||||
// container_algorithm_internal::end(c));
|
||||
// These are meant for internal use only.
|
||||
|
||||
template <typename C>
|
||||
@ -188,7 +188,7 @@ bool c_any_of(const C& c, Pred&& pred) {
|
||||
// c_none_of()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::none_of()` function to
|
||||
// test if no elements in a container fulfil a condition.
|
||||
// test if no elements in a container fulfill a condition.
|
||||
template <typename C, typename Pred>
|
||||
bool c_none_of(const C& c, Pred&& pred) {
|
||||
return std::none_of(container_algorithm_internal::c_begin(c),
|
||||
@ -340,24 +340,45 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
|
||||
// c_mismatch()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::mismatch()` function to
|
||||
// return the first element where two ordered containers differ.
|
||||
// return the first element where two ordered containers differ. Applies `==` to
|
||||
// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
|
||||
template <typename C1, typename C2>
|
||||
container_algorithm_internal::ContainerIterPairType<C1, C2>
|
||||
c_mismatch(C1& c1, C2& c2) {
|
||||
return std::mismatch(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2));
|
||||
auto first1 = container_algorithm_internal::c_begin(c1);
|
||||
auto last1 = container_algorithm_internal::c_end(c1);
|
||||
auto first2 = container_algorithm_internal::c_begin(c2);
|
||||
auto last2 = container_algorithm_internal::c_end(c2);
|
||||
|
||||
for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
|
||||
// Negates equality because Cpp17EqualityComparable doesn't require clients
|
||||
// to overload both `operator==` and `operator!=`.
|
||||
if (!(*first1 == *first2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(first1, first2);
|
||||
}
|
||||
|
||||
// Overload of c_mismatch() for using a predicate evaluation other than `==` as
|
||||
// the function's test condition.
|
||||
// the function's test condition. Applies `pred`to the first N elements of `c1`
|
||||
// and `c2`, where N = min(size(c1), size(c2)).
|
||||
template <typename C1, typename C2, typename BinaryPredicate>
|
||||
container_algorithm_internal::ContainerIterPairType<C1, C2>
|
||||
c_mismatch(C1& c1, C2& c2, BinaryPredicate&& pred) {
|
||||
return std::mismatch(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
std::forward<BinaryPredicate>(pred));
|
||||
c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
|
||||
auto first1 = container_algorithm_internal::c_begin(c1);
|
||||
auto last1 = container_algorithm_internal::c_end(c1);
|
||||
auto first2 = container_algorithm_internal::c_begin(c2);
|
||||
auto last2 = container_algorithm_internal::c_end(c2);
|
||||
|
||||
for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
|
||||
if (!pred(*first1, *first2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(first1, first2);
|
||||
}
|
||||
|
||||
// c_equal()
|
||||
@ -539,12 +560,20 @@ BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator dest) {
|
||||
// c_swap_ranges()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::swap_ranges()` function to
|
||||
// swap a container's elements with another container's elements.
|
||||
// swap a container's elements with another container's elements. Swaps the
|
||||
// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
|
||||
template <typename C1, typename C2>
|
||||
container_algorithm_internal::ContainerIter<C2> c_swap_ranges(C1& c1, C2& c2) {
|
||||
return std::swap_ranges(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2));
|
||||
auto first1 = container_algorithm_internal::c_begin(c1);
|
||||
auto last1 = container_algorithm_internal::c_end(c1);
|
||||
auto first2 = container_algorithm_internal::c_begin(c2);
|
||||
auto last2 = container_algorithm_internal::c_end(c2);
|
||||
|
||||
using std::swap;
|
||||
for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
|
||||
swap(*first1, *first2);
|
||||
}
|
||||
return first2;
|
||||
}
|
||||
|
||||
// c_transform()
|
||||
@ -562,16 +591,23 @@ OutputIterator c_transform(const InputSequence& input, OutputIterator output,
|
||||
}
|
||||
|
||||
// Overload of c_transform() for performing a transformation using a binary
|
||||
// predicate.
|
||||
// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,
|
||||
// where N = min(size(c1), size(c2)).
|
||||
template <typename InputSequence1, typename InputSequence2,
|
||||
typename OutputIterator, typename BinaryOp>
|
||||
OutputIterator c_transform(const InputSequence1& input1,
|
||||
const InputSequence2& input2, OutputIterator output,
|
||||
BinaryOp&& binary_op) {
|
||||
return std::transform(container_algorithm_internal::c_begin(input1),
|
||||
container_algorithm_internal::c_end(input1),
|
||||
container_algorithm_internal::c_begin(input2), output,
|
||||
std::forward<BinaryOp>(binary_op));
|
||||
auto first1 = container_algorithm_internal::c_begin(input1);
|
||||
auto last1 = container_algorithm_internal::c_end(input1);
|
||||
auto first2 = container_algorithm_internal::c_begin(input2);
|
||||
auto last2 = container_algorithm_internal::c_end(input2);
|
||||
for (; first1 != last1 && first2 != last2;
|
||||
++first1, (void)++first2, ++output) {
|
||||
*output = binary_op(*first1, *first2);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// c_replace()
|
||||
@ -869,11 +905,11 @@ void c_sort(C& c) {
|
||||
|
||||
// Overload of c_sort() for performing a `comp` comparison other than the
|
||||
// default `operator<`.
|
||||
template <typename C, typename Compare>
|
||||
void c_sort(C& c, Compare&& comp) {
|
||||
template <typename C, typename LessThan>
|
||||
void c_sort(C& c, LessThan&& comp) {
|
||||
std::sort(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_stable_sort()
|
||||
@ -889,11 +925,11 @@ void c_stable_sort(C& c) {
|
||||
|
||||
// Overload of c_stable_sort() for performing a `comp` comparison other than the
|
||||
// default `operator<`.
|
||||
template <typename C, typename Compare>
|
||||
void c_stable_sort(C& c, Compare&& comp) {
|
||||
template <typename C, typename LessThan>
|
||||
void c_stable_sort(C& c, LessThan&& comp) {
|
||||
std::stable_sort(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_is_sorted()
|
||||
@ -908,11 +944,11 @@ bool c_is_sorted(const C& c) {
|
||||
|
||||
// c_is_sorted() overload for performing a `comp` comparison other than the
|
||||
// default `operator<`.
|
||||
template <typename C, typename Compare>
|
||||
bool c_is_sorted(const C& c, Compare&& comp) {
|
||||
template <typename C, typename LessThan>
|
||||
bool c_is_sorted(const C& c, LessThan&& comp) {
|
||||
return std::is_sorted(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_partial_sort()
|
||||
@ -930,22 +966,23 @@ void c_partial_sort(
|
||||
|
||||
// Overload of c_partial_sort() for performing a `comp` comparison other than
|
||||
// the default `operator<`.
|
||||
template <typename RandomAccessContainer, typename Compare>
|
||||
template <typename RandomAccessContainer, typename LessThan>
|
||||
void c_partial_sort(
|
||||
RandomAccessContainer& sequence,
|
||||
container_algorithm_internal::ContainerIter<RandomAccessContainer> middle,
|
||||
Compare&& comp) {
|
||||
LessThan&& comp) {
|
||||
std::partial_sort(container_algorithm_internal::c_begin(sequence), middle,
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_partial_sort_copy()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::partial_sort_copy()`
|
||||
// function to sort elements within a container such that elements before
|
||||
// `middle` are sorted in ascending order, and return the result within an
|
||||
// iterator.
|
||||
// function to sort the elements in the given range `result` within the larger
|
||||
// `sequence` in ascending order (and using `result` as the output parameter).
|
||||
// At most min(result.last - result.first, sequence.last - sequence.first)
|
||||
// elements from the sequence will be stored in the result.
|
||||
template <typename C, typename RandomAccessContainer>
|
||||
container_algorithm_internal::ContainerIter<RandomAccessContainer>
|
||||
c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {
|
||||
@ -957,15 +994,15 @@ c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {
|
||||
|
||||
// Overload of c_partial_sort_copy() for performing a `comp` comparison other
|
||||
// than the default `operator<`.
|
||||
template <typename C, typename RandomAccessContainer, typename Compare>
|
||||
template <typename C, typename RandomAccessContainer, typename LessThan>
|
||||
container_algorithm_internal::ContainerIter<RandomAccessContainer>
|
||||
c_partial_sort_copy(const C& sequence, RandomAccessContainer& result,
|
||||
Compare&& comp) {
|
||||
LessThan&& comp) {
|
||||
return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
container_algorithm_internal::c_begin(result),
|
||||
container_algorithm_internal::c_end(result),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_is_sorted_until()
|
||||
@ -981,12 +1018,12 @@ container_algorithm_internal::ContainerIter<C> c_is_sorted_until(C& c) {
|
||||
|
||||
// Overload of c_is_sorted_until() for performing a `comp` comparison other than
|
||||
// the default `operator<`.
|
||||
template <typename C, typename Compare>
|
||||
template <typename C, typename LessThan>
|
||||
container_algorithm_internal::ContainerIter<C> c_is_sorted_until(
|
||||
C& c, Compare&& comp) {
|
||||
C& c, LessThan&& comp) {
|
||||
return std::is_sorted_until(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_nth_element()
|
||||
@ -1006,14 +1043,14 @@ void c_nth_element(
|
||||
|
||||
// Overload of c_nth_element() for performing a `comp` comparison other than
|
||||
// the default `operator<`.
|
||||
template <typename RandomAccessContainer, typename Compare>
|
||||
template <typename RandomAccessContainer, typename LessThan>
|
||||
void c_nth_element(
|
||||
RandomAccessContainer& sequence,
|
||||
container_algorithm_internal::ContainerIter<RandomAccessContainer> nth,
|
||||
Compare&& comp) {
|
||||
LessThan&& comp) {
|
||||
std::nth_element(container_algorithm_internal::c_begin(sequence), nth,
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1035,12 +1072,12 @@ container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
|
||||
|
||||
// Overload of c_lower_bound() for performing a `comp` comparison other than
|
||||
// the default `operator<`.
|
||||
template <typename Sequence, typename T, typename Compare>
|
||||
template <typename Sequence, typename T, typename LessThan>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
|
||||
Sequence& sequence, T&& value, Compare&& comp) {
|
||||
Sequence& sequence, T&& value, LessThan&& comp) {
|
||||
return std::lower_bound(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<T>(value), std::forward<Compare>(comp));
|
||||
std::forward<T>(value), std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_upper_bound()
|
||||
@ -1058,12 +1095,12 @@ container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
|
||||
|
||||
// Overload of c_upper_bound() for performing a `comp` comparison other than
|
||||
// the default `operator<`.
|
||||
template <typename Sequence, typename T, typename Compare>
|
||||
template <typename Sequence, typename T, typename LessThan>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
|
||||
Sequence& sequence, T&& value, Compare&& comp) {
|
||||
Sequence& sequence, T&& value, LessThan&& comp) {
|
||||
return std::upper_bound(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<T>(value), std::forward<Compare>(comp));
|
||||
std::forward<T>(value), std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_equal_range()
|
||||
@ -1081,12 +1118,12 @@ c_equal_range(Sequence& sequence, T&& value) {
|
||||
|
||||
// Overload of c_equal_range() for performing a `comp` comparison other than
|
||||
// the default `operator<`.
|
||||
template <typename Sequence, typename T, typename Compare>
|
||||
template <typename Sequence, typename T, typename LessThan>
|
||||
container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
|
||||
c_equal_range(Sequence& sequence, T&& value, Compare&& comp) {
|
||||
c_equal_range(Sequence& sequence, T&& value, LessThan&& comp) {
|
||||
return std::equal_range(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<T>(value), std::forward<Compare>(comp));
|
||||
std::forward<T>(value), std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_binary_search()
|
||||
@ -1103,12 +1140,12 @@ bool c_binary_search(Sequence&& sequence, T&& value) {
|
||||
|
||||
// Overload of c_binary_search() for performing a `comp` comparison other than
|
||||
// the default `operator<`.
|
||||
template <typename Sequence, typename T, typename Compare>
|
||||
bool c_binary_search(Sequence&& sequence, T&& value, Compare&& comp) {
|
||||
template <typename Sequence, typename T, typename LessThan>
|
||||
bool c_binary_search(Sequence&& sequence, T&& value, LessThan&& comp) {
|
||||
return std::binary_search(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<T>(value),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1129,14 +1166,14 @@ OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result) {
|
||||
|
||||
// Overload of c_merge() for performing a `comp` comparison other than
|
||||
// the default `operator<`.
|
||||
template <typename C1, typename C2, typename OutputIterator, typename Compare>
|
||||
template <typename C1, typename C2, typename OutputIterator, typename LessThan>
|
||||
OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result,
|
||||
Compare&& comp) {
|
||||
LessThan&& comp) {
|
||||
return std::merge(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2), result,
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_inplace_merge()
|
||||
@ -1152,13 +1189,13 @@ void c_inplace_merge(C& c,
|
||||
|
||||
// Overload of c_inplace_merge() for performing a merge using a `comp` other
|
||||
// than `operator<`.
|
||||
template <typename C, typename Compare>
|
||||
template <typename C, typename LessThan>
|
||||
void c_inplace_merge(C& c,
|
||||
container_algorithm_internal::ContainerIter<C> middle,
|
||||
Compare&& comp) {
|
||||
LessThan&& comp) {
|
||||
std::inplace_merge(container_algorithm_internal::c_begin(c), middle,
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_includes()
|
||||
@ -1176,13 +1213,13 @@ bool c_includes(const C1& c1, const C2& c2) {
|
||||
|
||||
// Overload of c_includes() for performing a merge using a `comp` other than
|
||||
// `operator<`.
|
||||
template <typename C1, typename C2, typename Compare>
|
||||
bool c_includes(const C1& c1, const C2& c2, Compare&& comp) {
|
||||
template <typename C1, typename C2, typename LessThan>
|
||||
bool c_includes(const C1& c1, const C2& c2, LessThan&& comp) {
|
||||
return std::includes(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_set_union()
|
||||
@ -1206,7 +1243,7 @@ OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) {
|
||||
|
||||
// Overload of c_set_union() for performing a merge using a `comp` other than
|
||||
// `operator<`.
|
||||
template <typename C1, typename C2, typename OutputIterator, typename Compare,
|
||||
template <typename C1, typename C2, typename OutputIterator, typename LessThan,
|
||||
typename = typename std::enable_if<
|
||||
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
|
||||
void>::type,
|
||||
@ -1214,18 +1251,18 @@ template <typename C1, typename C2, typename OutputIterator, typename Compare,
|
||||
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
|
||||
void>::type>
|
||||
OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output,
|
||||
Compare&& comp) {
|
||||
LessThan&& comp) {
|
||||
return std::set_union(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2), output,
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_set_intersection()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::set_intersection()` function
|
||||
// to return an iterator containing the intersection of two containers.
|
||||
// to return an iterator containing the intersection of two sorted containers.
|
||||
template <typename C1, typename C2, typename OutputIterator,
|
||||
typename = typename std::enable_if<
|
||||
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
|
||||
@ -1235,6 +1272,11 @@ template <typename C1, typename C2, typename OutputIterator,
|
||||
void>::type>
|
||||
OutputIterator c_set_intersection(const C1& c1, const C2& c2,
|
||||
OutputIterator output) {
|
||||
// In debug builds, ensure that both containers are sorted with respect to the
|
||||
// default comparator. std::set_intersection requires the containers be sorted
|
||||
// using operator<.
|
||||
assert(absl::c_is_sorted(c1));
|
||||
assert(absl::c_is_sorted(c2));
|
||||
return std::set_intersection(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
@ -1243,7 +1285,7 @@ OutputIterator c_set_intersection(const C1& c1, const C2& c2,
|
||||
|
||||
// Overload of c_set_intersection() for performing a merge using a `comp` other
|
||||
// than `operator<`.
|
||||
template <typename C1, typename C2, typename OutputIterator, typename Compare,
|
||||
template <typename C1, typename C2, typename OutputIterator, typename LessThan,
|
||||
typename = typename std::enable_if<
|
||||
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
|
||||
void>::type,
|
||||
@ -1251,12 +1293,17 @@ template <typename C1, typename C2, typename OutputIterator, typename Compare,
|
||||
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
|
||||
void>::type>
|
||||
OutputIterator c_set_intersection(const C1& c1, const C2& c2,
|
||||
OutputIterator output, Compare&& comp) {
|
||||
OutputIterator output, LessThan&& comp) {
|
||||
// In debug builds, ensure that both containers are sorted with respect to the
|
||||
// default comparator. std::set_intersection requires the containers be sorted
|
||||
// using the same comparator.
|
||||
assert(absl::c_is_sorted(c1, comp));
|
||||
assert(absl::c_is_sorted(c2, comp));
|
||||
return std::set_intersection(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2), output,
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_set_difference()
|
||||
@ -1281,7 +1328,7 @@ OutputIterator c_set_difference(const C1& c1, const C2& c2,
|
||||
|
||||
// Overload of c_set_difference() for performing a merge using a `comp` other
|
||||
// than `operator<`.
|
||||
template <typename C1, typename C2, typename OutputIterator, typename Compare,
|
||||
template <typename C1, typename C2, typename OutputIterator, typename LessThan,
|
||||
typename = typename std::enable_if<
|
||||
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
|
||||
void>::type,
|
||||
@ -1289,12 +1336,12 @@ template <typename C1, typename C2, typename OutputIterator, typename Compare,
|
||||
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
|
||||
void>::type>
|
||||
OutputIterator c_set_difference(const C1& c1, const C2& c2,
|
||||
OutputIterator output, Compare&& comp) {
|
||||
OutputIterator output, LessThan&& comp) {
|
||||
return std::set_difference(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2), output,
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_set_symmetric_difference()
|
||||
@ -1320,7 +1367,7 @@ OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
|
||||
|
||||
// Overload of c_set_symmetric_difference() for performing a merge using a
|
||||
// `comp` other than `operator<`.
|
||||
template <typename C1, typename C2, typename OutputIterator, typename Compare,
|
||||
template <typename C1, typename C2, typename OutputIterator, typename LessThan,
|
||||
typename = typename std::enable_if<
|
||||
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
|
||||
void>::type,
|
||||
@ -1329,13 +1376,13 @@ template <typename C1, typename C2, typename OutputIterator, typename Compare,
|
||||
void>::type>
|
||||
OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
|
||||
OutputIterator output,
|
||||
Compare&& comp) {
|
||||
LessThan&& comp) {
|
||||
return std::set_symmetric_difference(
|
||||
container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2), output,
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1354,11 +1401,11 @@ void c_push_heap(RandomAccessContainer& sequence) {
|
||||
|
||||
// Overload of c_push_heap() for performing a push operation on a heap using a
|
||||
// `comp` other than `operator<`.
|
||||
template <typename RandomAccessContainer, typename Compare>
|
||||
void c_push_heap(RandomAccessContainer& sequence, Compare&& comp) {
|
||||
template <typename RandomAccessContainer, typename LessThan>
|
||||
void c_push_heap(RandomAccessContainer& sequence, LessThan&& comp) {
|
||||
std::push_heap(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_pop_heap()
|
||||
@ -1373,11 +1420,11 @@ void c_pop_heap(RandomAccessContainer& sequence) {
|
||||
|
||||
// Overload of c_pop_heap() for performing a pop operation on a heap using a
|
||||
// `comp` other than `operator<`.
|
||||
template <typename RandomAccessContainer, typename Compare>
|
||||
void c_pop_heap(RandomAccessContainer& sequence, Compare&& comp) {
|
||||
template <typename RandomAccessContainer, typename LessThan>
|
||||
void c_pop_heap(RandomAccessContainer& sequence, LessThan&& comp) {
|
||||
std::pop_heap(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_make_heap()
|
||||
@ -1392,11 +1439,11 @@ void c_make_heap(RandomAccessContainer& sequence) {
|
||||
|
||||
// Overload of c_make_heap() for performing heap comparisons using a
|
||||
// `comp` other than `operator<`
|
||||
template <typename RandomAccessContainer, typename Compare>
|
||||
void c_make_heap(RandomAccessContainer& sequence, Compare&& comp) {
|
||||
template <typename RandomAccessContainer, typename LessThan>
|
||||
void c_make_heap(RandomAccessContainer& sequence, LessThan&& comp) {
|
||||
std::make_heap(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_sort_heap()
|
||||
@ -1411,11 +1458,11 @@ void c_sort_heap(RandomAccessContainer& sequence) {
|
||||
|
||||
// Overload of c_sort_heap() for performing heap comparisons using a
|
||||
// `comp` other than `operator<`
|
||||
template <typename RandomAccessContainer, typename Compare>
|
||||
void c_sort_heap(RandomAccessContainer& sequence, Compare&& comp) {
|
||||
template <typename RandomAccessContainer, typename LessThan>
|
||||
void c_sort_heap(RandomAccessContainer& sequence, LessThan&& comp) {
|
||||
std::sort_heap(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_is_heap()
|
||||
@ -1430,11 +1477,11 @@ bool c_is_heap(const RandomAccessContainer& sequence) {
|
||||
|
||||
// Overload of c_is_heap() for performing heap comparisons using a
|
||||
// `comp` other than `operator<`
|
||||
template <typename RandomAccessContainer, typename Compare>
|
||||
bool c_is_heap(const RandomAccessContainer& sequence, Compare&& comp) {
|
||||
template <typename RandomAccessContainer, typename LessThan>
|
||||
bool c_is_heap(const RandomAccessContainer& sequence, LessThan&& comp) {
|
||||
return std::is_heap(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_is_heap_until()
|
||||
@ -1450,12 +1497,12 @@ c_is_heap_until(RandomAccessContainer& sequence) {
|
||||
|
||||
// Overload of c_is_heap_until() for performing heap comparisons using a
|
||||
// `comp` other than `operator<`
|
||||
template <typename RandomAccessContainer, typename Compare>
|
||||
template <typename RandomAccessContainer, typename LessThan>
|
||||
container_algorithm_internal::ContainerIter<RandomAccessContainer>
|
||||
c_is_heap_until(RandomAccessContainer& sequence, Compare&& comp) {
|
||||
c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {
|
||||
return std::is_heap_until(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1476,12 +1523,12 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
|
||||
|
||||
// Overload of c_min_element() for performing a `comp` comparison other than
|
||||
// `operator<`.
|
||||
template <typename Sequence, typename Compare>
|
||||
template <typename Sequence, typename LessThan>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_min_element(
|
||||
Sequence& sequence, Compare&& comp) {
|
||||
Sequence& sequence, LessThan&& comp) {
|
||||
return std::min_element(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_max_element()
|
||||
@ -1498,12 +1545,12 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
|
||||
|
||||
// Overload of c_max_element() for performing a `comp` comparison other than
|
||||
// `operator<`.
|
||||
template <typename Sequence, typename Compare>
|
||||
template <typename Sequence, typename LessThan>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_max_element(
|
||||
Sequence& sequence, Compare&& comp) {
|
||||
Sequence& sequence, LessThan&& comp) {
|
||||
return std::max_element(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_minmax_element()
|
||||
@ -1521,12 +1568,12 @@ c_minmax_element(C& c) {
|
||||
|
||||
// Overload of c_minmax_element() for performing `comp` comparisons other than
|
||||
// `operator<`.
|
||||
template <typename C, typename Compare>
|
||||
template <typename C, typename LessThan>
|
||||
container_algorithm_internal::ContainerIterPairType<C, C>
|
||||
c_minmax_element(C& c, Compare&& comp) {
|
||||
c_minmax_element(C& c, LessThan&& comp) {
|
||||
return std::minmax_element(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1551,15 +1598,15 @@ bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2) {
|
||||
|
||||
// Overload of c_lexicographical_compare() for performing a lexicographical
|
||||
// comparison using a `comp` operator instead of `operator<`.
|
||||
template <typename Sequence1, typename Sequence2, typename Compare>
|
||||
template <typename Sequence1, typename Sequence2, typename LessThan>
|
||||
bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2,
|
||||
Compare&& comp) {
|
||||
LessThan&& comp) {
|
||||
return std::lexicographical_compare(
|
||||
container_algorithm_internal::c_begin(sequence1),
|
||||
container_algorithm_internal::c_end(sequence1),
|
||||
container_algorithm_internal::c_begin(sequence2),
|
||||
container_algorithm_internal::c_end(sequence2),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_next_permutation()
|
||||
@ -1575,11 +1622,11 @@ bool c_next_permutation(C& c) {
|
||||
|
||||
// Overload of c_next_permutation() for performing a lexicographical
|
||||
// comparison using a `comp` operator instead of `operator<`.
|
||||
template <typename C, typename Compare>
|
||||
bool c_next_permutation(C& c, Compare&& comp) {
|
||||
template <typename C, typename LessThan>
|
||||
bool c_next_permutation(C& c, LessThan&& comp) {
|
||||
return std::next_permutation(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
// c_prev_permutation()
|
||||
@ -1595,11 +1642,11 @@ bool c_prev_permutation(C& c) {
|
||||
|
||||
// Overload of c_prev_permutation() for performing a lexicographical
|
||||
// comparison using a `comp` operator instead of `operator<`.
|
||||
template <typename C, typename Compare>
|
||||
bool c_prev_permutation(C& c, Compare&& comp) {
|
||||
template <typename C, typename LessThan>
|
||||
bool c_prev_permutation(C& c, LessThan&& comp) {
|
||||
return std::prev_permutation(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Compare>(comp));
|
||||
std::forward<LessThan>(comp));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -57,9 +57,7 @@ class NonMutatingTest : public testing::Test {
|
||||
};
|
||||
|
||||
struct AccumulateCalls {
|
||||
void operator()(int value) {
|
||||
calls.push_back(value);
|
||||
}
|
||||
void operator()(int value) { calls.push_back(value); }
|
||||
std::vector<int> calls;
|
||||
};
|
||||
|
||||
@ -68,7 +66,6 @@ bool BinPredicate(int v1, int v2) { return v1 < v2; }
|
||||
bool Equals(int v1, int v2) { return v1 == v2; }
|
||||
bool IsOdd(int x) { return x % 2 != 0; }
|
||||
|
||||
|
||||
TEST_F(NonMutatingTest, Distance) {
|
||||
EXPECT_EQ(container_.size(), absl::c_distance(container_));
|
||||
EXPECT_EQ(sequence_.size(), absl::c_distance(sequence_));
|
||||
@ -151,13 +148,90 @@ TEST_F(NonMutatingTest, CountIf) {
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, Mismatch) {
|
||||
absl::c_mismatch(container_, sequence_);
|
||||
absl::c_mismatch(sequence_, container_);
|
||||
// Testing necessary as absl::c_mismatch executes logic.
|
||||
{
|
||||
auto result = absl::c_mismatch(vector_, sequence_);
|
||||
EXPECT_EQ(result.first, vector_.end());
|
||||
EXPECT_EQ(result.second, sequence_.end());
|
||||
}
|
||||
{
|
||||
auto result = absl::c_mismatch(sequence_, vector_);
|
||||
EXPECT_EQ(result.first, sequence_.end());
|
||||
EXPECT_EQ(result.second, vector_.end());
|
||||
}
|
||||
|
||||
sequence_.back() = 5;
|
||||
{
|
||||
auto result = absl::c_mismatch(vector_, sequence_);
|
||||
EXPECT_EQ(result.first, std::prev(vector_.end()));
|
||||
EXPECT_EQ(result.second, std::prev(sequence_.end()));
|
||||
}
|
||||
{
|
||||
auto result = absl::c_mismatch(sequence_, vector_);
|
||||
EXPECT_EQ(result.first, std::prev(sequence_.end()));
|
||||
EXPECT_EQ(result.second, std::prev(vector_.end()));
|
||||
}
|
||||
|
||||
sequence_.pop_back();
|
||||
{
|
||||
auto result = absl::c_mismatch(vector_, sequence_);
|
||||
EXPECT_EQ(result.first, std::prev(vector_.end()));
|
||||
EXPECT_EQ(result.second, sequence_.end());
|
||||
}
|
||||
{
|
||||
auto result = absl::c_mismatch(sequence_, vector_);
|
||||
EXPECT_EQ(result.first, sequence_.end());
|
||||
EXPECT_EQ(result.second, std::prev(vector_.end()));
|
||||
}
|
||||
{
|
||||
struct NoNotEquals {
|
||||
constexpr bool operator==(NoNotEquals) const { return true; }
|
||||
constexpr bool operator!=(NoNotEquals) const = delete;
|
||||
};
|
||||
std::vector<NoNotEquals> first;
|
||||
std::list<NoNotEquals> second;
|
||||
|
||||
// Check this still compiles.
|
||||
absl::c_mismatch(first, second);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, MismatchWithPredicate) {
|
||||
absl::c_mismatch(container_, sequence_, BinPredicate);
|
||||
absl::c_mismatch(sequence_, container_, BinPredicate);
|
||||
// Testing necessary as absl::c_mismatch executes logic.
|
||||
{
|
||||
auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
|
||||
EXPECT_EQ(result.first, vector_.begin());
|
||||
EXPECT_EQ(result.second, sequence_.begin());
|
||||
}
|
||||
{
|
||||
auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
|
||||
EXPECT_EQ(result.first, sequence_.begin());
|
||||
EXPECT_EQ(result.second, vector_.begin());
|
||||
}
|
||||
|
||||
sequence_.front() = 0;
|
||||
{
|
||||
auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
|
||||
EXPECT_EQ(result.first, vector_.begin());
|
||||
EXPECT_EQ(result.second, sequence_.begin());
|
||||
}
|
||||
{
|
||||
auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
|
||||
EXPECT_EQ(result.first, std::next(sequence_.begin()));
|
||||
EXPECT_EQ(result.second, std::next(vector_.begin()));
|
||||
}
|
||||
|
||||
sequence_.clear();
|
||||
{
|
||||
auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
|
||||
EXPECT_EQ(result.first, vector_.begin());
|
||||
EXPECT_EQ(result.second, sequence_.end());
|
||||
}
|
||||
{
|
||||
auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
|
||||
EXPECT_EQ(result.first, sequence_.end());
|
||||
EXPECT_EQ(result.second, vector_.begin());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, Equal) {
|
||||
@ -519,11 +593,9 @@ TEST_F(SortingTest, IsSortedUntil) {
|
||||
TEST_F(SortingTest, NthElement) {
|
||||
std::vector<int> unsorted = {2, 4, 1, 3};
|
||||
absl::c_nth_element(unsorted, unsorted.begin() + 2);
|
||||
EXPECT_THAT(unsorted,
|
||||
ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
|
||||
EXPECT_THAT(unsorted, ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
|
||||
absl::c_nth_element(unsorted, unsorted.begin() + 2, std::greater<int>());
|
||||
EXPECT_THAT(unsorted,
|
||||
ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
|
||||
EXPECT_THAT(unsorted, ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
|
||||
}
|
||||
|
||||
TEST(MutatingTest, IsPartitioned) {
|
||||
@ -676,6 +748,15 @@ TEST(MutatingTest, SwapRanges) {
|
||||
absl::c_swap_ranges(odds, evens);
|
||||
EXPECT_THAT(odds, ElementsAre(1, 3, 5));
|
||||
EXPECT_THAT(evens, ElementsAre(2, 4, 6));
|
||||
|
||||
odds.pop_back();
|
||||
absl::c_swap_ranges(odds, evens);
|
||||
EXPECT_THAT(odds, ElementsAre(2, 4));
|
||||
EXPECT_THAT(evens, ElementsAre(1, 3, 6));
|
||||
|
||||
absl::c_swap_ranges(evens, odds);
|
||||
EXPECT_THAT(odds, ElementsAre(1, 3));
|
||||
EXPECT_THAT(evens, ElementsAre(2, 4, 6));
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, Transform) {
|
||||
@ -690,6 +771,20 @@ TEST_F(NonMutatingTest, Transform) {
|
||||
EXPECT_EQ(std::vector<int>({1, 5, 4}), z);
|
||||
*end = 7;
|
||||
EXPECT_EQ(std::vector<int>({1, 5, 4, 7}), z);
|
||||
|
||||
z.clear();
|
||||
y.pop_back();
|
||||
end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
|
||||
EXPECT_EQ(std::vector<int>({1, 5}), z);
|
||||
*end = 7;
|
||||
EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
|
||||
|
||||
z.clear();
|
||||
std::swap(x, y);
|
||||
end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
|
||||
EXPECT_EQ(std::vector<int>({1, 5}), z);
|
||||
*end = 7;
|
||||
EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
|
||||
}
|
||||
|
||||
TEST(MutatingTest, Replace) {
|
||||
@ -755,10 +850,9 @@ MATCHER_P2(IsElement, key, value, "") {
|
||||
TEST(MutatingTest, StableSort) {
|
||||
std::vector<Element> test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}};
|
||||
absl::c_stable_sort(test_vector);
|
||||
EXPECT_THAT(
|
||||
test_vector,
|
||||
ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
|
||||
IsElement(2, 0), IsElement(2, 2)));
|
||||
EXPECT_THAT(test_vector,
|
||||
ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
|
||||
IsElement(2, 0), IsElement(2, 2)));
|
||||
}
|
||||
|
||||
TEST(MutatingTest, StableSortWithPredicate) {
|
||||
@ -766,10 +860,9 @@ TEST(MutatingTest, StableSortWithPredicate) {
|
||||
absl::c_stable_sort(test_vector, [](const Element& e1, const Element& e2) {
|
||||
return e2 < e1;
|
||||
});
|
||||
EXPECT_THAT(
|
||||
test_vector,
|
||||
ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
|
||||
IsElement(1, 1), IsElement(1, 0)));
|
||||
EXPECT_THAT(test_vector,
|
||||
ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
|
||||
IsElement(1, 1), IsElement(1, 0)));
|
||||
}
|
||||
|
||||
TEST(MutatingTest, ReplaceCopyIf) {
|
||||
|
||||
229
third_party/abseil-cpp/absl/base/BUILD.bazel
vendored
229
third_party/abseil-cpp/absl/base/BUILD.bazel
vendored
@ -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",
|
||||
@ -24,7 +23,7 @@ load(
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "atomic_hook",
|
||||
@ -115,11 +114,18 @@ cc_library(
|
||||
|
||||
cc_library(
|
||||
name = "dynamic_annotations",
|
||||
srcs = ["dynamic_annotations.cc"],
|
||||
hdrs = ["dynamic_annotations.h"],
|
||||
srcs = [
|
||||
"internal/dynamic_annotations.h",
|
||||
],
|
||||
hdrs = [
|
||||
"dynamic_annotations.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
defines = ["__CLANG_SUPPORT_DYN_ANNOTATION__"],
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
@ -153,7 +159,9 @@ cc_library(
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = select({
|
||||
"//absl:windows": [],
|
||||
"//absl:msvc_compiler": [],
|
||||
"//absl:clang-cl_compiler": [],
|
||||
"//absl:wasm": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}) + ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
@ -212,9 +220,13 @@ cc_library(
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = select({
|
||||
"//absl:windows": [
|
||||
"//absl:msvc_compiler": [
|
||||
"-DEFAULTLIB:advapi32.lib",
|
||||
],
|
||||
"//absl:clang-cl_compiler": [
|
||||
"-DEFAULTLIB:advapi32.lib",
|
||||
],
|
||||
"//absl:wasm": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}) + ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
@ -307,6 +319,7 @@ cc_test(
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":errno_saver",
|
||||
":strerror",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
@ -405,6 +418,7 @@ cc_library(
|
||||
deps = [
|
||||
":base",
|
||||
":base_internal",
|
||||
":config",
|
||||
":core_headers",
|
||||
"//absl/synchronization",
|
||||
"@com_google_googletest//:gtest",
|
||||
@ -421,6 +435,7 @@ cc_test(
|
||||
deps = [
|
||||
":base",
|
||||
":base_internal",
|
||||
":config",
|
||||
":core_headers",
|
||||
"//absl/synchronization",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
@ -451,6 +466,7 @@ cc_binary(
|
||||
testonly = 1,
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
tags = ["benchmark"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":spinlock_benchmark_common",
|
||||
@ -466,6 +482,7 @@ cc_library(
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":base",
|
||||
":config",
|
||||
":core_headers",
|
||||
],
|
||||
@ -538,8 +555,13 @@ cc_test(
|
||||
srcs = ["internal/low_level_alloc_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
tags = ["no_test_ios_x86_64"],
|
||||
deps = [":malloc_internal"],
|
||||
tags = [
|
||||
"no_test_ios_x86_64",
|
||||
],
|
||||
deps = [
|
||||
":malloc_internal",
|
||||
"//absl/container:node_hash_map",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
@ -570,100 +592,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,
|
||||
@ -705,3 +633,98 @@ cc_test(
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "strerror",
|
||||
srcs = ["internal/strerror.cc"],
|
||||
hdrs = ["internal/strerror.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
"//absl:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers",
|
||||
":errno_saver",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "strerror_test",
|
||||
size = "small",
|
||||
srcs = ["internal/strerror_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":strerror",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "strerror_benchmark",
|
||||
testonly = 1,
|
||||
srcs = ["internal/strerror_benchmark.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
tags = ["benchmark"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":strerror",
|
||||
"@com_github_google_benchmark//:benchmark_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "fast_type_id",
|
||||
hdrs = ["internal/fast_type_id.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
"//absl:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":config",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "fast_type_id_test",
|
||||
size = "small",
|
||||
srcs = ["internal/fast_type_id_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":fast_type_id",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "unique_small_name_test",
|
||||
size = "small",
|
||||
srcs = ["internal/unique_small_name_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
linkstatic = 1,
|
||||
deps = [
|
||||
":core_headers",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "optimization_test",
|
||||
size = "small",
|
||||
srcs = ["optimization_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":core_headers",
|
||||
"//absl/types:optional",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
206
third_party/abseil-cpp/absl/base/CMakeLists.txt
vendored
206
third_party/abseil-cpp/absl/base/CMakeLists.txt
vendored
@ -105,11 +105,11 @@ absl_cc_library(
|
||||
HDRS
|
||||
"dynamic_annotations.h"
|
||||
SRCS
|
||||
"dynamic_annotations.cc"
|
||||
"internal/dynamic_annotations.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEFINES
|
||||
"__CLANG_SUPPORT_DYN_ANNOTATION__"
|
||||
DEPS
|
||||
absl::config
|
||||
PUBLIC
|
||||
)
|
||||
|
||||
@ -191,7 +191,7 @@ absl_cc_library(
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
$<$<BOOL:${LIBRT}>:${LIBRT}>
|
||||
$<$<BOOL:${LIBRT}>:-lrt>
|
||||
$<$<BOOL:${MINGW}>:"advapi32">
|
||||
DEPS
|
||||
absl::atomic_hook
|
||||
@ -230,7 +230,7 @@ absl_cc_library(
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
gtest
|
||||
GTest::gtest
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -259,7 +259,7 @@ absl_cc_library(
|
||||
absl::meta
|
||||
absl::strings
|
||||
absl::utility
|
||||
gtest
|
||||
GTest::gtest
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -273,7 +273,7 @@ absl_cc_test(
|
||||
DEPS
|
||||
absl::exception_safety_testing
|
||||
absl::memory
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -300,8 +300,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 +314,7 @@ absl_cc_test(
|
||||
DEPS
|
||||
absl::base
|
||||
absl::core_headers
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -326,8 +326,9 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::errno_saver
|
||||
gmock
|
||||
gtest_main
|
||||
absl::strerror
|
||||
GTest::gmock
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -341,7 +342,7 @@ absl_cc_test(
|
||||
absl::base
|
||||
absl::config
|
||||
absl::throw_delegate
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -356,7 +357,7 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::base_internal
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -370,8 +371,8 @@ absl_cc_test(
|
||||
absl::base_internal
|
||||
absl::memory
|
||||
absl::strings
|
||||
gmock
|
||||
gtest_main
|
||||
GTest::gmock
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -383,10 +384,11 @@ absl_cc_library(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::base
|
||||
absl::config
|
||||
absl::base_internal
|
||||
absl::core_headers
|
||||
absl::synchronization
|
||||
gtest
|
||||
GTest::gtest
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -401,9 +403,10 @@ absl_cc_test(
|
||||
DEPS
|
||||
absl::base
|
||||
absl::base_internal
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::synchronization
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -415,6 +418,7 @@ absl_cc_library(
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::base
|
||||
absl::config
|
||||
absl::core_headers
|
||||
PUBLIC
|
||||
@ -431,7 +435,7 @@ absl_cc_test(
|
||||
absl::base
|
||||
absl::config
|
||||
absl::endian
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -444,7 +448,7 @@ absl_cc_test(
|
||||
DEPS
|
||||
absl::config
|
||||
absl::synchronization
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -458,7 +462,7 @@ absl_cc_test(
|
||||
absl::base
|
||||
absl::core_headers
|
||||
absl::synchronization
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -471,7 +475,7 @@ absl_cc_test(
|
||||
DEPS
|
||||
absl::raw_logging_internal
|
||||
absl::strings
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -484,7 +488,7 @@ absl_cc_test(
|
||||
DEPS
|
||||
absl::base
|
||||
absl::synchronization
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -496,6 +500,7 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::malloc_internal
|
||||
absl::node_hash_map
|
||||
Threads::Threads
|
||||
)
|
||||
|
||||
@ -511,85 +516,7 @@ 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
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -615,7 +542,7 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::scoped_set_env
|
||||
gtest_main
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -639,6 +566,75 @@ absl_cc_test(
|
||||
absl::flags_marshalling
|
||||
absl::log_severity
|
||||
absl::strings
|
||||
gmock
|
||||
gtest_main
|
||||
GTest::gmock
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
strerror
|
||||
SRCS
|
||||
"internal/strerror.cc"
|
||||
HDRS
|
||||
"internal/strerror.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::errno_saver
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
strerror_test
|
||||
SRCS
|
||||
"internal/strerror_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::strerror
|
||||
absl::strings
|
||||
GTest::gmock
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
fast_type_id
|
||||
HDRS
|
||||
"internal/fast_type_id.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
fast_type_id_test
|
||||
SRCS
|
||||
"internal/fast_type_id_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::fast_type_id
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
optimization_test
|
||||
SRCS
|
||||
"optimization_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::core_headers
|
||||
absl::optional
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
224
third_party/abseil-cpp/absl/base/attributes.h
vendored
224
third_party/abseil-cpp/absl/base/attributes.h
vendored
@ -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.
|
||||
//
|
||||
@ -32,34 +30,12 @@
|
||||
// of them are not supported in older version of Clang. Thus, we check
|
||||
// `__has_attribute()` first. If the check fails, we check if we are on GCC and
|
||||
// assume the attribute exists on GCC (which is verified on GCC 4.7).
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// Sanitizer Attributes
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Sanitizer-related attributes are not "defined" in this file (and indeed
|
||||
// are not defined as such in any file). To utilize the following
|
||||
// sanitizer-related attributes within your builds, define the following macros
|
||||
// within your build using a `-D` flag, along with the given value for
|
||||
// `-fsanitize`:
|
||||
//
|
||||
// * `ADDRESS_SANITIZER` + `-fsanitize=address` (Clang, GCC 4.8)
|
||||
// * `MEMORY_SANITIZER` + `-fsanitize=memory` (Clang-only)
|
||||
// * `THREAD_SANITIZER + `-fsanitize=thread` (Clang, GCC 4.8+)
|
||||
// * `UNDEFINED_BEHAVIOR_SANITIZER` + `-fsanitize=undefined` (Clang, GCC 4.9+)
|
||||
// * `CONTROL_FLOW_INTEGRITY` + -fsanitize=cfi (Clang-only)
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // Enable branches in the Abseil code that are tagged for ASan:
|
||||
// $ bazel build --copt=-DADDRESS_SANITIZER --copt=-fsanitize=address
|
||||
// --linkopt=-fsanitize=address *target*
|
||||
//
|
||||
// Since these macro names are only supported by GCC and Clang, we only check
|
||||
// for `__GNUC__` (GCC or Clang) and the above macros.
|
||||
|
||||
#ifndef ABSL_BASE_ATTRIBUTES_H_
|
||||
#define ABSL_BASE_ATTRIBUTES_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
// ABSL_HAVE_ATTRIBUTE
|
||||
//
|
||||
// A function-like feature checking macro that is a wrapper around
|
||||
@ -143,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")))
|
||||
@ -155,14 +131,14 @@
|
||||
// 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__)
|
||||
(!defined(_WIN32) || __clang_major__ < 9) && !defined(__MINGW32__)
|
||||
#undef ABSL_ATTRIBUTE_WEAK
|
||||
#define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
|
||||
#define ABSL_HAVE_ATTRIBUTE_WEAK 1
|
||||
@ -234,7 +210,7 @@
|
||||
// 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 defined(__GNUC__)
|
||||
#if ABSL_HAVE_ATTRIBUTE(no_sanitize_address)
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
|
||||
@ -242,13 +218,13 @@
|
||||
|
||||
// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
|
||||
//
|
||||
// Tells the MemorySanitizer to relax the handling of a given function. All
|
||||
// "Use of uninitialized value" warnings from such functions will be suppressed,
|
||||
// and all values loaded from memory will be considered fully initialized.
|
||||
// This attribute is similar to the ADDRESS_SANITIZER attribute above, but deals
|
||||
// with initialized-ness rather than addressability issues.
|
||||
// Tells the MemorySanitizer to relax the handling of a given function. All "Use
|
||||
// of uninitialized value" warnings from such functions will be suppressed, and
|
||||
// all values loaded from memory will be considered fully initialized. This
|
||||
// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute
|
||||
// above, but deals with initialized-ness rather than addressability issues.
|
||||
// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC.
|
||||
#if defined(__clang__)
|
||||
#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory)
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
|
||||
@ -259,7 +235,7 @@
|
||||
// Tells the ThreadSanitizer to not instrument a given function.
|
||||
// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8.
|
||||
// https://gcc.gnu.org/gcc-4.8/changes.html
|
||||
#if defined(__GNUC__)
|
||||
#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread)
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD
|
||||
@ -271,8 +247,10 @@
|
||||
// where certain behavior (eg. division by zero) is being used intentionally.
|
||||
// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9.
|
||||
// https://gcc.gnu.org/gcc-4.9/changes.html
|
||||
#if defined(__GNUC__) && \
|
||||
(defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER))
|
||||
#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined)
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
|
||||
__attribute__((no_sanitize_undefined))
|
||||
#elif ABSL_HAVE_ATTRIBUTE(no_sanitize)
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
|
||||
__attribute__((no_sanitize("undefined")))
|
||||
#else
|
||||
@ -283,7 +261,7 @@
|
||||
//
|
||||
// Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
|
||||
// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.
|
||||
#if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY)
|
||||
#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
|
||||
@ -293,7 +271,7 @@
|
||||
//
|
||||
// Tells the SafeStack to not instrument a given function.
|
||||
// See https://clang.llvm.org/docs/SafeStack.html for details.
|
||||
#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER)
|
||||
#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
|
||||
#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \
|
||||
__attribute__((no_sanitize("safe-stack")))
|
||||
#else
|
||||
@ -303,10 +281,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
|
||||
@ -343,8 +318,16 @@
|
||||
// `__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 achived 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
|
||||
//
|
||||
@ -507,8 +490,10 @@
|
||||
// packages/targets, as this may lead to conflicting definitions of functions at
|
||||
// link-time.
|
||||
//
|
||||
// XRay isn't currently supported on Android:
|
||||
// https://github.com/android/ndk/issues/368
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \
|
||||
!defined(ABSL_NO_XRAY_ATTRIBUTES)
|
||||
!defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__)
|
||||
#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]]
|
||||
#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]]
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args)
|
||||
@ -544,6 +529,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__))
|
||||
@ -564,13 +556,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
|
||||
@ -592,6 +590,79 @@
|
||||
#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes)
|
||||
#endif
|
||||
|
||||
// ABSL_FALLTHROUGH_INTENDED
|
||||
//
|
||||
// Annotates implicit fall-through between switch labels, allowing a case to
|
||||
// indicate intentional fallthrough and turn off warnings about any lack of a
|
||||
// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by
|
||||
// a semicolon and can be used in most places where `break` can, provided that
|
||||
// no statements exist between it and the next switch label.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// switch (x) {
|
||||
// case 40:
|
||||
// case 41:
|
||||
// if (truth_is_out_there) {
|
||||
// ++x;
|
||||
// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations
|
||||
// // in comments
|
||||
// } else {
|
||||
// return x;
|
||||
// }
|
||||
// case 42:
|
||||
// ...
|
||||
//
|
||||
// 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
|
||||
// behavior and performance of code.
|
||||
|
||||
#ifdef ABSL_FALLTHROUGH_INTENDED
|
||||
#error "ABSL_FALLTHROUGH_INTENDED should not be defined."
|
||||
#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough)
|
||||
#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]]
|
||||
#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough)
|
||||
#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
|
||||
#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough)
|
||||
#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
|
||||
#else
|
||||
#define ABSL_FALLTHROUGH_INTENDED \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
// ABSL_DEPRECATED()
|
||||
//
|
||||
// Marks a deprecated class, struct, enum, function, method and variable
|
||||
// declarations. The macro argument is used as a custom diagnostic message (e.g.
|
||||
// suggestion of a better alternative).
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// class ABSL_DEPRECATED("Use Bar instead") Foo {...};
|
||||
//
|
||||
// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...}
|
||||
//
|
||||
// template <typename T>
|
||||
// ABSL_DEPRECATED("Use DoThat() instead")
|
||||
// void DoThis();
|
||||
//
|
||||
// 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__) && defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#define ABSL_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
#endif
|
||||
|
||||
#ifndef ABSL_DEPRECATED
|
||||
#define ABSL_DEPRECATED(message)
|
||||
#endif
|
||||
|
||||
// ABSL_CONST_INIT
|
||||
//
|
||||
// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will
|
||||
@ -618,4 +689,47 @@
|
||||
#define ABSL_CONST_INIT
|
||||
#endif // ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
|
||||
|
||||
// ABSL_ATTRIBUTE_PURE_FUNCTION
|
||||
//
|
||||
// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure"
|
||||
// functions. A function is pure if its return value is only a function of its
|
||||
// arguments. The pure attribute prohibits a function from modifying the state
|
||||
// of the program that is observable by means other than inspecting the
|
||||
// function's return value. Declaring such functions with the pure attribute
|
||||
// allows the compiler to avoid emitting some calls in repeated invocations of
|
||||
// the function with the same argument values.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d);
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure)
|
||||
#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]]
|
||||
#elif ABSL_HAVE_ATTRIBUTE(pure)
|
||||
#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure))
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_PURE_FUNCTION
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
||||
#endif // ABSL_BASE_ATTRIBUTES_H_
|
||||
|
||||
13
third_party/abseil-cpp/absl/base/call_once.h
vendored
13
third_party/abseil-cpp/absl/base/call_once.h
vendored
@ -175,17 +175,10 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
|
||||
std::memory_order_relaxed) ||
|
||||
base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,
|
||||
scheduling_mode) == kOnceInit) {
|
||||
base_internal::Invoke(std::forward<Callable>(fn),
|
||||
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);
|
||||
}
|
||||
|
||||
15
third_party/abseil-cpp/absl/base/casts.h
vendored
15
third_party/abseil-cpp/absl/base/casts.h
vendored
@ -159,16 +159,19 @@ inline Dest bit_cast(const Source& source) {
|
||||
return dest;
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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>
|
||||
!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.")
|
||||
"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.");
|
||||
|
||||
199
third_party/abseil-cpp/absl/base/config.h
vendored
199
third_party/abseil-cpp/absl/base/config.h
vendored
@ -66,6 +66,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 20211102
|
||||
#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 +150,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
|
||||
@ -154,6 +189,28 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#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.
|
||||
@ -171,10 +228,9 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
// 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)
|
||||
#elif defined(_LIBCPP_VERSION) || defined(_MSC_VER) || \
|
||||
(!defined(__clang__) && defined(__GLIBCXX__) && \
|
||||
ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(4, 8))
|
||||
#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1
|
||||
#endif
|
||||
|
||||
@ -187,16 +243,17 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
//
|
||||
// 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).
|
||||
// Notes: Clang with libc++ supports these features, as does gcc >= 7.4 with
|
||||
// libstdc++, or gcc >= 8.2 with libc++, 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__))) || \
|
||||
#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \
|
||||
(!defined(__clang__) && \
|
||||
((ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(7, 4) && defined(__GLIBCXX__)) || \
|
||||
(ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(8, 2) && \
|
||||
defined(_LIBCPP_VERSION)))) || \
|
||||
(defined(_MSC_VER) && !defined(__NVCC__))
|
||||
#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
|
||||
#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
|
||||
@ -210,6 +267,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#if ABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \
|
||||
ABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE)
|
||||
#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
|
||||
#elif ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0)
|
||||
#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -226,11 +285,9 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
|
||||
// targeting iOS 9.x.
|
||||
// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
|
||||
// making __has_feature unreliable there.
|
||||
// making ABSL_HAVE_FEATURE unreliable there.
|
||||
//
|
||||
// Otherwise, `__has_feature` is only supported by Clang so it has be inside
|
||||
// `defined(__APPLE__)` check.
|
||||
#if __has_feature(cxx_thread_local) && \
|
||||
#if ABSL_HAVE_FEATURE(cxx_thread_local) && \
|
||||
!(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
|
||||
#define ABSL_HAVE_THREAD_LOCAL 1
|
||||
#endif
|
||||
@ -262,13 +319,6 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#endif
|
||||
#endif // defined(__ANDROID__) && defined(__clang__)
|
||||
|
||||
// Emscripten doesn't yet support `thread_local` or `__thread`.
|
||||
// https://github.com/emscripten-core/emscripten/issues/3502
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
#undef ABSL_HAVE_TLS
|
||||
#undef ABSL_HAVE_THREAD_LOCAL
|
||||
#endif // defined(__EMSCRIPTEN__)
|
||||
|
||||
// ABSL_HAVE_INTRINSIC_INT128
|
||||
//
|
||||
// Checks whether the __int128 compiler extension for a 128-bit integral type is
|
||||
@ -314,25 +364,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 __has_feature(cxx_exceptions)
|
||||
#if ABSL_HAVE_FEATURE(cxx_exceptions)
|
||||
#define ABSL_HAVE_EXCEPTIONS 1
|
||||
#endif // __has_feature(cxx_exceptions)
|
||||
#else
|
||||
#endif // ABSL_HAVE_FEATURE(cxx_exceptions)
|
||||
#elif defined(__clang__)
|
||||
// Clang < 3.6
|
||||
// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
|
||||
#if defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
|
||||
#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
|
||||
#define ABSL_HAVE_EXCEPTIONS 1
|
||||
#endif // defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
|
||||
#endif // __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
|
||||
|
||||
#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
|
||||
// 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
|
||||
@ -364,10 +410,11 @@ 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__)
|
||||
#define ABSL_HAVE_MMAP 1
|
||||
#endif
|
||||
|
||||
@ -378,10 +425,19 @@ 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__)
|
||||
#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
|
||||
@ -477,9 +533,9 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
(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__ < 120000) || \
|
||||
__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
|
||||
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 50000))
|
||||
__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
|
||||
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
|
||||
#else
|
||||
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
|
||||
@ -493,7 +549,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#endif
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include(<any>) && __cplusplus >= 201703L && \
|
||||
#if __has_include(<any>) && defined(__cplusplus) && __cplusplus >= 201703L && \
|
||||
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
|
||||
#define ABSL_HAVE_STD_ANY 1
|
||||
#endif
|
||||
@ -507,8 +563,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#endif
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include(<optional>) && __cplusplus >= 201703L && \
|
||||
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
|
||||
#if __has_include(<optional>) && defined(__cplusplus) && \
|
||||
__cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
|
||||
#define ABSL_HAVE_STD_OPTIONAL 1
|
||||
#endif
|
||||
#endif
|
||||
@ -521,8 +577,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#endif
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include(<variant>) && __cplusplus >= 201703L && \
|
||||
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
|
||||
#if __has_include(<variant>) && defined(__cplusplus) && \
|
||||
__cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
|
||||
#define ABSL_HAVE_STD_VARIANT 1
|
||||
#endif
|
||||
#endif
|
||||
@ -535,7 +591,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#endif
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include(<string_view>) && __cplusplus >= 201703L
|
||||
#if __has_include(<string_view>) && defined(__cplusplus) && \
|
||||
__cplusplus >= 201703L
|
||||
#define ABSL_HAVE_STD_STRING_VIEW 1
|
||||
#endif
|
||||
#endif
|
||||
@ -547,8 +604,9 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
// 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)
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1910 && \
|
||||
((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || \
|
||||
(defined(__cplusplus) && __cplusplus > 201402))
|
||||
// #define ABSL_HAVE_STD_ANY 1
|
||||
#define ABSL_HAVE_STD_OPTIONAL 1
|
||||
#define ABSL_HAVE_STD_VARIANT 1
|
||||
@ -668,4 +726,47 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
||||
#define ABSL_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(__SANITIZE_MEMORY__)
|
||||
#define ABSL_HAVE_MEMORY_SANITIZER 1
|
||||
#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer)
|
||||
#define ABSL_HAVE_MEMORY_SANITIZER 1
|
||||
#endif
|
||||
|
||||
// ABSL_HAVE_THREAD_SANITIZER
|
||||
//
|
||||
// ThreadSanitizer (TSan) is a fast data race detector.
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#error "ABSL_HAVE_THREAD_SANITIZER cannot be directly set."
|
||||
#elif defined(__SANITIZE_THREAD__)
|
||||
#define ABSL_HAVE_THREAD_SANITIZER 1
|
||||
#elif ABSL_HAVE_FEATURE(thread_sanitizer)
|
||||
#define ABSL_HAVE_THREAD_SANITIZER 1
|
||||
#endif
|
||||
|
||||
// ABSL_HAVE_ADDRESS_SANITIZER
|
||||
//
|
||||
// AddressSanitizer (ASan) is a fast memory error detector.
|
||||
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
|
||||
#error "ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set."
|
||||
#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_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
|
||||
|
||||
#endif // ABSL_BASE_CONFIG_H_
|
||||
|
||||
@ -1,129 +0,0 @@
|
||||
// Copyright 2017 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "absl/base/dynamic_annotations.h"
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
/* Compiler-based ThreadSanitizer defines
|
||||
DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
|
||||
and provides its own definitions of the functions. */
|
||||
|
||||
#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
|
||||
# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
|
||||
#endif
|
||||
|
||||
/* Each function is empty and called (via a macro) only in debug mode.
|
||||
The arguments are captured by dynamic tools at runtime. */
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 && !defined(__native_client__)
|
||||
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#include <sanitizer/msan_interface.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void AnnotateRWLockCreate(const char *, int,
|
||||
const volatile void *){}
|
||||
void AnnotateRWLockDestroy(const char *, int,
|
||||
const volatile void *){}
|
||||
void AnnotateRWLockAcquired(const char *, int,
|
||||
const volatile void *, long){}
|
||||
void AnnotateRWLockReleased(const char *, int,
|
||||
const volatile void *, long){}
|
||||
void AnnotateBenignRace(const char *, int,
|
||||
const volatile void *,
|
||||
const char *){}
|
||||
void AnnotateBenignRaceSized(const char *, int,
|
||||
const volatile void *,
|
||||
size_t,
|
||||
const char *) {}
|
||||
void AnnotateThreadName(const char *, int,
|
||||
const char *){}
|
||||
void AnnotateIgnoreReadsBegin(const char *, int){}
|
||||
void AnnotateIgnoreReadsEnd(const char *, int){}
|
||||
void AnnotateIgnoreWritesBegin(const char *, int){}
|
||||
void AnnotateIgnoreWritesEnd(const char *, int){}
|
||||
void AnnotateEnableRaceDetection(const char *, int, int){}
|
||||
void AnnotateMemoryIsInitialized(const char *, int,
|
||||
const volatile void *mem, size_t size) {
|
||||
#if __has_feature(memory_sanitizer)
|
||||
__msan_unpoison(mem, size);
|
||||
#else
|
||||
(void)mem;
|
||||
(void)size;
|
||||
#endif
|
||||
}
|
||||
|
||||
void AnnotateMemoryIsUninitialized(const char *, int,
|
||||
const volatile void *mem, size_t size) {
|
||||
#if __has_feature(memory_sanitizer)
|
||||
__msan_allocated_memory(mem, size);
|
||||
#else
|
||||
(void)mem;
|
||||
(void)size;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int GetRunningOnValgrind(void) {
|
||||
#ifdef RUNNING_ON_VALGRIND
|
||||
if (RUNNING_ON_VALGRIND) return 1;
|
||||
#endif
|
||||
char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND");
|
||||
if (running_on_valgrind_str) {
|
||||
return strcmp(running_on_valgrind_str, "0") != 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See the comments in dynamic_annotations.h */
|
||||
int RunningOnValgrind(void) {
|
||||
static volatile int running_on_valgrind = -1;
|
||||
int local_running_on_valgrind = running_on_valgrind;
|
||||
/* C doesn't have thread-safe initialization of statics, and we
|
||||
don't want to depend on pthread_once here, so hack it. */
|
||||
ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack");
|
||||
if (local_running_on_valgrind == -1)
|
||||
running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
|
||||
return local_running_on_valgrind;
|
||||
}
|
||||
|
||||
/* See the comments in dynamic_annotations.h */
|
||||
double ValgrindSlowdown(void) {
|
||||
/* Same initialization hack as in RunningOnValgrind(). */
|
||||
static volatile double slowdown = 0.0;
|
||||
double local_slowdown = slowdown;
|
||||
ANNOTATE_BENIGN_RACE(&slowdown, "safe hack");
|
||||
if (RunningOnValgrind() == 0) {
|
||||
return 1.0;
|
||||
}
|
||||
if (local_slowdown == 0.0) {
|
||||
char *env = getenv("VALGRIND_SLOWDOWN");
|
||||
slowdown = local_slowdown = env ? atof(env) : 50.0;
|
||||
}
|
||||
return local_slowdown;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
|
||||
@ -1,389 +1,471 @@
|
||||
/*
|
||||
* Copyright 2017 The Abseil Authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/* This file defines dynamic annotations for use with dynamic analysis
|
||||
tool such as valgrind, PIN, etc.
|
||||
// Copyright 2017 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.
|
||||
|
||||
Dynamic annotation is a source code annotation that affects
|
||||
the generated code (that is, the annotation is not a comment).
|
||||
Each such annotation is attached to a particular
|
||||
instruction and/or to a particular object (address) in the program.
|
||||
|
||||
The annotations that should be used by users are macros in all upper-case
|
||||
(e.g., ANNOTATE_THREAD_NAME).
|
||||
|
||||
Actual implementation of these macros may differ depending on the
|
||||
dynamic analysis tool being used.
|
||||
|
||||
This file supports the following configurations:
|
||||
- Dynamic Annotations enabled (with static thread-safety warnings disabled).
|
||||
In this case, macros expand to functions implemented by Thread Sanitizer,
|
||||
when building with TSan. When not provided an external implementation,
|
||||
dynamic_annotations.cc provides no-op implementations.
|
||||
|
||||
- Static Clang thread-safety warnings enabled.
|
||||
When building with a Clang compiler that supports thread-safety warnings,
|
||||
a subset of annotations can be statically-checked at compile-time. We
|
||||
expand these macros to static-inline functions that can be analyzed for
|
||||
thread-safety, but afterwards elided when building the final binary.
|
||||
|
||||
- All annotations are disabled.
|
||||
If neither Dynamic Annotations nor Clang thread-safety warnings are
|
||||
enabled, then all annotation-macros expand to empty. */
|
||||
// This file defines dynamic annotations for use with dynamic analysis tool
|
||||
// such as valgrind, PIN, etc.
|
||||
//
|
||||
// Dynamic annotation is a source code annotation that affects the generated
|
||||
// code (that is, the annotation is not a comment). Each such annotation is
|
||||
// attached to a particular instruction and/or to a particular object (address)
|
||||
// in the program.
|
||||
//
|
||||
// The annotations that should be used by users are macros in all upper-case
|
||||
// (e.g., ABSL_ANNOTATE_THREAD_NAME).
|
||||
//
|
||||
// Actual implementation of these macros may differ depending on the dynamic
|
||||
// analysis tool being used.
|
||||
//
|
||||
// This file supports the following configurations:
|
||||
// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
|
||||
// In this case, macros expand to functions implemented by Thread Sanitizer,
|
||||
// when building with TSan. When not provided an external implementation,
|
||||
// dynamic_annotations.cc provides no-op implementations.
|
||||
//
|
||||
// - Static Clang thread-safety warnings enabled.
|
||||
// When building with a Clang compiler that supports thread-safety warnings,
|
||||
// a subset of annotations can be statically-checked at compile-time. We
|
||||
// expand these macros to static-inline functions that can be analyzed for
|
||||
// thread-safety, but afterwards elided when building the final binary.
|
||||
//
|
||||
// - All annotations are disabled.
|
||||
// If neither Dynamic Annotations nor Clang thread-safety warnings are
|
||||
// enabled, then all annotation-macros expand to empty.
|
||||
|
||||
#ifndef ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
|
||||
#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
|
||||
|
||||
#ifndef DYNAMIC_ANNOTATIONS_ENABLED
|
||||
# define DYNAMIC_ANNOTATIONS_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations that suppress errors. It is usually better to express the
|
||||
program's synchronization using the other annotations, but these can
|
||||
be used when all else fails. */
|
||||
|
||||
/* Report that we may have a benign race at "pointer", with size
|
||||
"sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the
|
||||
point where "pointer" has been allocated, preferably close to the point
|
||||
where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC. */
|
||||
#define ANNOTATE_BENIGN_RACE(pointer, description) \
|
||||
AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \
|
||||
sizeof(*(pointer)), description)
|
||||
|
||||
/* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
|
||||
the memory range [address, address+size). */
|
||||
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
|
||||
AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
|
||||
|
||||
/* Enable (enable!=0) or disable (enable==0) race detection for all threads.
|
||||
This annotation could be useful if you want to skip expensive race analysis
|
||||
during some period of program execution, e.g. during initialization. */
|
||||
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
|
||||
AnnotateEnableRaceDetection(__FILE__, __LINE__, enable)
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations useful for debugging. */
|
||||
|
||||
/* Report the current thread name to a race detector. */
|
||||
#define ANNOTATE_THREAD_NAME(name) \
|
||||
AnnotateThreadName(__FILE__, __LINE__, name)
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
Annotations useful when implementing locks. They are not
|
||||
normally needed by modules that merely use locks.
|
||||
The "lock" argument is a pointer to the lock object. */
|
||||
|
||||
/* Report that a lock has been created at address "lock". */
|
||||
#define ANNOTATE_RWLOCK_CREATE(lock) \
|
||||
AnnotateRWLockCreate(__FILE__, __LINE__, lock)
|
||||
|
||||
/* Report that a linker initialized lock has been created at address "lock".
|
||||
*/
|
||||
#ifdef THREAD_SANITIZER
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
AnnotateRWLockCreateStatic(__FILE__, __LINE__, lock)
|
||||
#else
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
|
||||
#endif
|
||||
|
||||
/* Report that the lock at address "lock" is about to be destroyed. */
|
||||
#define ANNOTATE_RWLOCK_DESTROY(lock) \
|
||||
AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
|
||||
|
||||
/* Report that the lock at address "lock" has been acquired.
|
||||
is_w=1 for writer lock, is_w=0 for reader lock. */
|
||||
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
|
||||
AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
/* Report that the lock at address "lock" is about to be released. */
|
||||
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
|
||||
AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
|
||||
|
||||
#define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) /* empty */
|
||||
#define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
|
||||
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
|
||||
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
|
||||
#define ANNOTATE_BENIGN_RACE(address, description) /* empty */
|
||||
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
|
||||
#define ANNOTATE_THREAD_NAME(name) /* empty */
|
||||
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
|
||||
|
||||
#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
|
||||
|
||||
/* These annotations are also made available to LLVM's Memory Sanitizer */
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED == 1 || defined(MEMORY_SANITIZER)
|
||||
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
AnnotateMemoryIsInitialized(__FILE__, __LINE__, address, size)
|
||||
|
||||
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
AnnotateMemoryIsUninitialized(__FILE__, __LINE__, address, size)
|
||||
#else
|
||||
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */
|
||||
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */
|
||||
#endif /* DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */
|
||||
|
||||
/* TODO(delesley) -- Replace __CLANG_SUPPORT_DYN_ANNOTATION__ with the
|
||||
appropriate feature ID. */
|
||||
#if defined(__clang__) && (!defined(SWIG)) \
|
||||
&& defined(__CLANG_SUPPORT_DYN_ANNOTATION__)
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED == 0
|
||||
#define ANNOTALYSIS_ENABLED
|
||||
#endif
|
||||
|
||||
/* When running in opt-mode, GCC will issue a warning, if these attributes are
|
||||
compiled. Only include them when compiling using Clang. */
|
||||
#define ATTRIBUTE_IGNORE_READS_BEGIN \
|
||||
__attribute((exclusive_lock_function("*")))
|
||||
#define ATTRIBUTE_IGNORE_READS_END \
|
||||
__attribute((unlock_function("*")))
|
||||
#else
|
||||
#define ATTRIBUTE_IGNORE_READS_BEGIN /* empty */
|
||||
#define ATTRIBUTE_IGNORE_READS_END /* empty */
|
||||
#endif /* defined(__clang__) && ... */
|
||||
|
||||
#if (DYNAMIC_ANNOTATIONS_ENABLED != 0) || defined(ANNOTALYSIS_ENABLED)
|
||||
#define ANNOTATIONS_ENABLED
|
||||
#endif
|
||||
|
||||
#if (DYNAMIC_ANNOTATIONS_ENABLED != 0)
|
||||
|
||||
/* Request the analysis tool to ignore all reads in the current thread
|
||||
until ANNOTATE_IGNORE_READS_END is called.
|
||||
Useful to ignore intentional racey reads, while still checking
|
||||
other reads and all writes.
|
||||
See also ANNOTATE_UNPROTECTED_READ. */
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
|
||||
|
||||
/* Stop ignoring reads. */
|
||||
#define ANNOTATE_IGNORE_READS_END() \
|
||||
AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
|
||||
|
||||
/* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead. */
|
||||
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
|
||||
AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
|
||||
|
||||
/* Stop ignoring writes. */
|
||||
#define ANNOTATE_IGNORE_WRITES_END() \
|
||||
AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
|
||||
|
||||
/* Clang provides limited support for static thread-safety analysis
|
||||
through a feature called Annotalysis. We configure macro-definitions
|
||||
according to whether Annotalysis support is available. */
|
||||
#elif defined(ANNOTALYSIS_ENABLED)
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
StaticAnnotateIgnoreReadsBegin(__FILE__, __LINE__)
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_END() \
|
||||
StaticAnnotateIgnoreReadsEnd(__FILE__, __LINE__)
|
||||
|
||||
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
|
||||
StaticAnnotateIgnoreWritesBegin(__FILE__, __LINE__)
|
||||
|
||||
#define ANNOTATE_IGNORE_WRITES_END() \
|
||||
StaticAnnotateIgnoreWritesEnd(__FILE__, __LINE__)
|
||||
|
||||
#else
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
|
||||
#define ANNOTATE_IGNORE_READS_END() /* empty */
|
||||
#define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
|
||||
#define ANNOTATE_IGNORE_WRITES_END() /* empty */
|
||||
#endif
|
||||
|
||||
/* Implement the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
|
||||
primitive annotations defined above. */
|
||||
#if defined(ANNOTATIONS_ENABLED)
|
||||
|
||||
/* Start ignoring all memory accesses (both reads and writes). */
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
|
||||
do { \
|
||||
ANNOTATE_IGNORE_READS_BEGIN(); \
|
||||
ANNOTATE_IGNORE_WRITES_BEGIN(); \
|
||||
}while (0)
|
||||
|
||||
/* Stop ignoring both reads and writes. */
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
|
||||
do { \
|
||||
ANNOTATE_IGNORE_WRITES_END(); \
|
||||
ANNOTATE_IGNORE_READS_END(); \
|
||||
}while (0)
|
||||
|
||||
#else
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
|
||||
#endif
|
||||
|
||||
/* Use the macros above rather than using these functions directly. */
|
||||
#include <stddef.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void AnnotateRWLockCreate(const char *file, int line,
|
||||
const volatile void *lock);
|
||||
void AnnotateRWLockCreateStatic(const char *file, int line,
|
||||
const volatile void *lock);
|
||||
void AnnotateRWLockDestroy(const char *file, int line,
|
||||
const volatile void *lock);
|
||||
void AnnotateRWLockAcquired(const char *file, int line,
|
||||
const volatile void *lock, long is_w); /* NOLINT */
|
||||
void AnnotateRWLockReleased(const char *file, int line,
|
||||
const volatile void *lock, long is_w); /* NOLINT */
|
||||
void AnnotateBenignRace(const char *file, int line,
|
||||
const volatile void *address,
|
||||
const char *description);
|
||||
void AnnotateBenignRaceSized(const char *file, int line,
|
||||
const volatile void *address,
|
||||
size_t size,
|
||||
const char *description);
|
||||
void AnnotateThreadName(const char *file, int line,
|
||||
const char *name);
|
||||
void AnnotateEnableRaceDetection(const char *file, int line, int enable);
|
||||
void AnnotateMemoryIsInitialized(const char *file, int line,
|
||||
const volatile void *mem, size_t size);
|
||||
void AnnotateMemoryIsUninitialized(const char *file, int line,
|
||||
const volatile void *mem, size_t size);
|
||||
|
||||
/* Annotations expand to these functions, when Dynamic Annotations are enabled.
|
||||
These functions are either implemented as no-op calls, if no Sanitizer is
|
||||
attached, or provided with externally-linked implementations by a library
|
||||
like ThreadSanitizer. */
|
||||
void AnnotateIgnoreReadsBegin(const char *file, int line)
|
||||
ATTRIBUTE_IGNORE_READS_BEGIN;
|
||||
void AnnotateIgnoreReadsEnd(const char *file, int line)
|
||||
ATTRIBUTE_IGNORE_READS_END;
|
||||
void AnnotateIgnoreWritesBegin(const char *file, int line);
|
||||
void AnnotateIgnoreWritesEnd(const char *file, int line);
|
||||
|
||||
#if defined(ANNOTALYSIS_ENABLED)
|
||||
/* When Annotalysis is enabled without Dynamic Annotations, the use of
|
||||
static-inline functions allows the annotations to be read at compile-time,
|
||||
while still letting the compiler elide the functions from the final build.
|
||||
|
||||
TODO(delesley) -- The exclusive lock here ignores writes as well, but
|
||||
allows IGNORE_READS_AND_WRITES to work properly. */
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
static inline void StaticAnnotateIgnoreReadsBegin(const char *file, int line)
|
||||
ATTRIBUTE_IGNORE_READS_BEGIN { (void)file; (void)line; }
|
||||
static inline void StaticAnnotateIgnoreReadsEnd(const char *file, int line)
|
||||
ATTRIBUTE_IGNORE_READS_END { (void)file; (void)line; }
|
||||
static inline void StaticAnnotateIgnoreWritesBegin(
|
||||
const char *file, int line) { (void)file; (void)line; }
|
||||
static inline void StaticAnnotateIgnoreWritesEnd(
|
||||
const char *file, int line) { (void)file; (void)line; }
|
||||
#pragma GCC diagnostic pop
|
||||
#include "absl/base/macros.h"
|
||||
#endif
|
||||
|
||||
/* Return non-zero value if running under valgrind.
|
||||
// TODO(rogeeff): Remove after the backward compatibility period.
|
||||
#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export
|
||||
|
||||
If "valgrind.h" is included into dynamic_annotations.cc,
|
||||
the regular valgrind mechanism will be used.
|
||||
See http://valgrind.org/docs/manual/manual-core-adv.html about
|
||||
RUNNING_ON_VALGRIND and other valgrind "client requests".
|
||||
The file "valgrind.h" may be obtained by doing
|
||||
svn co svn://svn.valgrind.org/valgrind/trunk/include
|
||||
// -------------------------------------------------------------------------
|
||||
// Decide which features are enabled.
|
||||
|
||||
If for some reason you can't use "valgrind.h" or want to fake valgrind,
|
||||
there are two ways to make this function return non-zero:
|
||||
- Use environment variable: export RUNNING_ON_VALGRIND=1
|
||||
- Make your tool intercept the function RunningOnValgrind() and
|
||||
change its return value.
|
||||
*/
|
||||
int RunningOnValgrind(void);
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
|
||||
/* ValgrindSlowdown returns:
|
||||
* 1.0, if (RunningOnValgrind() == 0)
|
||||
* 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == NULL)
|
||||
* atof(getenv("VALGRIND_SLOWDOWN")) otherwise
|
||||
This function can be used to scale timeout values:
|
||||
EXAMPLE:
|
||||
for (;;) {
|
||||
DoExpensiveBackgroundTask();
|
||||
SleepForSeconds(5 * ValgrindSlowdown());
|
||||
}
|
||||
*/
|
||||
double ValgrindSlowdown(void);
|
||||
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
|
||||
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
|
||||
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
|
||||
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
|
||||
|
||||
// Clang provides limited support for static thread-safety analysis through a
|
||||
// feature called Annotalysis. We configure macro-definitions according to
|
||||
// whether Annotalysis support is available. When running in opt-mode, GCC
|
||||
// will issue a warning, if these attributes are compiled. Only include them
|
||||
// when compiling using Clang.
|
||||
|
||||
#if defined(__clang__)
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1
|
||||
#if !defined(SWIG)
|
||||
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
|
||||
#endif
|
||||
#else
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
|
||||
#endif
|
||||
|
||||
// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
|
||||
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
|
||||
ABSL_INTERNAL_ANNOTALYSIS_ENABLED
|
||||
|
||||
#endif // ABSL_HAVE_THREAD_SANITIZER
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
|
||||
#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
|
||||
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
|
||||
#define ABSL_INTERNAL_STATIC_INLINE inline
|
||||
#else
|
||||
#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
|
||||
#define ABSL_INTERNAL_END_EXTERN_C // empty
|
||||
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
|
||||
#define ABSL_INTERNAL_STATIC_INLINE static inline
|
||||
#endif
|
||||
|
||||
/* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
|
||||
// -------------------------------------------------------------------------
|
||||
// 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 santizer 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
|
||||
// program's synchronization using the other annotations, but these can be used
|
||||
// when all else fails.
|
||||
|
||||
// Report that we may have a benign race at `pointer`, with size
|
||||
// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
|
||||
// point where `pointer` has been allocated, preferably close to the point
|
||||
// where the race happens. See also ABSL_ANNOTATE_BENIGN_RACE_STATIC.
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE(pointer, description) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
|
||||
(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
|
||||
|
||||
// Same as ABSL_ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
|
||||
// the memory range [`address`, `address`+`size`).
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
|
||||
(__FILE__, __LINE__, address, size, description)
|
||||
|
||||
// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
|
||||
// This annotation could be useful if you want to skip expensive race analysis
|
||||
// during some period of program execution, e.g. during initialization.
|
||||
#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
|
||||
(__FILE__, __LINE__, enable)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations useful for debugging.
|
||||
|
||||
// Report the current thread `name` to a race detector.
|
||||
#define ABSL_ANNOTATE_THREAD_NAME(name) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations useful when implementing locks. They are not normally needed by
|
||||
// modules that merely use locks. The `lock` argument is a pointer to the lock
|
||||
// object.
|
||||
|
||||
// Report that a lock has been created at address `lock`.
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that a linker initialized lock has been created at address `lock`.
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
|
||||
(__FILE__, __LINE__, lock)
|
||||
#else
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
ABSL_ANNOTATE_RWLOCK_CREATE(lock)
|
||||
#endif
|
||||
|
||||
// Report that the lock at address `lock` is about to be destroyed.
|
||||
#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that the lock at address `lock` has been acquired.
|
||||
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
|
||||
#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
|
||||
(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
// Report that the lock at address `lock` is about to be released.
|
||||
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
|
||||
#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
|
||||
(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
// Apply ABSL_ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
|
||||
namespace { \
|
||||
class static_var##_annotator { \
|
||||
public: \
|
||||
static_var##_annotator() { \
|
||||
ABSL_ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
|
||||
#static_var ": " description); \
|
||||
} \
|
||||
}; \
|
||||
static static_var##_annotator the##static_var##_annotator; \
|
||||
} // namespace
|
||||
|
||||
// Function prototypes of annotations provided by the compiler-based sanitizer
|
||||
// implementation.
|
||||
ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
void AnnotateRWLockCreate(const char* file, int line,
|
||||
const volatile void* lock);
|
||||
void AnnotateRWLockCreateStatic(const char* file, int line,
|
||||
const volatile void* lock);
|
||||
void AnnotateRWLockDestroy(const char* file, int line,
|
||||
const volatile void* lock);
|
||||
void AnnotateRWLockAcquired(const char* file, int line,
|
||||
const volatile void* lock, long is_w); // NOLINT
|
||||
void AnnotateRWLockReleased(const char* file, int line,
|
||||
const volatile void* lock, long is_w); // NOLINT
|
||||
void AnnotateBenignRace(const char* file, int line,
|
||||
const volatile void* address, const char* description);
|
||||
void AnnotateBenignRaceSized(const char* file, int line,
|
||||
const volatile void* address, size_t size,
|
||||
const char* description);
|
||||
void AnnotateThreadName(const char* file, int line, const char* name);
|
||||
void AnnotateEnableRaceDetection(const char* file, int line, int enable);
|
||||
ABSL_INTERNAL_END_EXTERN_C
|
||||
|
||||
#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
|
||||
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) // empty
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
|
||||
#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) // empty
|
||||
#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
|
||||
#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE(address, description) // empty
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
|
||||
#define ABSL_ANNOTATE_THREAD_NAME(name) // empty
|
||||
#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
|
||||
|
||||
#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define memory annotations.
|
||||
|
||||
#ifdef ABSL_HAVE_MEMORY_SANITIZER
|
||||
|
||||
#include <sanitizer/msan_interface.h>
|
||||
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
__msan_unpoison(address, size)
|
||||
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
__msan_allocated_memory(address, size)
|
||||
|
||||
#else // !defined(ABSL_HAVE_MEMORY_SANITIZER)
|
||||
|
||||
// TODO(rogeeff): remove this branch
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ABSL_HAVE_MEMORY_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END attributes.
|
||||
|
||||
#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
|
||||
__attribute((exclusive_lock_function("*")))
|
||||
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
|
||||
__attribute((unlock_function("*")))
|
||||
|
||||
#else // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
|
||||
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
|
||||
|
||||
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// 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__)
|
||||
|
||||
// Stop ignoring reads.
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd) \
|
||||
(__FILE__, __LINE__)
|
||||
|
||||
// Function prototypes of annotations provided by the compiler-based sanitizer
|
||||
// implementation.
|
||||
ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
void AnnotateIgnoreReadsBegin(const char* file, int line)
|
||||
ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE;
|
||||
void AnnotateIgnoreReadsEnd(const char* file,
|
||||
int line) ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE;
|
||||
ABSL_INTERNAL_END_EXTERN_C
|
||||
|
||||
#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
|
||||
|
||||
// When Annotalysis is enabled without Dynamic Annotations, the use of
|
||||
// static-inline functions allows the annotations to be read at compile-time,
|
||||
// while still letting the compiler elide the functions from the final build.
|
||||
//
|
||||
// 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( \
|
||||
ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsBegin)) \
|
||||
()
|
||||
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED( \
|
||||
ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsEnd)) \
|
||||
()
|
||||
|
||||
ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
|
||||
AbslInternalAnnotateIgnoreReadsBegin)()
|
||||
ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE {}
|
||||
|
||||
ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
|
||||
AbslInternalAnnotateIgnoreReadsEnd)()
|
||||
ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE {}
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() // empty
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_END() // empty
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_WRITES_BEGIN/_END annotations.
|
||||
|
||||
#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
// Similar to ABSL_ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
|
||||
#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
|
||||
|
||||
// Stop ignoring writes.
|
||||
#define ABSL_ANNOTATE_IGNORE_WRITES_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
|
||||
|
||||
// Function prototypes of annotations provided by the compiler-based sanitizer
|
||||
// implementation.
|
||||
ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
void AnnotateIgnoreWritesBegin(const char* file, int line);
|
||||
void AnnotateIgnoreWritesEnd(const char* file, int line);
|
||||
ABSL_INTERNAL_END_EXTERN_C
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() // empty
|
||||
#define ABSL_ANNOTATE_IGNORE_WRITES_END() // empty
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define the ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
|
||||
// primitive annotations defined above.
|
||||
//
|
||||
// Instead of doing
|
||||
// ABSL_ANNOTATE_IGNORE_READS_BEGIN();
|
||||
// ... = x;
|
||||
// ABSL_ANNOTATE_IGNORE_READS_END();
|
||||
// one can use
|
||||
// ... = ABSL_ANNOTATE_UNPROTECTED_READ(x);
|
||||
|
||||
#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
|
||||
|
||||
// Start ignoring all memory accesses (both reads and writes).
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
|
||||
do { \
|
||||
ABSL_ANNOTATE_IGNORE_READS_BEGIN(); \
|
||||
ABSL_ANNOTATE_IGNORE_WRITES_BEGIN(); \
|
||||
} while (0)
|
||||
|
||||
// Stop ignoring both reads and writes.
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() \
|
||||
do { \
|
||||
ABSL_ANNOTATE_IGNORE_WRITES_END(); \
|
||||
ABSL_ANNOTATE_IGNORE_READS_END(); \
|
||||
} while (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
// ABSL_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
|
||||
#define ABSL_ANNOTATE_UNPROTECTED_READ(x) \
|
||||
absl::base_internal::AnnotateUnprotectedRead(x)
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
Instead of doing
|
||||
ANNOTATE_IGNORE_READS_BEGIN();
|
||||
... = x;
|
||||
ANNOTATE_IGNORE_READS_END();
|
||||
one can use
|
||||
... = ANNOTATE_UNPROTECTED_READ(x); */
|
||||
#if defined(__cplusplus) && defined(ANNOTATIONS_ENABLED)
|
||||
template <typename T>
|
||||
inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) { /* NOLINT */
|
||||
ANNOTATE_IGNORE_READS_BEGIN();
|
||||
inline T AnnotateUnprotectedRead(const volatile T& x) { // NOLINT
|
||||
ABSL_ANNOTATE_IGNORE_READS_BEGIN();
|
||||
T res = x;
|
||||
ANNOTATE_IGNORE_READS_END();
|
||||
ABSL_ANNOTATE_IGNORE_READS_END();
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
#define ANNOTATE_UNPROTECTED_READ(x) (x)
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
|
||||
/* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
|
||||
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
|
||||
namespace { \
|
||||
class static_var ## _annotator { \
|
||||
public: \
|
||||
static_var ## _annotator() { \
|
||||
ANNOTATE_BENIGN_RACE_SIZED(&static_var, \
|
||||
sizeof(static_var), \
|
||||
# static_var ": " description); \
|
||||
} \
|
||||
}; \
|
||||
static static_var ## _annotator the ## static_var ## _annotator;\
|
||||
} // namespace
|
||||
#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
|
||||
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */
|
||||
#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
/* Describe the current state of a contiguous container such as e.g.
|
||||
* std::vector or std::string. For more details see
|
||||
* sanitizer/common_interface_defs.h, which is provided by the compiler. */
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
|
||||
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
|
||||
#define ADDRESS_SANITIZER_REDZONE(name) \
|
||||
struct { char x[8] __attribute__ ((aligned (8))); } name
|
||||
#else
|
||||
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
|
||||
#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
/* Undefine the macros intended only in this file. */
|
||||
#undef ANNOTALYSIS_ENABLED
|
||||
#undef ANNOTATIONS_ENABLED
|
||||
#undef ATTRIBUTE_IGNORE_READS_BEGIN
|
||||
#undef ATTRIBUTE_IGNORE_READS_END
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
|
||||
#define ABSL_ANNOTATE_UNPROTECTED_READ(x) (x)
|
||||
|
||||
#endif /* ABSL_BASE_DYNAMIC_ANNOTATIONS_H_ */
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Address sanitizer annotations
|
||||
|
||||
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
|
||||
// Describe the current state of a contiguous container such as e.g.
|
||||
// std::vector or std::string. For more details see
|
||||
// sanitizer/common_interface_defs.h, which is provided by the compiler.
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
|
||||
#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
|
||||
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
|
||||
#define ABSL_ADDRESS_SANITIZER_REDZONE(name) \
|
||||
struct { \
|
||||
alignas(8) char x[8]; \
|
||||
} name
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) // empty
|
||||
#define ABSL_ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
|
||||
|
||||
#endif // ABSL_HAVE_ADDRESS_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Undefine the macros intended only for this file.
|
||||
|
||||
#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
|
||||
#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
#undef ABSL_INTERNAL_END_EXTERN_C
|
||||
#undef ABSL_INTERNAL_STATIC_INLINE
|
||||
|
||||
#endif // ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
|
||||
|
||||
218
third_party/abseil-cpp/absl/base/internal/bits.h
vendored
218
third_party/abseil-cpp/absl/base/internal/bits.h
vendored
@ -1,218 +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)
|
||||
#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)
|
||||
// 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(_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)
|
||||
// MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if ((n >> 32) && _BitScanReverse(&result, n >> 32)) {
|
||||
return 31 - result;
|
||||
}
|
||||
if (_BitScanReverse(&result, n)) {
|
||||
return 63 - result;
|
||||
}
|
||||
return 64;
|
||||
#elif defined(__GNUC__)
|
||||
// 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)
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if (_BitScanReverse(&result, n)) {
|
||||
return 31 - result;
|
||||
}
|
||||
return 32;
|
||||
#elif defined(__GNUC__)
|
||||
// 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(_M_X64)
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
_BitScanForward64(&result, n);
|
||||
return result;
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if (static_cast<uint32_t>(n) == 0) {
|
||||
_BitScanForward(&result, n >> 32);
|
||||
return result + 32;
|
||||
}
|
||||
_BitScanForward(&result, n);
|
||||
return result;
|
||||
#elif defined(__GNUC__)
|
||||
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)
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
_BitScanForward(&result, n);
|
||||
return result;
|
||||
#elif defined(__GNUC__)
|
||||
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_
|
||||
@ -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
|
||||
@ -61,6 +61,10 @@ extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
|
||||
#endif
|
||||
#endif // __BIONIC__
|
||||
|
||||
#if defined(__NR_mmap2) && !defined(SYS_mmap2)
|
||||
#define SYS_mmap2 __NR_mmap2
|
||||
#endif
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
@ -70,9 +74,13 @@ namespace base_internal {
|
||||
inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off64_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(__s390__) && !defined(__s390x__))
|
||||
(defined(__riscv) && __riscv_xlen == 32) || \
|
||||
(defined(__s390__) && !defined(__s390x__)) || \
|
||||
(defined(__sparc__) && !defined(__arch64__))
|
||||
// On these architectures, implement mmap with mmap2.
|
||||
static int pagesize = 0;
|
||||
if (pagesize == 0) {
|
||||
|
||||
398
third_party/abseil-cpp/absl/base/internal/dynamic_annotations.h
vendored
Normal file
398
third_party/abseil-cpp/absl/base/internal/dynamic_annotations.h
vendored
Normal file
@ -0,0 +1,398 @@
|
||||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file defines dynamic annotations for use with dynamic analysis tool
|
||||
// such as valgrind, PIN, etc.
|
||||
//
|
||||
// Dynamic annotation is a source code annotation that affects the generated
|
||||
// code (that is, the annotation is not a comment). Each such annotation is
|
||||
// attached to a particular instruction and/or to a particular object (address)
|
||||
// in the program.
|
||||
//
|
||||
// The annotations that should be used by users are macros in all upper-case
|
||||
// (e.g., ANNOTATE_THREAD_NAME).
|
||||
//
|
||||
// Actual implementation of these macros may differ depending on the dynamic
|
||||
// analysis tool being used.
|
||||
//
|
||||
// This file supports the following configurations:
|
||||
// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
|
||||
// In this case, macros expand to functions implemented by Thread Sanitizer,
|
||||
// when building with TSan. When not provided an external implementation,
|
||||
// dynamic_annotations.cc provides no-op implementations.
|
||||
//
|
||||
// - Static Clang thread-safety warnings enabled.
|
||||
// When building with a Clang compiler that supports thread-safety warnings,
|
||||
// a subset of annotations can be statically-checked at compile-time. We
|
||||
// expand these macros to static-inline functions that can be analyzed for
|
||||
// thread-safety, but afterwards elided when building the final binary.
|
||||
//
|
||||
// - All annotations are disabled.
|
||||
// If neither Dynamic Annotations nor Clang thread-safety warnings are
|
||||
// enabled, then all annotation-macros expand to empty.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
|
||||
#define ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Decide which features are enabled
|
||||
|
||||
#ifndef DYNAMIC_ANNOTATIONS_ENABLED
|
||||
#define DYNAMIC_ANNOTATIONS_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) && !defined(SWIG)
|
||||
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
|
||||
|
||||
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
|
||||
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
|
||||
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
|
||||
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
|
||||
|
||||
// Clang provides limited support for static thread-safety analysis through a
|
||||
// feature called Annotalysis. We configure macro-definitions according to
|
||||
// whether Annotalysis support is available. When running in opt-mode, GCC
|
||||
// will issue a warning, if these attributes are compiled. Only include them
|
||||
// when compiling using Clang.
|
||||
|
||||
// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \
|
||||
defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
|
||||
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
|
||||
ABSL_INTERNAL_ANNOTALYSIS_ENABLED
|
||||
#endif
|
||||
|
||||
// Memory annotations are also made available to LLVM's Memory Sanitizer
|
||||
#if defined(ABSL_HAVE_MEMORY_SANITIZER) && !defined(__native_client__)
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
|
||||
#endif
|
||||
|
||||
#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
|
||||
#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
|
||||
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
|
||||
#define ABSL_INTERNAL_STATIC_INLINE inline
|
||||
#else
|
||||
#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
|
||||
#define ABSL_INTERNAL_END_EXTERN_C // empty
|
||||
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
|
||||
#define ABSL_INTERNAL_STATIC_INLINE static inline
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define race annotations.
|
||||
|
||||
#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations that suppress errors. It is usually better to express the
|
||||
// program's synchronization using the other annotations, but these can be used
|
||||
// when all else fails.
|
||||
|
||||
// Report that we may have a benign race at `pointer`, with size
|
||||
// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
|
||||
// point where `pointer` has been allocated, preferably close to the point
|
||||
// where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.
|
||||
#define ANNOTATE_BENIGN_RACE(pointer, description) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
|
||||
(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
|
||||
|
||||
// Same as ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
|
||||
// the memory range [`address`, `address`+`size`).
|
||||
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
|
||||
(__FILE__, __LINE__, address, size, description)
|
||||
|
||||
// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
|
||||
// This annotation could be useful if you want to skip expensive race analysis
|
||||
// during some period of program execution, e.g. during initialization.
|
||||
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
|
||||
(__FILE__, __LINE__, enable)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations useful for debugging.
|
||||
|
||||
// Report the current thread `name` to a race detector.
|
||||
#define ANNOTATE_THREAD_NAME(name) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations useful when implementing locks. They are not normally needed by
|
||||
// modules that merely use locks. The `lock` argument is a pointer to the lock
|
||||
// object.
|
||||
|
||||
// Report that a lock has been created at address `lock`.
|
||||
#define ANNOTATE_RWLOCK_CREATE(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that a linker initialized lock has been created at address `lock`.
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
|
||||
(__FILE__, __LINE__, lock)
|
||||
#else
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
|
||||
#endif
|
||||
|
||||
// Report that the lock at address `lock` is about to be destroyed.
|
||||
#define ANNOTATE_RWLOCK_DESTROY(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that the lock at address `lock` has been acquired.
|
||||
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
|
||||
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
|
||||
(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
// Report that the lock at address `lock` is about to be released.
|
||||
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
|
||||
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
|
||||
(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
// Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
|
||||
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
|
||||
namespace { \
|
||||
class static_var##_annotator { \
|
||||
public: \
|
||||
static_var##_annotator() { \
|
||||
ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
|
||||
#static_var ": " description); \
|
||||
} \
|
||||
}; \
|
||||
static static_var##_annotator the##static_var##_annotator; \
|
||||
} // namespace
|
||||
|
||||
#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
|
||||
|
||||
#define ANNOTATE_RWLOCK_CREATE(lock) // empty
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
|
||||
#define ANNOTATE_RWLOCK_DESTROY(lock) // empty
|
||||
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
|
||||
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
|
||||
#define ANNOTATE_BENIGN_RACE(address, description) // empty
|
||||
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
|
||||
#define ANNOTATE_THREAD_NAME(name) // empty
|
||||
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
|
||||
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
|
||||
|
||||
#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define memory annotations.
|
||||
|
||||
#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
#include <sanitizer/msan_interface.h>
|
||||
|
||||
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
__msan_unpoison(address, size)
|
||||
|
||||
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
__msan_allocated_memory(address, size)
|
||||
|
||||
#else // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED == 1
|
||||
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
|
||||
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
|
||||
#endif
|
||||
|
||||
#endif // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END attributes.
|
||||
|
||||
#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
|
||||
__attribute((exclusive_lock_function("*")))
|
||||
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
|
||||
__attribute((unlock_function("*")))
|
||||
|
||||
#else // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
|
||||
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
|
||||
|
||||
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END annotations.
|
||||
|
||||
#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
// Request the analysis tool to ignore all reads in the current thread until
|
||||
// ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
|
||||
// reads, while still checking other reads and all writes.
|
||||
// See also ANNOTATE_UNPROTECTED_READ.
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
|
||||
|
||||
// Stop ignoring reads.
|
||||
#define ANNOTATE_IGNORE_READS_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
|
||||
|
||||
#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
|
||||
|
||||
// When Annotalysis is enabled without Dynamic Annotations, the use of
|
||||
// static-inline functions allows the annotations to be read at compile-time,
|
||||
// while still letting the compiler elide the functions from the final build.
|
||||
//
|
||||
// TODO(delesley) -- The exclusive lock here ignores writes as well, but
|
||||
// allows IGNORE_READS_AND_WRITES to work properly.
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
|
||||
|
||||
#else
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() // empty
|
||||
#define ANNOTATE_IGNORE_READS_END() // empty
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_WRITES_BEGIN/_END annotations.
|
||||
|
||||
#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
// Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
|
||||
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
|
||||
|
||||
// Stop ignoring writes.
|
||||
#define ANNOTATE_IGNORE_WRITES_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
|
||||
|
||||
#else
|
||||
|
||||
#define ANNOTATE_IGNORE_WRITES_BEGIN() // empty
|
||||
#define ANNOTATE_IGNORE_WRITES_END() // empty
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
|
||||
// primitive annotations defined above.
|
||||
//
|
||||
// Instead of doing
|
||||
// ANNOTATE_IGNORE_READS_BEGIN();
|
||||
// ... = x;
|
||||
// ANNOTATE_IGNORE_READS_END();
|
||||
// one can use
|
||||
// ... = ANNOTATE_UNPROTECTED_READ(x);
|
||||
|
||||
#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
|
||||
|
||||
// Start ignoring all memory accesses (both reads and writes).
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
|
||||
do { \
|
||||
ANNOTATE_IGNORE_READS_BEGIN(); \
|
||||
ANNOTATE_IGNORE_WRITES_BEGIN(); \
|
||||
} while (0)
|
||||
|
||||
// Stop ignoring both reads and writes.
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
|
||||
do { \
|
||||
ANNOTATE_IGNORE_WRITES_END(); \
|
||||
ANNOTATE_IGNORE_READS_END(); \
|
||||
} while (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
// ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
|
||||
#define ANNOTATE_UNPROTECTED_READ(x) \
|
||||
absl::base_internal::AnnotateUnprotectedRead(x)
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
|
||||
#define ANNOTATE_UNPROTECTED_READ(x) (x)
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Address sanitizer annotations
|
||||
|
||||
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
|
||||
// Describe the current state of a contiguous container such as e.g.
|
||||
// std::vector or std::string. For more details see
|
||||
// sanitizer/common_interface_defs.h, which is provided by the compiler.
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
|
||||
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
|
||||
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
|
||||
#define ADDRESS_SANITIZER_REDZONE(name) \
|
||||
struct { \
|
||||
char x[8] __attribute__((aligned(8))); \
|
||||
} name
|
||||
|
||||
#else
|
||||
|
||||
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
|
||||
#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
|
||||
|
||||
#endif // ABSL_HAVE_ADDRESS_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Undefine the macros intended only for this file.
|
||||
|
||||
#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
|
||||
#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
#undef ABSL_INTERNAL_END_EXTERN_C
|
||||
#undef ABSL_INTERNAL_STATIC_INLINE
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
|
||||
@ -26,6 +26,7 @@
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
#include "absl/base/casts.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/unaligned_access.h"
|
||||
#include "absl/base/port.h"
|
||||
@ -173,6 +174,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 +264,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));
|
||||
|
||||
@ -54,24 +54,22 @@ const uint32_t k32ValueBE{0x67452301};
|
||||
const uint16_t k16ValueBE{0x2301};
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> GenerateAllValuesForType() {
|
||||
std::vector<T> result;
|
||||
T next = std::numeric_limits<T>::min();
|
||||
while (true) {
|
||||
result.push_back(next);
|
||||
if (next == std::numeric_limits<T>::max()) {
|
||||
return result;
|
||||
}
|
||||
++next;
|
||||
std::vector<uint16_t> GenerateAllUint16Values() {
|
||||
std::vector<uint16_t> result;
|
||||
result.reserve(size_t{1} << (sizeof(uint16_t) * 8));
|
||||
for (uint32_t i = std::numeric_limits<uint16_t>::min();
|
||||
i <= std::numeric_limits<uint16_t>::max(); ++i) {
|
||||
result.push_back(static_cast<uint16_t>(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> GenerateRandomIntegers(size_t numValuesToTest) {
|
||||
std::vector<T> GenerateRandomIntegers(size_t num_values_to_test) {
|
||||
std::vector<T> result;
|
||||
result.reserve(num_values_to_test);
|
||||
std::mt19937_64 rng(kRandomSeed);
|
||||
for (size_t i = 0; i < numValuesToTest; ++i) {
|
||||
for (size_t i = 0; i < num_values_to_test; ++i) {
|
||||
result.push_back(rng());
|
||||
}
|
||||
return result;
|
||||
@ -148,7 +146,7 @@ void Swap64(char* bytes) {
|
||||
}
|
||||
|
||||
TEST(EndianessTest, Uint16) {
|
||||
GBSwapHelper(GenerateAllValuesForType<uint16_t>(), &Swap16);
|
||||
GBSwapHelper(GenerateAllUint16Values(), &Swap16);
|
||||
}
|
||||
|
||||
TEST(EndianessTest, Uint32) {
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/internal/strerror.h"
|
||||
|
||||
namespace {
|
||||
using ::testing::Eq;
|
||||
@ -26,7 +27,7 @@ struct ErrnoPrinter {
|
||||
int no;
|
||||
};
|
||||
std::ostream &operator<<(std::ostream &os, ErrnoPrinter ep) {
|
||||
return os << strerror(ep.no) << " [" << ep.no << "]";
|
||||
return os << absl::base_internal::StrError(ep.no) << " [" << ep.no << "]";
|
||||
}
|
||||
bool operator==(ErrnoPrinter one, ErrnoPrinter two) { return one.no == two.no; }
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
48
third_party/abseil-cpp/absl/base/internal/fast_type_id.h
vendored
Normal file
48
third_party/abseil-cpp/absl/base/internal/fast_type_id.h
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
|
||||
#define ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
template <typename Type>
|
||||
struct FastTypeTag {
|
||||
constexpr static char dummy_var = 0;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
constexpr char FastTypeTag<Type>::dummy_var;
|
||||
|
||||
// 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
|
||||
// straight up comparisons.
|
||||
using FastTypeIdType = const void*;
|
||||
|
||||
template <typename Type>
|
||||
constexpr inline FastTypeIdType FastTypeId() {
|
||||
return &FastTypeTag<Type>::dummy_var;
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
|
||||
123
third_party/abseil-cpp/absl/base/internal/fast_type_id_test.cc
vendored
Normal file
123
third_party/abseil-cpp/absl/base/internal/fast_type_id_test.cc
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/fast_type_id.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
namespace bi = absl::base_internal;
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
#define PRIM_TYPES(A) \
|
||||
A(bool) \
|
||||
A(short) \
|
||||
A(unsigned short) \
|
||||
A(int) \
|
||||
A(unsigned int) \
|
||||
A(long) \
|
||||
A(unsigned long) \
|
||||
A(long long) \
|
||||
A(unsigned long long) \
|
||||
A(float) \
|
||||
A(double) \
|
||||
A(long double)
|
||||
|
||||
TEST(FastTypeIdTest, PrimitiveTypes) {
|
||||
bi::FastTypeIdType type_ids[] = {
|
||||
#define A(T) bi::FastTypeId<T>(),
|
||||
PRIM_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<const T>(),
|
||||
PRIM_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<volatile T>(),
|
||||
PRIM_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<const volatile T>(),
|
||||
PRIM_TYPES(A)
|
||||
#undef A
|
||||
};
|
||||
size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
|
||||
|
||||
for (int i = 0; i < total_type_ids; ++i) {
|
||||
EXPECT_EQ(type_ids[i], type_ids[i]);
|
||||
for (int j = 0; j < i; ++j) {
|
||||
EXPECT_NE(type_ids[i], type_ids[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define FIXED_WIDTH_TYPES(A) \
|
||||
A(int8_t) \
|
||||
A(uint8_t) \
|
||||
A(int16_t) \
|
||||
A(uint16_t) \
|
||||
A(int32_t) \
|
||||
A(uint32_t) \
|
||||
A(int64_t) \
|
||||
A(uint64_t)
|
||||
|
||||
TEST(FastTypeIdTest, FixedWidthTypes) {
|
||||
bi::FastTypeIdType type_ids[] = {
|
||||
#define A(T) bi::FastTypeId<T>(),
|
||||
FIXED_WIDTH_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<const T>(),
|
||||
FIXED_WIDTH_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<volatile T>(),
|
||||
FIXED_WIDTH_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<const volatile T>(),
|
||||
FIXED_WIDTH_TYPES(A)
|
||||
#undef A
|
||||
};
|
||||
size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
|
||||
|
||||
for (int i = 0; i < total_type_ids; ++i) {
|
||||
EXPECT_EQ(type_ids[i], type_ids[i]);
|
||||
for (int j = 0; j < i; ++j) {
|
||||
EXPECT_NE(type_ids[i], type_ids[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FastTypeIdTest, AliasTypes) {
|
||||
using int_alias = int;
|
||||
EXPECT_EQ(bi::FastTypeId<int_alias>(), bi::FastTypeId<int>());
|
||||
}
|
||||
|
||||
TEST(FastTypeIdTest, TemplateSpecializations) {
|
||||
EXPECT_NE(bi::FastTypeId<std::vector<int>>(),
|
||||
bi::FastTypeId<std::vector<long>>());
|
||||
|
||||
EXPECT_NE((bi::FastTypeId<std::map<int, float>>()),
|
||||
(bi::FastTypeId<std::map<int, double>>()));
|
||||
}
|
||||
|
||||
struct Base {};
|
||||
struct Derived : Base {};
|
||||
struct PDerived : private Base {};
|
||||
|
||||
TEST(FastTypeIdTest, Inheritance) {
|
||||
EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<Derived>());
|
||||
EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<PDerived>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// absl::base_internal::Invoke(f, args...) is an implementation of
|
||||
// absl::base_internal::invoke(f, args...) is an implementation of
|
||||
// INVOKE(f, args...) from section [func.require] of the C++ standard.
|
||||
//
|
||||
// [func.require]
|
||||
@ -29,7 +29,7 @@
|
||||
// is not one of the types described in the previous item;
|
||||
// 5. f(t1, t2, ..., tN) in all other cases.
|
||||
//
|
||||
// The implementation is SFINAE-friendly: substitution failure within Invoke()
|
||||
// The implementation is SFINAE-friendly: substitution failure within invoke()
|
||||
// isn't an error.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_INVOKE_H_
|
||||
@ -170,13 +170,13 @@ struct Invoker {
|
||||
|
||||
// The result type of Invoke<F, Args...>.
|
||||
template <typename F, typename... Args>
|
||||
using InvokeT = decltype(Invoker<F, Args...>::type::Invoke(
|
||||
using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
|
||||
std::declval<F>(), std::declval<Args>()...));
|
||||
|
||||
// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
|
||||
// [func.require] of the C++ standard.
|
||||
template <typename F, typename... Args>
|
||||
InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
|
||||
invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
|
||||
return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@ -598,7 +598,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
|
||||
section.Leave();
|
||||
result = &s->levels;
|
||||
}
|
||||
ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
|
||||
ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,12 @@
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
#include "absl/container/node_hash_map.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
@ -75,7 +81,7 @@ static bool using_low_level_alloc = false;
|
||||
// allocations and deallocations are reported via the MallocHook
|
||||
// interface.
|
||||
static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
|
||||
typedef std::unordered_map<int, BlockDesc> AllocMap;
|
||||
typedef absl::node_hash_map<int, BlockDesc> AllocMap;
|
||||
AllocMap allocated;
|
||||
AllocMap::iterator it;
|
||||
BlockDesc block_desc;
|
||||
@ -156,5 +162,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;
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
|
||||
#define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
|
||||
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/scheduling_mode.h"
|
||||
#include "absl/base/macros.h"
|
||||
|
||||
@ -29,6 +30,13 @@ extern "C" void __google_enable_rescheduling(bool disable_result);
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
class CondVar;
|
||||
class Mutex;
|
||||
|
||||
namespace synchronization_internal {
|
||||
int MutexDelay(int32_t c, int mode);
|
||||
} // namespace synchronization_internal
|
||||
|
||||
namespace base_internal {
|
||||
|
||||
class SchedulingHelper; // To allow use of SchedulingGuard.
|
||||
@ -53,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
|
||||
@ -76,12 +86,23 @@ class SchedulingGuard {
|
||||
bool disabled;
|
||||
};
|
||||
|
||||
// Access to SchedulingGuard is explicitly white-listed.
|
||||
// A scoped helper to enable rescheduling temporarily.
|
||||
// REQUIRES: destructor must run in same thread as constructor.
|
||||
class ScopedEnable {
|
||||
public:
|
||||
ScopedEnable();
|
||||
~ScopedEnable();
|
||||
|
||||
private:
|
||||
int scheduling_disabled_depth_;
|
||||
};
|
||||
|
||||
// Access to SchedulingGuard is explicitly permitted.
|
||||
friend class absl::CondVar;
|
||||
friend class absl::Mutex;
|
||||
friend class SchedulingHelper;
|
||||
friend class SpinLock;
|
||||
|
||||
SchedulingGuard(const SchedulingGuard&) = delete;
|
||||
SchedulingGuard& operator=(const SchedulingGuard&) = delete;
|
||||
friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -100,6 +121,12 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) {
|
||||
return;
|
||||
}
|
||||
|
||||
inline SchedulingGuard::ScopedEnable::ScopedEnable()
|
||||
: scheduling_disabled_depth_(0) {}
|
||||
inline SchedulingGuard::ScopedEnable::~ScopedEnable() {
|
||||
ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning");
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
@ -67,28 +67,32 @@
|
||||
#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
|
||||
// whitelisted set of platforms for which we expect not to be able to raw log.
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace raw_logging_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.
|
||||
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
|
||||
absl::base_internal::AtomicHook<LogPrefixHook>
|
||||
log_prefix_hook;
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
|
||||
absl::base_internal::AtomicHook<AbortHook>
|
||||
abort_hook;
|
||||
|
||||
#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) {
|
||||
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) {
|
||||
int n = vsnprintf(*buf, *size, format, ap);
|
||||
bool result = true;
|
||||
if (n < 0 || n > *size) {
|
||||
@ -96,7 +100,7 @@ inline static bool VADoRawLog(char** buf, int* size,
|
||||
if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
|
||||
n = *size - sizeof(kTruncated); // room for truncation message
|
||||
} else {
|
||||
n = 0; // no room for truncation message
|
||||
n = 0; // no room for truncation message
|
||||
}
|
||||
}
|
||||
*size -= n;
|
||||
@ -105,9 +109,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.
|
||||
@ -166,7 +168,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
|
||||
} else {
|
||||
DoRawLog(&buf, &size, "%s", kTruncated);
|
||||
}
|
||||
absl::raw_logging_internal::SafeWriteToStderr(buffer, strlen(buffer));
|
||||
SafeWriteToStderr(buffer, strlen(buffer));
|
||||
}
|
||||
#else
|
||||
static_cast<void>(format);
|
||||
@ -181,11 +183,18 @@ 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)
|
||||
syscall(SYS_write, STDERR_FILENO, s, len);
|
||||
@ -200,8 +209,6 @@ void SafeWriteToStderr(const char *s, size_t len) {
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
@ -210,15 +217,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;
|
||||
@ -227,10 +225,14 @@ bool RawLoggingFullySupported() {
|
||||
#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
|
||||
}
|
||||
|
||||
ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL
|
||||
absl::base_internal::AtomicHook<InternalLogFunction>
|
||||
internal_log_function(DefaultInternalLog);
|
||||
|
||||
void RegisterLogPrefixHook(LogPrefixHook func) { log_prefix_hook.Store(func); }
|
||||
|
||||
void RegisterAbortHook(AbortHook func) { abort_hook.Store(func); }
|
||||
|
||||
void RegisterInternalLogFunction(InternalLogFunction func) {
|
||||
internal_log_function.Store(func);
|
||||
}
|
||||
|
||||
@ -72,10 +72,14 @@
|
||||
//
|
||||
// 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 { \
|
||||
::absl::raw_logging_internal::internal_log_function( \
|
||||
ABSL_RAW_LOGGING_INTERNAL_##severity, __FILE__, __LINE__, 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); \
|
||||
if (ABSL_RAW_LOGGING_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \
|
||||
ABSL_INTERNAL_UNREACHABLE; \
|
||||
} while (0)
|
||||
|
||||
#define ABSL_INTERNAL_CHECK(condition, message) \
|
||||
@ -170,10 +174,18 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity,
|
||||
const char* file, int line,
|
||||
const std::string& message);
|
||||
|
||||
ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES extern base_internal::AtomicHook<
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook<
|
||||
InternalLogFunction>
|
||||
internal_log_function;
|
||||
|
||||
// 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 RegisterLogPrefixHook(LogPrefixHook func);
|
||||
void RegisterAbortHook(AbortHook func);
|
||||
void RegisterInternalLogFunction(InternalLogFunction func);
|
||||
|
||||
} // namespace raw_logging_internal
|
||||
|
||||
@ -66,35 +66,19 @@ void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock,
|
||||
submit_profile_data.Store(fn);
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// Uncommon constructors.
|
||||
SpinLock::SpinLock(base_internal::SchedulingMode mode)
|
||||
: lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {
|
||||
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
|
||||
}
|
||||
|
||||
SpinLock::SpinLock(base_internal::LinkerInitialized,
|
||||
base_internal::SchedulingMode mode) {
|
||||
ABSL_TSAN_MUTEX_CREATE(this, 0);
|
||||
if (IsCooperative(mode)) {
|
||||
InitLinkerInitializedAndCooperative();
|
||||
}
|
||||
// Otherwise, lockword_ is already initialized.
|
||||
}
|
||||
|
||||
// Static (linker initialized) spinlocks always start life as functional
|
||||
// non-cooperative locks. When their static constructor does run, it will call
|
||||
// this initializer to augment the lockword with the cooperative bit. By
|
||||
// actually taking the lock when we do this we avoid the need for an atomic
|
||||
// operation in the regular unlock path.
|
||||
//
|
||||
// SlowLock() must be careful to re-test for this bit so that any outstanding
|
||||
// waiters may be upgraded to cooperative status.
|
||||
void SpinLock::InitLinkerInitializedAndCooperative() {
|
||||
Lock();
|
||||
lockword_.fetch_or(kSpinLockCooperative, std::memory_order_relaxed);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// Monitor the lock to see if its value changes within some time period
|
||||
// (adaptive_spin_count loop iterations). The last value read from the lock
|
||||
// is returned from the method.
|
||||
@ -121,6 +105,14 @@ void SpinLock::SlowLock() {
|
||||
if ((lock_value & kSpinLockHeld) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
base_internal::SchedulingMode scheduling_mode;
|
||||
if ((lock_value & kSpinLockCooperative) != 0) {
|
||||
scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
|
||||
} else {
|
||||
scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY;
|
||||
}
|
||||
|
||||
// The lock was not obtained initially, so this thread needs to wait for
|
||||
// it. Record the current timestamp in the local variable wait_start_time
|
||||
// so the total wait time can be stored in the lockword once this thread
|
||||
@ -133,8 +125,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)) {
|
||||
@ -148,15 +141,17 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
base_internal::SchedulingMode scheduling_mode;
|
||||
if ((lock_value & kSpinLockCooperative) != 0) {
|
||||
scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
|
||||
} else {
|
||||
scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY;
|
||||
}
|
||||
// SpinLockDelay() calls into fiber scheduler, we need to see
|
||||
// synchronization there to avoid false positives.
|
||||
ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
|
||||
@ -190,30 +185,32 @@ void SpinLock::SlowUnlock(uint32_t lock_value) {
|
||||
// We use the upper 29 bits of the lock word to store the time spent waiting to
|
||||
// acquire this lock. This is reported by contentionz profiling. Since the
|
||||
// lower bits of the cycle counter wrap very quickly on high-frequency
|
||||
// processors we divide to reduce the granularity to 2^PROFILE_TIMESTAMP_SHIFT
|
||||
// processors we divide to reduce the granularity to 2^kProfileTimestampShift
|
||||
// sized units. On a 4Ghz machine this will lose track of wait times greater
|
||||
// than (2^29/4 Ghz)*128 =~ 17.2 seconds. Such waits should be extremely rare.
|
||||
enum { PROFILE_TIMESTAMP_SHIFT = 7 };
|
||||
enum { LOCKWORD_RESERVED_SHIFT = 3 }; // We currently reserve the lower 3 bits.
|
||||
static constexpr int kProfileTimestampShift = 7;
|
||||
|
||||
// We currently reserve the lower 3 bits.
|
||||
static constexpr int kLockwordReservedShift = 3;
|
||||
|
||||
uint32_t SpinLock::EncodeWaitCycles(int64_t wait_start_time,
|
||||
int64_t wait_end_time) {
|
||||
static const int64_t kMaxWaitTime =
|
||||
std::numeric_limits<uint32_t>::max() >> LOCKWORD_RESERVED_SHIFT;
|
||||
std::numeric_limits<uint32_t>::max() >> kLockwordReservedShift;
|
||||
int64_t scaled_wait_time =
|
||||
(wait_end_time - wait_start_time) >> PROFILE_TIMESTAMP_SHIFT;
|
||||
(wait_end_time - wait_start_time) >> kProfileTimestampShift;
|
||||
|
||||
// Return a representation of the time spent waiting that can be stored in
|
||||
// the lock word's upper bits.
|
||||
uint32_t clamped = static_cast<uint32_t>(
|
||||
std::min(scaled_wait_time, kMaxWaitTime) << LOCKWORD_RESERVED_SHIFT);
|
||||
std::min(scaled_wait_time, kMaxWaitTime) << kLockwordReservedShift);
|
||||
|
||||
if (clamped == 0) {
|
||||
return kSpinLockSleeper; // Just wake waiters, but don't record contention.
|
||||
}
|
||||
// Bump up value if necessary to avoid returning kSpinLockSleeper.
|
||||
const uint32_t kMinWaitTime =
|
||||
kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
|
||||
kSpinLockSleeper + (1 << kLockwordReservedShift);
|
||||
if (clamped == kSpinLockSleeper) {
|
||||
return kMinWaitTime;
|
||||
}
|
||||
@ -224,8 +221,7 @@ uint64_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 =
|
||||
static_cast<uint32_t>(lock_value & kWaitTimeMask);
|
||||
return scaled_wait_time
|
||||
<< (PROFILE_TIMESTAMP_SHIFT - LOCKWORD_RESERVED_SHIFT);
|
||||
return scaled_wait_time << (kProfileTimestampShift - kLockwordReservedShift);
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
|
||||
@ -15,17 +15,16 @@
|
||||
//
|
||||
|
||||
// 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_
|
||||
@ -36,6 +35,7 @@
|
||||
#include <atomic>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/const_init.h"
|
||||
#include "absl/base/dynamic_annotations.h"
|
||||
#include "absl/base/internal/low_level_scheduling.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
@ -55,29 +55,22 @@ class ABSL_LOCKABLE SpinLock {
|
||||
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
|
||||
}
|
||||
|
||||
// Special constructor for use with static SpinLock objects. E.g.,
|
||||
//
|
||||
// static SpinLock lock(base_internal::kLinkerInitialized);
|
||||
//
|
||||
// When initialized using this constructor, we depend on the fact
|
||||
// that the linker has already initialized the memory appropriately. The lock
|
||||
// is initialized in non-cooperative mode.
|
||||
//
|
||||
// A SpinLock constructed like this can be freely used from global
|
||||
// initializers without worrying about the order in which global
|
||||
// initializers run.
|
||||
explicit SpinLock(base_internal::LinkerInitialized) {
|
||||
// Does nothing; lockword_ is already initialized
|
||||
ABSL_TSAN_MUTEX_CREATE(this, 0);
|
||||
}
|
||||
|
||||
// Constructors that allow non-cooperative spinlocks to be created for use
|
||||
// inside thread schedulers. Normal clients should not use these.
|
||||
explicit SpinLock(base_internal::SchedulingMode mode);
|
||||
SpinLock(base_internal::LinkerInitialized,
|
||||
base_internal::SchedulingMode mode);
|
||||
|
||||
// Constructor for global SpinLock instances. See absl/base/const_init.h.
|
||||
constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode)
|
||||
: lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {}
|
||||
|
||||
// For global SpinLock instances prefer trivial destructor when possible.
|
||||
// Default but non-trivial destructor in some build configurations causes an
|
||||
// extra static initializer.
|
||||
#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
|
||||
~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
|
||||
#else
|
||||
~SpinLock() = default;
|
||||
#endif
|
||||
|
||||
// Acquire this SpinLock.
|
||||
inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
|
||||
@ -146,14 +139,27 @@ 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.
|
||||
enum { kSpinLockHeld = 1 };
|
||||
enum { kSpinLockCooperative = 2 };
|
||||
enum { kSpinLockDisabledScheduling = 4 };
|
||||
enum { kSpinLockSleeper = 8 };
|
||||
enum { kWaitTimeMask = // Includes kSpinLockSleeper.
|
||||
~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling) };
|
||||
// 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;
|
||||
static constexpr uint32_t kSpinLockSleeper = 8;
|
||||
// Includes kSpinLockSleeper.
|
||||
static constexpr uint32_t kWaitTimeMask =
|
||||
~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling);
|
||||
|
||||
// Returns true if the provided scheduling mode is cooperative.
|
||||
static constexpr bool IsCooperative(
|
||||
@ -162,7 +168,6 @@ class ABSL_LOCKABLE SpinLock {
|
||||
}
|
||||
|
||||
uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles);
|
||||
void InitLinkerInitializedAndCooperative();
|
||||
void SlowLock() ABSL_ATTRIBUTE_COLD;
|
||||
void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
|
||||
uint32_t SpinLoop();
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -46,9 +46,17 @@ static_assert(sizeof(std::atomic<uint32_t>) == sizeof(int),
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
|
||||
#define SYS_futex_time64 __NR_futex_time64
|
||||
#endif
|
||||
|
||||
#if defined(SYS_futex_time64) && !defined(SYS_futex)
|
||||
#define SYS_futex SYS_futex_time64
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
|
||||
ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
|
||||
std::atomic<uint32_t> *w, uint32_t value, int loop,
|
||||
absl::base_internal::SchedulingMode) {
|
||||
absl::base_internal::ErrnoSaver errno_saver;
|
||||
@ -58,8 +66,8 @@ ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
|
||||
syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -20,9 +20,9 @@
|
||||
|
||||
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);
|
||||
@ -31,7 +31,7 @@ void AbslInternalSpinLockDelay(std::atomic<uint32_t>* /* lock_word */,
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
88
third_party/abseil-cpp/absl/base/internal/strerror.cc
vendored
Normal file
88
third_party/abseil-cpp/absl/base/internal/strerror.cc
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/strerror.h"
|
||||
|
||||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/internal/errno_saver.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
namespace {
|
||||
|
||||
const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
|
||||
#if defined(_WIN32)
|
||||
int rc = strerror_s(buf, buflen, errnum);
|
||||
buf[buflen - 1] = '\0'; // guarantee NUL termination
|
||||
if (rc == 0 && strncmp(buf, "Unknown error", buflen) == 0) *buf = '\0';
|
||||
return buf;
|
||||
#else
|
||||
// The type of `ret` is platform-specific; both of these branches must compile
|
||||
// either way but only one will execute on any given platform:
|
||||
auto ret = strerror_r(errnum, buf, buflen);
|
||||
if (std::is_same<decltype(ret), int>::value) {
|
||||
// XSI `strerror_r`; `ret` is `int`:
|
||||
if (ret) *buf = '\0';
|
||||
return buf;
|
||||
} else {
|
||||
// GNU `strerror_r`; `ret` is `char *`:
|
||||
return reinterpret_cast<const char*>(ret);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string StrErrorInternal(int errnum) {
|
||||
char buf[100];
|
||||
const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
|
||||
if (*str == '\0') {
|
||||
snprintf(buf, sizeof buf, "Unknown error %d", errnum);
|
||||
str = buf;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// kSysNerr is the number of errors from a recent glibc. `StrError()` falls back
|
||||
// to `StrErrorAdaptor()` if the value is larger than this.
|
||||
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);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
} // 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];
|
||||
}
|
||||
return StrErrorInternal(errnum);
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
39
third_party/abseil-cpp/absl/base/internal/strerror.h
vendored
Normal file
39
third_party/abseil-cpp/absl/base/internal/strerror.h
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_STRERROR_H_
|
||||
#define ABSL_BASE_INTERNAL_STRERROR_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
// A portable and thread-safe alternative to C89's `strerror`.
|
||||
//
|
||||
// The C89 specification of `strerror` is not suitable for use in a
|
||||
// multi-threaded application as the returned string may be changed by calls to
|
||||
// `strerror` from another thread. The many non-stdlib alternatives differ
|
||||
// enough in their names, availability, and semantics to justify this wrapper
|
||||
// around them. `errno` will not be modified by a call to `absl::StrError`.
|
||||
std::string StrError(int errnum);
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_STRERROR_H_
|
||||
29
third_party/abseil-cpp/absl/base/internal/strerror_benchmark.cc
vendored
Normal file
29
third_party/abseil-cpp/absl/base/internal/strerror_benchmark.cc
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/internal/strerror.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace {
|
||||
void BM_AbslStrError(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(absl::base_internal::StrError(ERANGE));
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_AbslStrError);
|
||||
} // namespace
|
||||
88
third_party/abseil-cpp/absl/base/internal/strerror_test.cc
vendored
Normal file
88
third_party/abseil-cpp/absl/base/internal/strerror_test.cc
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/strerror.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <thread> // NOLINT(build/c++11)
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/match.h"
|
||||
|
||||
namespace {
|
||||
using ::testing::AnyOf;
|
||||
using ::testing::Eq;
|
||||
|
||||
TEST(StrErrorTest, ValidErrorCode) {
|
||||
errno = ERANGE;
|
||||
EXPECT_THAT(absl::base_internal::StrError(EDOM), Eq(strerror(EDOM)));
|
||||
EXPECT_THAT(errno, Eq(ERANGE));
|
||||
}
|
||||
|
||||
TEST(StrErrorTest, InvalidErrorCode) {
|
||||
errno = ERANGE;
|
||||
EXPECT_THAT(absl::base_internal::StrError(-1),
|
||||
AnyOf(Eq("No error information"), Eq("Unknown error -1")));
|
||||
EXPECT_THAT(errno, Eq(ERANGE));
|
||||
}
|
||||
|
||||
TEST(StrErrorTest, MultipleThreads) {
|
||||
// In this test, we will start up 2 threads and have each one call
|
||||
// StrError 1000 times, each time with a different errnum. We
|
||||
// expect that StrError(errnum) will return a string equal to the
|
||||
// one returned by strerror(errnum), if the code is known. Since
|
||||
// strerror is known to be thread-hostile, collect all the expected
|
||||
// strings up front.
|
||||
const int kNumCodes = 1000;
|
||||
std::vector<std::string> expected_strings(kNumCodes);
|
||||
for (int i = 0; i < kNumCodes; ++i) {
|
||||
expected_strings[i] = strerror(i);
|
||||
}
|
||||
|
||||
std::atomic_int counter(0);
|
||||
auto thread_fun = [&]() {
|
||||
for (int i = 0; i < kNumCodes; ++i) {
|
||||
++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(value, Eq(expected_strings[i]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const int kNumThreads = 100;
|
||||
std::vector<std::thread> threads;
|
||||
for (int i = 0; i < kNumThreads; ++i) {
|
||||
threads.push_back(std::thread(thread_fun));
|
||||
}
|
||||
for (auto& thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
EXPECT_THAT(counter, Eq(kNumThreads * kNumCodes));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
102
third_party/abseil-cpp/absl/base/internal/sysinfo.cc
vendored
102
third_party/abseil-cpp/absl/base/internal/sysinfo.cc
vendored
@ -39,6 +39,7 @@
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
@ -50,17 +51,88 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/call_once.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/spinlock.h"
|
||||
#include "absl/base/internal/unscaledcycleclock.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
|
||||
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 logicalProcessorCount;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
static int GetNumCPUs() {
|
||||
#if defined(__myriad2__)
|
||||
return 1;
|
||||
#elif defined(_WIN32)
|
||||
const unsigned 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()
|
||||
@ -72,6 +144,12 @@ static int GetNumCPUs() {
|
||||
#if defined(_WIN32)
|
||||
|
||||
static double GetNominalCPUFrequency() {
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
|
||||
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
// UWP apps don't have access to the registry and currently don't provide an
|
||||
// API informing about CPU nominal frequency.
|
||||
return 1.0;
|
||||
#else
|
||||
#pragma comment(lib, "advapi32.lib") // For Reg* functions.
|
||||
HKEY key;
|
||||
// Use the Reg* functions rather than the SH functions because shlwapi.dll
|
||||
@ -91,6 +169,7 @@ static double GetNominalCPUFrequency() {
|
||||
}
|
||||
}
|
||||
return 1.0;
|
||||
#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
|
||||
}
|
||||
|
||||
#elif defined(CTL_HW) && defined(HW_CPU_FREQ)
|
||||
@ -336,15 +415,16 @@ pid_t GetTID() {
|
||||
#else
|
||||
|
||||
// Fallback implementation of GetTID using pthread_getspecific.
|
||||
static once_flag tid_once;
|
||||
static pthread_key_t tid_key;
|
||||
static absl::base_internal::SpinLock tid_lock(
|
||||
absl::base_internal::kLinkerInitialized);
|
||||
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().
|
||||
static std::vector<uint32_t>* tid_array GUARDED_BY(tid_lock) = nullptr;
|
||||
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.
|
||||
@ -411,6 +491,18 @@ pid_t GetTID() {
|
||||
|
||||
#endif
|
||||
|
||||
// GetCachedTID() caches the thread ID in thread-local storage (which is a
|
||||
// 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() {
|
||||
#ifdef ABSL_HAVE_THREAD_LOCAL
|
||||
static thread_local pid_t thread_id = GetTID();
|
||||
return thread_id;
|
||||
#else
|
||||
return GetTID();
|
||||
#endif // ABSL_HAVE_THREAD_LOCAL
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/port.h"
|
||||
|
||||
namespace absl {
|
||||
@ -59,6 +60,13 @@ using pid_t = uint32_t;
|
||||
#endif
|
||||
pid_t GetTID();
|
||||
|
||||
// Like GetTID(), but caches the result in thread-local storage in order
|
||||
// to avoid unnecessary system calls. Note that there are some cases where
|
||||
// one must call through to GetTID directly, which is why this exists as a
|
||||
// separate function. For example, GetCachedTID() is not safe to call in
|
||||
// an asynchronous signal-handling context nor right after a call to fork().
|
||||
pid_t GetCachedTID();
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
@ -37,17 +37,28 @@ TEST(SysinfoTest, NumCPUs) {
|
||||
<< "NumCPUs() should not have the default value of 0";
|
||||
}
|
||||
|
||||
// Ensure that NominalCPUFrequency returns a reasonable value, or 1.00 on
|
||||
// platforms where the CPU frequency is not available through sysfs.
|
||||
//
|
||||
// POWER is particularly problematic here; some Linux kernels expose the CPU
|
||||
// frequency, while others do not. Since we can't predict a priori what a given
|
||||
// machine is going to do, just disable this test on POWER on Linux.
|
||||
#if !(defined(__linux) && (defined(__ppc64__) || defined(__PPC64__)))
|
||||
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.
|
||||
// Linux only exposes the CPU frequency on certain architectures, and
|
||||
// Emscripten doesn't expose it at all.
|
||||
#if defined(__linux__) && \
|
||||
(defined(__aarch64__) || defined(__hppa__) || defined(__mips__) || \
|
||||
defined(__riscv) || defined(__s390x__)) || \
|
||||
defined(__EMSCRIPTEN__)
|
||||
EXPECT_EQ(NominalCPUFrequency(), 1.0)
|
||||
<< "CPU frequency detection was fixed! Please update unittest.";
|
||||
#else
|
||||
EXPECT_GE(NominalCPUFrequency(), 1000.0)
|
||||
<< "NominalCPUFrequency() did not return a reasonable value";
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(SysinfoTest, GetTID) {
|
||||
EXPECT_EQ(GetTID(), GetTID()); // Basic compile and equality test.
|
||||
|
||||
@ -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,9 +54,11 @@ 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__
|
||||
// Apple platforms have the visibility attribute, but issue a compile warning
|
||||
// that protected visibility is unsupported.
|
||||
#if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
|
||||
__attribute__((visibility("protected")))
|
||||
#endif // __GNUC__
|
||||
#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;
|
||||
@ -117,10 +120,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
|
||||
|
||||
@ -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
|
||||
@ -69,30 +70,28 @@ struct PerThreadSynch {
|
||||
// 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.
|
||||
@ -111,30 +110,30 @@ struct PerThreadSynch {
|
||||
};
|
||||
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;
|
||||
};
|
||||
|
||||
// The instances of this class are allocated in NewThreadIdentity() with an
|
||||
// alignment of PerThreadSynch::kAlignment.
|
||||
struct ThreadIdentity {
|
||||
// Must be the first member. The Mutex implementation requires that
|
||||
// the PerThreadSynch object associated with each thread is
|
||||
@ -144,7 +143,7 @@ struct ThreadIdentity {
|
||||
|
||||
// Private: Reserved for absl::synchronization_internal::Waiter.
|
||||
struct WaiterState {
|
||||
char data[128];
|
||||
alignas(void*) char data[128];
|
||||
} waiter_state;
|
||||
|
||||
// Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().
|
||||
@ -189,30 +188,32 @@ 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 ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
|
||||
#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
|
||||
// present in the upstream eglibc.
|
||||
@ -235,13 +236,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;
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/internal/spinlock.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/synchronization/internal/per_thread_sem.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
|
||||
@ -29,10 +30,9 @@ ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
namespace {
|
||||
|
||||
// protects num_identities_reused
|
||||
static absl::base_internal::SpinLock map_lock(
|
||||
absl::base_internal::kLinkerInitialized);
|
||||
static int num_identities_reused;
|
||||
ABSL_CONST_INIT static absl::base_internal::SpinLock map_lock(
|
||||
absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
|
||||
ABSL_CONST_INIT static int num_identities_reused ABSL_GUARDED_BY(map_lock);
|
||||
|
||||
static const void* const kCheckNoIdentity = reinterpret_cast<void*>(1);
|
||||
|
||||
@ -75,7 +75,7 @@ TEST(ThreadIdentityTest, BasicIdentityWorksThreaded) {
|
||||
// - If a thread implementation chooses to recycle threads, that
|
||||
// correct re-initialization occurs.
|
||||
static const int kNumLoops = 3;
|
||||
static const int kNumThreads = 400;
|
||||
static const int kNumThreads = 32;
|
||||
for (int iter = 0; iter < kNumLoops; iter++) {
|
||||
std::vector<std::thread> threads;
|
||||
for (int i = 0; i < kNumThreads; ++i) {
|
||||
@ -90,6 +90,7 @@ TEST(ThreadIdentityTest, BasicIdentityWorksThreaded) {
|
||||
// We should have recycled ThreadIdentity objects above; while (external)
|
||||
// library threads allocating their own identities may preclude some
|
||||
// reuse, we should have sufficient repetitions to exclude this.
|
||||
absl::base_internal::SpinLockHolder l(&map_lock);
|
||||
EXPECT_LT(kNumThreads, num_identities_reused);
|
||||
}
|
||||
|
||||
|
||||
@ -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,186 @@ namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
// NOTE: The various STL exception throwing functions are placed within the
|
||||
// #ifdef blocks so the symbols aren't exposed on platforms that don't support
|
||||
// them, such as the Android NDK. For example, ANGLE fails to link when building
|
||||
// within AOSP without them, since the STL functions don't exist.
|
||||
namespace {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
template <typename T>
|
||||
[[noreturn]] void Throw(const T& error) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
throw error;
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", error.what());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
void ThrowStdLogicError(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::logic_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdLogicError(const char* 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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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) {
|
||||
#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
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
#ifndef ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
|
||||
#define ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
// ABSL_INTERNAL_HAVE_TSAN_INTERFACE
|
||||
// Macro intended only for internal use.
|
||||
//
|
||||
@ -28,7 +30,7 @@
|
||||
#error "ABSL_INTERNAL_HAVE_TSAN_INTERFACE cannot be directly set."
|
||||
#endif
|
||||
|
||||
#if defined(THREAD_SANITIZER) && defined(__has_include)
|
||||
#if defined(ABSL_HAVE_THREAD_SANITIZER) && defined(__has_include)
|
||||
#if __has_include(<sanitizer/tsan_interface.h>)
|
||||
#define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1
|
||||
#endif
|
||||
|
||||
@ -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(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\
|
||||
defined(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_
|
||||
|
||||
77
third_party/abseil-cpp/absl/base/internal/unique_small_name_test.cc
vendored
Normal file
77
third_party/abseil-cpp/absl/base/internal/unique_small_name_test.cc
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/optimization.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
// This test by itself does not do anything fancy, but it serves as binary I can
|
||||
// query in shell test.
|
||||
|
||||
namespace {
|
||||
|
||||
template <class T>
|
||||
void DoNotOptimize(const T& var) {
|
||||
#ifdef __GNUC__
|
||||
asm volatile("" : "+m"(const_cast<T&>(var)));
|
||||
#else
|
||||
std::cout << (void*)&var;
|
||||
#endif
|
||||
}
|
||||
|
||||
int very_long_int_variable_name ABSL_INTERNAL_UNIQUE_SMALL_NAME() = 0;
|
||||
char very_long_str_variable_name[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = "abc";
|
||||
|
||||
TEST(UniqueSmallName, NonAutomaticVar) {
|
||||
EXPECT_EQ(very_long_int_variable_name, 0);
|
||||
EXPECT_EQ(absl::string_view(very_long_str_variable_name), "abc");
|
||||
}
|
||||
|
||||
int VeryLongFreeFunctionName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
|
||||
|
||||
TEST(UniqueSmallName, FreeFunction) {
|
||||
DoNotOptimize(&VeryLongFreeFunctionName);
|
||||
|
||||
EXPECT_EQ(VeryLongFreeFunctionName(), 456);
|
||||
}
|
||||
|
||||
int VeryLongFreeFunctionName() { return 456; }
|
||||
|
||||
struct VeryLongStructName {
|
||||
explicit VeryLongStructName(int i);
|
||||
|
||||
int VeryLongMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
|
||||
|
||||
static int VeryLongStaticMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
|
||||
|
||||
private:
|
||||
int fld;
|
||||
};
|
||||
|
||||
TEST(UniqueSmallName, Struct) {
|
||||
VeryLongStructName var(10);
|
||||
|
||||
DoNotOptimize(var);
|
||||
DoNotOptimize(&VeryLongStructName::VeryLongMethodName);
|
||||
DoNotOptimize(&VeryLongStructName::VeryLongStaticMethodName);
|
||||
|
||||
EXPECT_EQ(var.VeryLongMethodName(), 10);
|
||||
EXPECT_EQ(VeryLongStructName::VeryLongStaticMethodName(), 123);
|
||||
}
|
||||
|
||||
VeryLongStructName::VeryLongStructName(int i) : fld(i) {}
|
||||
int VeryLongStructName::VeryLongMethodName() { return fld; }
|
||||
int VeryLongStructName::VeryLongStaticMethodName() { return 123; }
|
||||
|
||||
} // namespace
|
||||
@ -87,6 +87,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 +123,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();
|
||||
|
||||
@ -15,8 +15,8 @@
|
||||
// UnscaledCycleClock
|
||||
// An UnscaledCycleClock yields the value and frequency of a cycle counter
|
||||
// that increments at a rate that is approximately constant.
|
||||
// This class is for internal / whitelisted use only, you should consider
|
||||
// using CycleClock instead.
|
||||
// This class is for internal use only, you should consider using CycleClock
|
||||
// instead.
|
||||
//
|
||||
// Notes:
|
||||
// The cycle counter frequency is not necessarily the core clock frequency.
|
||||
@ -46,8 +46,8 @@
|
||||
|
||||
// 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)
|
||||
defined(__powerpc__) || defined(__ppc__) || defined(__riscv) || \
|
||||
defined(_M_IX86) || defined(_M_X64)
|
||||
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
|
||||
#else
|
||||
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
|
||||
@ -80,8 +80,8 @@
|
||||
|
||||
// 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))
|
||||
#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \
|
||||
defined(_M_IX86) || defined(_M_X64))
|
||||
#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
|
||||
#endif
|
||||
|
||||
@ -109,7 +109,7 @@ class UnscaledCycleClock {
|
||||
// value.
|
||||
static double Frequency();
|
||||
|
||||
// Whitelisted friends.
|
||||
// Allowed users
|
||||
friend class base_internal::CycleClock;
|
||||
friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime;
|
||||
friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency;
|
||||
|
||||
128
third_party/abseil-cpp/absl/base/invoke_test.cc
vendored
128
third_party/abseil-cpp/absl/base/invoke_test.cc
vendored
@ -86,71 +86,73 @@ struct FlipFlop {
|
||||
int member;
|
||||
};
|
||||
|
||||
// CallMaybeWithArg(f) resolves either to Invoke(f) or Invoke(f, 42), depending
|
||||
// CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
|
||||
// on which one is valid.
|
||||
template <typename F>
|
||||
decltype(Invoke(std::declval<const F&>())) CallMaybeWithArg(const F& f) {
|
||||
return Invoke(f);
|
||||
decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
|
||||
const F& f) {
|
||||
return base_internal::invoke(f);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
decltype(Invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(const F& f) {
|
||||
return Invoke(f, 42);
|
||||
decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
|
||||
const F& f) {
|
||||
return base_internal::invoke(f, 42);
|
||||
}
|
||||
|
||||
TEST(InvokeTest, Function) {
|
||||
EXPECT_EQ(1, Invoke(Function, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Function, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, NonCopyableArgument) {
|
||||
EXPECT_EQ(42, Invoke(Sink, make_unique<int>(42)));
|
||||
EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, NonCopyableResult) {
|
||||
EXPECT_THAT(Invoke(Factory, 42), ::testing::Pointee(42));
|
||||
EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, VoidResult) {
|
||||
Invoke(NoOp);
|
||||
}
|
||||
TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
|
||||
|
||||
TEST(InvokeTest, ConstFunctor) {
|
||||
EXPECT_EQ(1, Invoke(ConstFunctor(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, MutableFunctor) {
|
||||
MutableFunctor f;
|
||||
EXPECT_EQ(1, Invoke(f, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(MutableFunctor(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, EphemeralFunctor) {
|
||||
EphemeralFunctor f;
|
||||
EXPECT_EQ(1, Invoke(std::move(f), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(EphemeralFunctor(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, OverloadedFunctor) {
|
||||
OverloadedFunctor f;
|
||||
const OverloadedFunctor& cf = f;
|
||||
|
||||
EXPECT_EQ("&", Invoke(f));
|
||||
EXPECT_EQ("& 42", Invoke(f, " 42"));
|
||||
EXPECT_EQ("&", base_internal::invoke(f));
|
||||
EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
|
||||
|
||||
EXPECT_EQ("const&", Invoke(cf));
|
||||
EXPECT_EQ("const& 42", Invoke(cf, " 42"));
|
||||
EXPECT_EQ("const&", base_internal::invoke(cf));
|
||||
EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
|
||||
|
||||
EXPECT_EQ("&&", Invoke(std::move(f)));
|
||||
EXPECT_EQ("&& 42", Invoke(std::move(f), " 42"));
|
||||
EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
|
||||
|
||||
OverloadedFunctor f2;
|
||||
EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, ReferenceWrapper) {
|
||||
ConstFunctor cf;
|
||||
MutableFunctor mf;
|
||||
EXPECT_EQ(1, Invoke(std::cref(cf), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(std::ref(cf), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(std::ref(mf), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, MemberFunction) {
|
||||
@ -158,58 +160,62 @@ TEST(InvokeTest, MemberFunction) {
|
||||
std::unique_ptr<const Class> cp(new Class);
|
||||
std::unique_ptr<volatile Class> vp(new Class);
|
||||
|
||||
EXPECT_EQ(1, Invoke(&Class::Method, p, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::Method, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::Method, *p, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::RefMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::RefMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::RefMethod, *p, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::RefRefMethod, std::move(*p), 3, 2)); // NOLINT
|
||||
EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, *p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
|
||||
2)); // NOLINT
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));
|
||||
|
||||
EXPECT_EQ(1, Invoke(&Class::ConstMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::ConstMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::ConstMethod, *p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));
|
||||
|
||||
EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp.get(), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::ConstMethod, *cp, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));
|
||||
|
||||
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *p, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp, 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp.get(), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *vp, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));
|
||||
|
||||
EXPECT_EQ(1, Invoke(&Class::Method, make_unique<Class>(), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<Class>(), 3, 2));
|
||||
EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<const Class>(), 3, 2));
|
||||
EXPECT_EQ(1,
|
||||
base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
|
||||
3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
|
||||
make_unique<const Class>(), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, DataMember) {
|
||||
std::unique_ptr<Class> p(new Class{42});
|
||||
std::unique_ptr<const Class> cp(new Class{42});
|
||||
EXPECT_EQ(42, Invoke(&Class::member, p));
|
||||
EXPECT_EQ(42, Invoke(&Class::member, *p));
|
||||
EXPECT_EQ(42, Invoke(&Class::member, p.get()));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));
|
||||
|
||||
Invoke(&Class::member, p) = 42;
|
||||
Invoke(&Class::member, p.get()) = 42;
|
||||
base_internal::invoke(&Class::member, p) = 42;
|
||||
base_internal::invoke(&Class::member, p.get()) = 42;
|
||||
|
||||
EXPECT_EQ(42, Invoke(&Class::member, cp));
|
||||
EXPECT_EQ(42, Invoke(&Class::member, *cp));
|
||||
EXPECT_EQ(42, Invoke(&Class::member, cp.get()));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, FlipFlop) {
|
||||
FlipFlop obj = {42};
|
||||
// This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
|
||||
// ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
|
||||
EXPECT_EQ(42, Invoke(&FlipFlop::ConstMethod, obj));
|
||||
EXPECT_EQ(42, Invoke(&FlipFlop::member, obj));
|
||||
EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
|
||||
EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, SfinaeFriendly) {
|
||||
|
||||
@ -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));
|
||||
@ -118,4 +118,4 @@ std::ostream& operator<<(std::ostream& os, absl::LogSeverity s);
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
|
||||
#endif // ABSL_BASE_LOG_SEVERITY_H_
|
||||
|
||||
@ -52,9 +52,9 @@ TEST(StreamTest, Works) {
|
||||
Eq("absl::LogSeverity(4)"));
|
||||
}
|
||||
|
||||
static_assert(
|
||||
absl::flags_internal::IsAtomicFlagTypeTrait<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(
|
||||
|
||||
156
third_party/abseil-cpp/absl/base/macros.h
vendored
156
third_party/abseil-cpp/absl/base/macros.h
vendored
@ -32,6 +32,7 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/optimization.h"
|
||||
#include "absl/base/port.h"
|
||||
|
||||
@ -54,115 +55,6 @@ auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
// kLinkerInitialized
|
||||
//
|
||||
// An enum used only as a constructor argument to indicate that a variable has
|
||||
// static storage duration, and that the constructor should do nothing to its
|
||||
// state. Use of this macro indicates to the reader that it is legal to
|
||||
// declare a static instance of the class, provided the constructor is given
|
||||
// the absl::base_internal::kLinkerInitialized argument.
|
||||
//
|
||||
// Normally, it is unsafe to declare a static variable that has a constructor or
|
||||
// a destructor because invocation order is undefined. However, if the type can
|
||||
// be zero-initialized (which the loader does for static variables) into a valid
|
||||
// state and the type's destructor does not affect storage, then a constructor
|
||||
// for static initialization can be declared.
|
||||
//
|
||||
// Example:
|
||||
// // Declaration
|
||||
// explicit MyClass(absl::base_internal:LinkerInitialized x) {}
|
||||
//
|
||||
// // Invocation
|
||||
// static MyClass my_global(absl::base_internal::kLinkerInitialized);
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
enum LinkerInitialized {
|
||||
kLinkerInitialized = 0,
|
||||
};
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
// ABSL_FALLTHROUGH_INTENDED
|
||||
//
|
||||
// Annotates implicit fall-through between switch labels, allowing a case to
|
||||
// indicate intentional fallthrough and turn off warnings about any lack of a
|
||||
// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by
|
||||
// a semicolon and can be used in most places where `break` can, provided that
|
||||
// no statements exist between it and the next switch label.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// switch (x) {
|
||||
// case 40:
|
||||
// case 41:
|
||||
// if (truth_is_out_there) {
|
||||
// ++x;
|
||||
// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations
|
||||
// // in comments
|
||||
// } else {
|
||||
// return x;
|
||||
// }
|
||||
// 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:
|
||||
// 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
|
||||
// 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")
|
||||
#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
|
||||
#endif
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 7
|
||||
#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
|
||||
#endif
|
||||
|
||||
#ifndef ABSL_FALLTHROUGH_INTENDED
|
||||
#define ABSL_FALLTHROUGH_INTENDED \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
// ABSL_DEPRECATED()
|
||||
//
|
||||
// Marks a deprecated class, struct, enum, function, method and variable
|
||||
// declarations. The macro argument is used as a custom diagnostic message (e.g.
|
||||
// suggestion of a better alternative).
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// class ABSL_DEPRECATED("Use Bar instead") Foo {...};
|
||||
//
|
||||
// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...}
|
||||
//
|
||||
// template <typename T>
|
||||
// ABSL_DEPRECATED("Use DoThat() instead")
|
||||
// void DoThis();
|
||||
//
|
||||
// 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
|
||||
#define ABSL_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
#endif
|
||||
|
||||
#ifndef ABSL_DEPRECATED
|
||||
#define ABSL_DEPRECATED(message)
|
||||
#endif
|
||||
|
||||
// ABSL_BAD_CALL_IF()
|
||||
//
|
||||
// Used on a function overload to trap bad calls: any call that matches the
|
||||
@ -207,6 +99,41 @@ ABSL_NAMESPACE_END
|
||||
: [] { assert(false && #expr); }()) // NOLINT
|
||||
#endif
|
||||
|
||||
// `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()`
|
||||
// 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(); \
|
||||
} while (false)
|
||||
#else
|
||||
#define ABSL_INTERNAL_HARDENING_ABORT() abort()
|
||||
#endif
|
||||
|
||||
// ABSL_HARDENING_ASSERT()
|
||||
//
|
||||
// `ABSL_HARDENING_ASSERT()` is like `ABSL_ASSERT()`, but used to implement
|
||||
// runtime assertions that should be enabled in hardened builds even when
|
||||
// `NDEBUG` is defined.
|
||||
//
|
||||
// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT()` is identical to
|
||||
// `ABSL_ASSERT()`.
|
||||
//
|
||||
// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
|
||||
// hardened mode.
|
||||
#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
|
||||
#define ABSL_HARDENING_ASSERT(expr) \
|
||||
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
|
||||
: [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
|
||||
#else
|
||||
#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr)
|
||||
#endif
|
||||
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
#define ABSL_INTERNAL_TRY try
|
||||
#define ABSL_INTERNAL_CATCH_ANY catch (...)
|
||||
@ -217,4 +144,15 @@ ABSL_NAMESPACE_END
|
||||
#define ABSL_INTERNAL_RETHROW do {} while (false)
|
||||
#endif // ABSL_HAVE_EXCEPTIONS
|
||||
|
||||
// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which
|
||||
// reaches one has undefined behavior, and the compiler may optimize
|
||||
// accordingly.
|
||||
#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
|
||||
#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
#define ABSL_INTERNAL_UNREACHABLE __assume(0)
|
||||
#else
|
||||
#define ABSL_INTERNAL_UNREACHABLE
|
||||
#endif
|
||||
|
||||
#endif // ABSL_BASE_MACROS_H_
|
||||
|
||||
75
third_party/abseil-cpp/absl/base/optimization.h
vendored
75
third_party/abseil-cpp/absl/base/optimization.h
vendored
@ -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:
|
||||
//
|
||||
@ -104,9 +106,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.
|
||||
@ -171,11 +174,71 @@
|
||||
// to yield performance improvements.
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_expect) || \
|
||||
(defined(__GNUC__) && !defined(__clang__))
|
||||
#define ABSL_PREDICT_FALSE(x) (__builtin_expect(x, 0))
|
||||
#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false))
|
||||
#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true))
|
||||
#else
|
||||
#define ABSL_PREDICT_FALSE(x) (x)
|
||||
#define ABSL_PREDICT_TRUE(x) (x)
|
||||
#endif
|
||||
|
||||
// ABSL_INTERNAL_ASSUME(cond)
|
||||
// Informs the compiler that 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.
|
||||
// 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.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// int x = ...;
|
||||
// ABSL_INTERNAL_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)
|
||||
#elif ABSL_HAVE_BUILTIN(__builtin_assume)
|
||||
#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond)
|
||||
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
|
||||
#define ABSL_INTERNAL_ASSUME(cond) \
|
||||
do { \
|
||||
if (!(cond)) __builtin_unreachable(); \
|
||||
} while (0)
|
||||
#elif defined(_MSC_VER)
|
||||
#define ABSL_INTERNAL_ASSUME(cond) __assume(cond)
|
||||
#else
|
||||
#define ABSL_INTERNAL_ASSUME(cond) \
|
||||
do { \
|
||||
static_cast<void>(false && (cond)); \
|
||||
} while (0)
|
||||
#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 cause a link time
|
||||
// conflict.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// #define MY_MACRO(txt)
|
||||
// namespace {
|
||||
// char VeryVeryLongVarName[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = txt;
|
||||
// const char* VeryVeryLongFuncName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
|
||||
// const char* VeryVeryLongFuncName() { return txt; }
|
||||
// }
|
||||
//
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) #x
|
||||
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME1(x) ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x)
|
||||
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
|
||||
asm(ABSL_INTERNAL_UNIQUE_SMALL_NAME1(.absl.__COUNTER__))
|
||||
#else
|
||||
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME()
|
||||
#endif
|
||||
|
||||
#endif // ABSL_BASE_OPTIMIZATION_H_
|
||||
|
||||
129
third_party/abseil-cpp/absl/base/optimization_test.cc
vendored
Normal file
129
third_party/abseil-cpp/absl/base/optimization_test.cc
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/optimization.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Tests for the ABSL_PREDICT_TRUE and ABSL_PREDICT_FALSE macros.
|
||||
// The tests only verify that the macros are functionally correct - i.e. code
|
||||
// behaves as if they weren't used. They don't try to check their impact on
|
||||
// optimization.
|
||||
|
||||
TEST(PredictTest, PredictTrue) {
|
||||
EXPECT_TRUE(ABSL_PREDICT_TRUE(true));
|
||||
EXPECT_FALSE(ABSL_PREDICT_TRUE(false));
|
||||
EXPECT_TRUE(ABSL_PREDICT_TRUE(1 == 1));
|
||||
EXPECT_FALSE(ABSL_PREDICT_TRUE(1 == 2));
|
||||
|
||||
if (ABSL_PREDICT_TRUE(false)) ADD_FAILURE();
|
||||
if (!ABSL_PREDICT_TRUE(true)) ADD_FAILURE();
|
||||
|
||||
EXPECT_TRUE(ABSL_PREDICT_TRUE(true) && true);
|
||||
EXPECT_TRUE(ABSL_PREDICT_TRUE(true) || false);
|
||||
}
|
||||
|
||||
TEST(PredictTest, PredictFalse) {
|
||||
EXPECT_TRUE(ABSL_PREDICT_FALSE(true));
|
||||
EXPECT_FALSE(ABSL_PREDICT_FALSE(false));
|
||||
EXPECT_TRUE(ABSL_PREDICT_FALSE(1 == 1));
|
||||
EXPECT_FALSE(ABSL_PREDICT_FALSE(1 == 2));
|
||||
|
||||
if (ABSL_PREDICT_FALSE(false)) ADD_FAILURE();
|
||||
if (!ABSL_PREDICT_FALSE(true)) ADD_FAILURE();
|
||||
|
||||
EXPECT_TRUE(ABSL_PREDICT_FALSE(true) && true);
|
||||
EXPECT_TRUE(ABSL_PREDICT_FALSE(true) || false);
|
||||
}
|
||||
|
||||
TEST(PredictTest, OneEvaluation) {
|
||||
// Verify that the expression is only evaluated once.
|
||||
int x = 0;
|
||||
if (ABSL_PREDICT_TRUE((++x) == 0)) ADD_FAILURE();
|
||||
EXPECT_EQ(x, 1);
|
||||
if (ABSL_PREDICT_FALSE((++x) == 0)) ADD_FAILURE();
|
||||
EXPECT_EQ(x, 2);
|
||||
}
|
||||
|
||||
TEST(PredictTest, OperatorOrder) {
|
||||
// Verify that operator order inside and outside the macro behaves well.
|
||||
// These would fail for a naive '#define ABSL_PREDICT_TRUE(x) x'
|
||||
EXPECT_TRUE(ABSL_PREDICT_TRUE(1 && 2) == true);
|
||||
EXPECT_TRUE(ABSL_PREDICT_FALSE(1 && 2) == true);
|
||||
EXPECT_TRUE(!ABSL_PREDICT_TRUE(1 == 2));
|
||||
EXPECT_TRUE(!ABSL_PREDICT_FALSE(1 == 2));
|
||||
}
|
||||
|
||||
TEST(PredictTest, Pointer) {
|
||||
const int x = 3;
|
||||
const int *good_intptr = &x;
|
||||
const int *null_intptr = nullptr;
|
||||
EXPECT_TRUE(ABSL_PREDICT_TRUE(good_intptr));
|
||||
EXPECT_FALSE(ABSL_PREDICT_TRUE(null_intptr));
|
||||
EXPECT_TRUE(ABSL_PREDICT_FALSE(good_intptr));
|
||||
EXPECT_FALSE(ABSL_PREDICT_FALSE(null_intptr));
|
||||
}
|
||||
|
||||
TEST(PredictTest, Optional) {
|
||||
// Note: An optional's truth value is the value's existence, not its truth.
|
||||
absl::optional<bool> has_value(false);
|
||||
absl::optional<bool> no_value;
|
||||
EXPECT_TRUE(ABSL_PREDICT_TRUE(has_value));
|
||||
EXPECT_FALSE(ABSL_PREDICT_TRUE(no_value));
|
||||
EXPECT_TRUE(ABSL_PREDICT_FALSE(has_value));
|
||||
EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
|
||||
}
|
||||
|
||||
class ImplictlyConvertibleToBool {
|
||||
public:
|
||||
explicit ImplictlyConvertibleToBool(bool value) : value_(value) {}
|
||||
operator bool() const { // NOLINT(google-explicit-constructor)
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool value_;
|
||||
};
|
||||
|
||||
TEST(PredictTest, ImplicitBoolConversion) {
|
||||
const ImplictlyConvertibleToBool is_true(true);
|
||||
const ImplictlyConvertibleToBool is_false(false);
|
||||
if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
|
||||
if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
|
||||
}
|
||||
|
||||
class ExplictlyConvertibleToBool {
|
||||
public:
|
||||
explicit ExplictlyConvertibleToBool(bool value) : value_(value) {}
|
||||
explicit operator bool() const { return value_; }
|
||||
|
||||
private:
|
||||
bool value_;
|
||||
};
|
||||
|
||||
TEST(PredictTest, ExplicitBoolConversion) {
|
||||
const ExplictlyConvertibleToBool is_true(true);
|
||||
const ExplictlyConvertibleToBool is_false(false);
|
||||
if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
|
||||
if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
35
third_party/abseil-cpp/absl/base/options.h
vendored
35
third_party/abseil-cpp/absl/base/options.h
vendored
@ -1,6 +1,3 @@
|
||||
#ifndef ABSL_BASE_OPTIONS_H_
|
||||
#define ABSL_BASE_OPTIONS_H_
|
||||
|
||||
// Copyright 2019 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -67,6 +64,9 @@
|
||||
// proper Abseil implementation at compile-time, which will not be sufficient
|
||||
// to guarantee ABI stability to package managers.
|
||||
|
||||
#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
|
||||
@ -206,6 +206,33 @@
|
||||
// allowed.
|
||||
|
||||
#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
|
||||
#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_2020_02_25
|
||||
#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20211102
|
||||
|
||||
// ABSL_OPTION_HARDENED
|
||||
//
|
||||
// This option enables a "hardened" build in release mode (in this context,
|
||||
// release mode is defined as a build where the `NDEBUG` macro is defined).
|
||||
//
|
||||
// A value of 0 means that "hardened" mode is not enabled.
|
||||
//
|
||||
// A value of 1 means that "hardened" mode is enabled.
|
||||
//
|
||||
// Hardened builds have additional security checks enabled when `NDEBUG` is
|
||||
// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a
|
||||
// no-op, as well as disabling other bespoke program consistency checks. By
|
||||
// defining ABSL_OPTION_HARDENED to 1, a select set of checks remain enabled in
|
||||
// release mode. These checks guard against programming errors that may lead to
|
||||
// security vulnerabilities. In release mode, when one of these programming
|
||||
// errors is encountered, the program will immediately abort, possibly without
|
||||
// any attempt at logging.
|
||||
//
|
||||
// The checks enabled by this option are not free; they do incur runtime cost.
|
||||
//
|
||||
// The checks enabled by this option are always active when `NDEBUG` is not
|
||||
// defined, even in the case when ABSL_OPTION_HARDENED is defined to 0. The
|
||||
// checks enabled by this option may abort the program in a different way and
|
||||
// log additional information when `NDEBUG` is not defined.
|
||||
|
||||
#define ABSL_OPTION_HARDENED 0
|
||||
|
||||
#endif // ABSL_BASE_OPTIONS_H_
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Compiler Check
|
||||
// Toolchain Check
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// We support MSVC++ 14.0 update 2 and later.
|
||||
|
||||
1
third_party/abseil-cpp/absl/base/port.h
vendored
1
third_party/abseil-cpp/absl/base/port.h
vendored
@ -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_
|
||||
|
||||
@ -20,10 +20,12 @@
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <thread> // NOLINT(build/c++11)
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/low_level_scheduling.h"
|
||||
#include "absl/base/internal/scheduling_mode.h"
|
||||
#include "absl/base/internal/spinlock.h"
|
||||
@ -56,12 +58,10 @@ namespace {
|
||||
static constexpr int kArrayLength = 10;
|
||||
static uint32_t values[kArrayLength];
|
||||
|
||||
static SpinLock static_spinlock(base_internal::kLinkerInitialized);
|
||||
static SpinLock static_cooperative_spinlock(
|
||||
base_internal::kLinkerInitialized,
|
||||
base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
|
||||
static SpinLock static_noncooperative_spinlock(
|
||||
base_internal::kLinkerInitialized, base_internal::SCHEDULE_KERNEL_ONLY);
|
||||
ABSL_CONST_INIT static SpinLock static_cooperative_spinlock(
|
||||
absl::kConstInit, base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
|
||||
ABSL_CONST_INIT static SpinLock static_noncooperative_spinlock(
|
||||
absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
|
||||
|
||||
// Simple integer hash function based on the public domain lookup2 hash.
|
||||
// http://burtleburtle.net/bob/c/lookup2.c
|
||||
@ -92,6 +92,7 @@ static void TestFunction(int thread_salt, SpinLock* spinlock) {
|
||||
|
||||
static void ThreadedTest(SpinLock* spinlock) {
|
||||
std::vector<std::thread> threads;
|
||||
threads.reserve(kNumThreads);
|
||||
for (int i = 0; i < kNumThreads; ++i) {
|
||||
threads.push_back(std::thread(TestFunction, i, spinlock));
|
||||
}
|
||||
@ -105,6 +106,10 @@ static void ThreadedTest(SpinLock* spinlock) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ABSL_HAVE_THREAD_SANITIZER
|
||||
static_assert(std::is_trivially_destructible<SpinLock>(), "");
|
||||
#endif
|
||||
|
||||
TEST(SpinLock, StackNonCooperativeDisablesScheduling) {
|
||||
SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY);
|
||||
spinlock.Lock();
|
||||
@ -191,10 +196,6 @@ TEST(SpinLock, WaitCyclesEncoding) {
|
||||
EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
|
||||
}
|
||||
|
||||
TEST(SpinLockWithThreads, StaticSpinLock) {
|
||||
ThreadedTest(&static_spinlock);
|
||||
}
|
||||
|
||||
TEST(SpinLockWithThreads, StackSpinLock) {
|
||||
SpinLock spinlock;
|
||||
ThreadedTest(&spinlock);
|
||||
|
||||
@ -34,16 +34,11 @@
|
||||
#ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
|
||||
#define ABSL_BASE_THREAD_ANNOTATIONS_H_
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
// TODO(mbonadei): Remove after the backward compatibility period.
|
||||
#include "absl/base/internal/thread_annotations.h" // IWYU pragma: export
|
||||
|
||||
#if defined(__clang__)
|
||||
#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x))
|
||||
#else
|
||||
#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) // no-op
|
||||
#endif
|
||||
|
||||
// ABSL_GUARDED_BY()
|
||||
//
|
||||
// Documents if a shared field or global variable needs to be protected by a
|
||||
@ -61,8 +56,11 @@
|
||||
// int p1_ ABSL_GUARDED_BY(mu_);
|
||||
// ...
|
||||
// };
|
||||
#define ABSL_GUARDED_BY(x) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(guarded_by(x))
|
||||
#if ABSL_HAVE_ATTRIBUTE(guarded_by)
|
||||
#define ABSL_GUARDED_BY(x) __attribute__((guarded_by(x)))
|
||||
#else
|
||||
#define ABSL_GUARDED_BY(x)
|
||||
#endif
|
||||
|
||||
// ABSL_PT_GUARDED_BY()
|
||||
//
|
||||
@ -84,8 +82,11 @@
|
||||
// // `q_`, guarded by `mu1_`, points to a shared memory location that is
|
||||
// // guarded by `mu2_`:
|
||||
// int *q_ ABSL_GUARDED_BY(mu1_) ABSL_PT_GUARDED_BY(mu2_);
|
||||
#define ABSL_PT_GUARDED_BY(x) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(pt_guarded_by(x))
|
||||
#if ABSL_HAVE_ATTRIBUTE(pt_guarded_by)
|
||||
#define ABSL_PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
|
||||
#else
|
||||
#define ABSL_PT_GUARDED_BY(x)
|
||||
#endif
|
||||
|
||||
// ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE()
|
||||
//
|
||||
@ -102,11 +103,17 @@
|
||||
//
|
||||
// Mutex m1_;
|
||||
// Mutex m2_ ABSL_ACQUIRED_AFTER(m1_);
|
||||
#define ABSL_ACQUIRED_AFTER(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_after(__VA_ARGS__))
|
||||
#if ABSL_HAVE_ATTRIBUTE(acquired_after)
|
||||
#define ABSL_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_ACQUIRED_AFTER(...)
|
||||
#endif
|
||||
|
||||
#define ABSL_ACQUIRED_BEFORE(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_before(__VA_ARGS__))
|
||||
#if ABSL_HAVE_ATTRIBUTE(acquired_before)
|
||||
#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_ACQUIRED_BEFORE(...)
|
||||
#endif
|
||||
|
||||
// ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED()
|
||||
//
|
||||
@ -131,33 +138,50 @@
|
||||
//
|
||||
// void foo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
|
||||
// void bar() const ABSL_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
|
||||
#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
|
||||
exclusive_locks_required(__VA_ARGS__))
|
||||
#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required)
|
||||
#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \
|
||||
__attribute__((exclusive_locks_required(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)
|
||||
#endif
|
||||
|
||||
#if ABSL_HAVE_ATTRIBUTE(shared_locks_required)
|
||||
#define ABSL_SHARED_LOCKS_REQUIRED(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_locks_required(__VA_ARGS__))
|
||||
__attribute__((shared_locks_required(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_SHARED_LOCKS_REQUIRED(...)
|
||||
#endif
|
||||
|
||||
// ABSL_LOCKS_EXCLUDED()
|
||||
//
|
||||
// Documents the locks acquired in the body of the function. These locks
|
||||
// cannot be held when calling this function (as Abseil's `Mutex` locks are
|
||||
// non-reentrant).
|
||||
#define ABSL_LOCKS_EXCLUDED(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(locks_excluded(__VA_ARGS__))
|
||||
#if ABSL_HAVE_ATTRIBUTE(locks_excluded)
|
||||
#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_LOCKS_EXCLUDED(...)
|
||||
#endif
|
||||
|
||||
// ABSL_LOCK_RETURNED()
|
||||
//
|
||||
// Documents a function that returns a mutex without acquiring it. For example,
|
||||
// a public getter method that returns a pointer to a private mutex should
|
||||
// be annotated with ABSL_LOCK_RETURNED.
|
||||
#define ABSL_LOCK_RETURNED(x) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lock_returned(x))
|
||||
#if ABSL_HAVE_ATTRIBUTE(lock_returned)
|
||||
#define ABSL_LOCK_RETURNED(x) __attribute__((lock_returned(x)))
|
||||
#else
|
||||
#define ABSL_LOCK_RETURNED(x)
|
||||
#endif
|
||||
|
||||
// ABSL_LOCKABLE
|
||||
//
|
||||
// Documents if a class/type is a lockable type (such as the `Mutex` class).
|
||||
#define ABSL_LOCKABLE ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lockable)
|
||||
#if ABSL_HAVE_ATTRIBUTE(lockable)
|
||||
#define ABSL_LOCKABLE __attribute__((lockable))
|
||||
#else
|
||||
#define ABSL_LOCKABLE
|
||||
#endif
|
||||
|
||||
// ABSL_SCOPED_LOCKABLE
|
||||
//
|
||||
@ -166,30 +190,43 @@
|
||||
// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no
|
||||
// arguments; the analysis will assume that the destructor unlocks whatever the
|
||||
// constructor locked.
|
||||
#define ABSL_SCOPED_LOCKABLE \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(scoped_lockable)
|
||||
#if ABSL_HAVE_ATTRIBUTE(scoped_lockable)
|
||||
#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable))
|
||||
#else
|
||||
#define ABSL_SCOPED_LOCKABLE
|
||||
#endif
|
||||
|
||||
// ABSL_EXCLUSIVE_LOCK_FUNCTION()
|
||||
//
|
||||
// Documents functions that acquire a lock in the body of a function, and do
|
||||
// not release it.
|
||||
#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
|
||||
exclusive_lock_function(__VA_ARGS__))
|
||||
#if ABSL_HAVE_ATTRIBUTE(exclusive_lock_function)
|
||||
#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \
|
||||
__attribute__((exclusive_lock_function(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...)
|
||||
#endif
|
||||
|
||||
// ABSL_SHARED_LOCK_FUNCTION()
|
||||
//
|
||||
// Documents functions that acquire a shared (reader) lock in the body of a
|
||||
// function, and do not release it.
|
||||
#if ABSL_HAVE_ATTRIBUTE(shared_lock_function)
|
||||
#define ABSL_SHARED_LOCK_FUNCTION(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_lock_function(__VA_ARGS__))
|
||||
__attribute__((shared_lock_function(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_SHARED_LOCK_FUNCTION(...)
|
||||
#endif
|
||||
|
||||
// ABSL_UNLOCK_FUNCTION()
|
||||
//
|
||||
// Documents functions that expect a lock to be held on entry to the function,
|
||||
// and release it in the body of the function.
|
||||
#define ABSL_UNLOCK_FUNCTION(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(unlock_function(__VA_ARGS__))
|
||||
#if ABSL_HAVE_ATTRIBUTE(unlock_function)
|
||||
#define ABSL_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_UNLOCK_FUNCTION(...)
|
||||
#endif
|
||||
|
||||
// ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION()
|
||||
//
|
||||
@ -199,31 +236,49 @@
|
||||
// success, or `false` for functions that return `false` on success. The second
|
||||
// argument specifies the mutex that is locked on success. If unspecified, this
|
||||
// mutex is assumed to be `this`.
|
||||
#if ABSL_HAVE_ATTRIBUTE(exclusive_trylock_function)
|
||||
#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
|
||||
exclusive_trylock_function(__VA_ARGS__))
|
||||
__attribute__((exclusive_trylock_function(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...)
|
||||
#endif
|
||||
|
||||
#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
|
||||
shared_trylock_function(__VA_ARGS__))
|
||||
#if ABSL_HAVE_ATTRIBUTE(shared_trylock_function)
|
||||
#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \
|
||||
__attribute__((shared_trylock_function(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_SHARED_TRYLOCK_FUNCTION(...)
|
||||
#endif
|
||||
|
||||
// ABSL_ASSERT_EXCLUSIVE_LOCK() / ABSL_ASSERT_SHARED_LOCK()
|
||||
//
|
||||
// Documents functions that dynamically check to see if a lock is held, and fail
|
||||
// if it is not held.
|
||||
#if ABSL_HAVE_ATTRIBUTE(assert_exclusive_lock)
|
||||
#define ABSL_ASSERT_EXCLUSIVE_LOCK(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_exclusive_lock(__VA_ARGS__))
|
||||
__attribute__((assert_exclusive_lock(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_ASSERT_EXCLUSIVE_LOCK(...)
|
||||
#endif
|
||||
|
||||
#if ABSL_HAVE_ATTRIBUTE(assert_shared_lock)
|
||||
#define ABSL_ASSERT_SHARED_LOCK(...) \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_shared_lock(__VA_ARGS__))
|
||||
__attribute__((assert_shared_lock(__VA_ARGS__)))
|
||||
#else
|
||||
#define ABSL_ASSERT_SHARED_LOCK(...)
|
||||
#endif
|
||||
|
||||
// ABSL_NO_THREAD_SAFETY_ANALYSIS
|
||||
//
|
||||
// Turns off thread safety checking within the body of a particular function.
|
||||
// This annotation is used to mark functions that are known to be correct, but
|
||||
// the locking behavior is more complicated than the analyzer can handle.
|
||||
#if ABSL_HAVE_ATTRIBUTE(no_thread_safety_analysis)
|
||||
#define ABSL_NO_THREAD_SAFETY_ANALYSIS \
|
||||
ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(no_thread_safety_analysis)
|
||||
__attribute__((no_thread_safety_analysis))
|
||||
#else
|
||||
#define ABSL_NO_THREAD_SAFETY_ANALYSIS
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Tool-Supplied Annotations
|
||||
@ -262,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;
|
||||
|
||||
65
third_party/abseil-cpp/absl/cleanup/BUILD.bazel
vendored
Normal file
65
third_party/abseil-cpp/absl/cleanup/BUILD.bazel
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
# Copyright 2021 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.
|
||||
|
||||
load(
|
||||
"//absl:copts/configure_copts.bzl",
|
||||
"ABSL_DEFAULT_COPTS",
|
||||
"ABSL_DEFAULT_LINKOPTS",
|
||||
"ABSL_TEST_COPTS",
|
||||
)
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "cleanup_internal",
|
||||
hdrs = ["internal/cleanup.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
"//absl/base:base_internal",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/utility",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "cleanup",
|
||||
hdrs = [
|
||||
"cleanup.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":cleanup_internal",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "cleanup_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"cleanup_test.cc",
|
||||
],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
deps = [
|
||||
":cleanup",
|
||||
"//absl/base:config",
|
||||
"//absl/utility",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
55
third_party/abseil-cpp/absl/cleanup/CMakeLists.txt
vendored
Normal file
55
third_party/abseil-cpp/absl/cleanup/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
# Copyright 2021 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.
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
cleanup_internal
|
||||
HDRS
|
||||
"internal/cleanup.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::base_internal
|
||||
absl::core_headers
|
||||
absl::utility
|
||||
PUBLIC
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
cleanup
|
||||
HDRS
|
||||
"cleanup.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::cleanup_internal
|
||||
absl::config
|
||||
absl::core_headers
|
||||
PUBLIC
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
cleanup_test
|
||||
SRCS
|
||||
"cleanup_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::cleanup
|
||||
absl::config
|
||||
absl::utility
|
||||
GTest::gmock_main
|
||||
)
|
||||
140
third_party/abseil-cpp/absl/cleanup/cleanup.h
vendored
Normal file
140
third_party/abseil-cpp/absl/cleanup/cleanup.h
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
// Copyright 2021 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: cleanup.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// `absl::Cleanup` implements the scope guard idiom, invoking the contained
|
||||
// callback's `operator()() &&` on scope exit.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ```
|
||||
// absl::Status CopyGoodData(const char* source_path, const char* sink_path) {
|
||||
// FILE* source_file = fopen(source_path, "r");
|
||||
// if (source_file == nullptr) {
|
||||
// return absl::NotFoundError("No source file"); // No cleanups execute
|
||||
// }
|
||||
//
|
||||
// // C++17 style cleanup using class template argument deduction
|
||||
// absl::Cleanup source_closer = [source_file] { fclose(source_file); };
|
||||
//
|
||||
// FILE* sink_file = fopen(sink_path, "w");
|
||||
// if (sink_file == nullptr) {
|
||||
// return absl::NotFoundError("No sink file"); // First cleanup executes
|
||||
// }
|
||||
//
|
||||
// // C++11 style cleanup using the factory function
|
||||
// auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); });
|
||||
//
|
||||
// Data data;
|
||||
// while (ReadData(source_file, &data)) {
|
||||
// if (!data.IsGood()) {
|
||||
// absl::Status result = absl::FailedPreconditionError("Read bad data");
|
||||
// return result; // Both cleanups execute
|
||||
// }
|
||||
// SaveData(sink_file, &data);
|
||||
// }
|
||||
//
|
||||
// return absl::OkStatus(); // Both cleanups execute
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Methods:
|
||||
//
|
||||
// `std::move(cleanup).Cancel()` will prevent the callback from executing.
|
||||
//
|
||||
// `std::move(cleanup).Invoke()` will execute the callback early, before
|
||||
// destruction, and prevent the callback from executing in the destructor.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// `absl::Cleanup` is not an interface type. It is only intended to be used
|
||||
// within the body of a function. It is not a value type and instead models a
|
||||
// control flow construct. Check out `defer` in Golang for something similar.
|
||||
|
||||
#ifndef ABSL_CLEANUP_CLEANUP_H_
|
||||
#define ABSL_CLEANUP_CLEANUP_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/cleanup/internal/cleanup.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
template <typename Arg, typename Callback = void()>
|
||||
class ABSL_MUST_USE_RESULT Cleanup final {
|
||||
static_assert(cleanup_internal::WasDeduced<Arg>(),
|
||||
"Explicit template parameters are not supported.");
|
||||
|
||||
static_assert(cleanup_internal::ReturnsVoid<Callback>(),
|
||||
"Callbacks that return values are not supported.");
|
||||
|
||||
public:
|
||||
Cleanup(Callback callback) : storage_(std::move(callback)) {} // NOLINT
|
||||
|
||||
Cleanup(Cleanup&& other) = default;
|
||||
|
||||
void Cancel() && {
|
||||
ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
|
||||
storage_.DestroyCallback();
|
||||
}
|
||||
|
||||
void Invoke() && {
|
||||
ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
|
||||
storage_.InvokeCallback();
|
||||
storage_.DestroyCallback();
|
||||
}
|
||||
|
||||
~Cleanup() {
|
||||
if (storage_.IsCallbackEngaged()) {
|
||||
storage_.InvokeCallback();
|
||||
storage_.DestroyCallback();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
cleanup_internal::Storage<Callback> storage_;
|
||||
};
|
||||
|
||||
// `absl::Cleanup c = /* callback */;`
|
||||
//
|
||||
// C++17 type deduction API for creating an instance of `absl::Cleanup`
|
||||
#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
|
||||
template <typename Callback>
|
||||
Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;
|
||||
#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
|
||||
|
||||
// `auto c = absl::MakeCleanup(/* callback */);`
|
||||
//
|
||||
// C++11 type deduction API for creating an instance of `absl::Cleanup`
|
||||
template <typename... Args, typename Callback>
|
||||
absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) {
|
||||
static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(),
|
||||
"Explicit template parameters are not supported.");
|
||||
|
||||
static_assert(cleanup_internal::ReturnsVoid<Callback>(),
|
||||
"Callbacks that return values are not supported.");
|
||||
|
||||
return {std::move(callback)};
|
||||
}
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_CLEANUP_CLEANUP_H_
|
||||
311
third_party/abseil-cpp/absl/cleanup/cleanup_test.cc
vendored
Normal file
311
third_party/abseil-cpp/absl/cleanup/cleanup_test.cc
vendored
Normal file
@ -0,0 +1,311 @@
|
||||
// Copyright 2021 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/cleanup/cleanup.h"
|
||||
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/utility/utility.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using Tag = absl::cleanup_internal::Tag;
|
||||
|
||||
template <typename Type1, typename Type2>
|
||||
constexpr bool IsSame() {
|
||||
return (std::is_same<Type1, Type2>::value);
|
||||
}
|
||||
|
||||
struct IdentityFactory {
|
||||
template <typename Callback>
|
||||
static Callback AsCallback(Callback callback) {
|
||||
return Callback(std::move(callback));
|
||||
}
|
||||
};
|
||||
|
||||
// `FunctorClass` is a type used for testing `absl::Cleanup`. It is intended to
|
||||
// represent users that make their own move-only callback types outside of
|
||||
// `std::function` and lambda literals.
|
||||
class FunctorClass {
|
||||
using Callback = std::function<void()>;
|
||||
|
||||
public:
|
||||
explicit FunctorClass(Callback callback) : callback_(std::move(callback)) {}
|
||||
|
||||
FunctorClass(FunctorClass&& other)
|
||||
: callback_(absl::exchange(other.callback_, Callback())) {}
|
||||
|
||||
FunctorClass(const FunctorClass&) = delete;
|
||||
|
||||
FunctorClass& operator=(const FunctorClass&) = delete;
|
||||
|
||||
FunctorClass& operator=(FunctorClass&&) = delete;
|
||||
|
||||
void operator()() const& = delete;
|
||||
|
||||
void operator()() && {
|
||||
ASSERT_TRUE(callback_);
|
||||
callback_();
|
||||
callback_ = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Callback callback_;
|
||||
};
|
||||
|
||||
struct FunctorClassFactory {
|
||||
template <typename Callback>
|
||||
static FunctorClass AsCallback(Callback callback) {
|
||||
return FunctorClass(std::move(callback));
|
||||
}
|
||||
};
|
||||
|
||||
struct StdFunctionFactory {
|
||||
template <typename Callback>
|
||||
static std::function<void()> AsCallback(Callback callback) {
|
||||
return std::function<void()>(std::move(callback));
|
||||
}
|
||||
};
|
||||
|
||||
using CleanupTestParams =
|
||||
::testing::Types<IdentityFactory, FunctorClassFactory, StdFunctionFactory>;
|
||||
template <typename>
|
||||
struct CleanupTest : public ::testing::Test {};
|
||||
TYPED_TEST_SUITE(CleanupTest, CleanupTestParams);
|
||||
|
||||
bool fn_ptr_called = false;
|
||||
void FnPtrFunction() { fn_ptr_called = true; }
|
||||
|
||||
TYPED_TEST(CleanupTest, FactoryProducesCorrectType) {
|
||||
{
|
||||
auto callback = TypeParam::AsCallback([] {});
|
||||
auto cleanup = absl::MakeCleanup(std::move(callback));
|
||||
|
||||
static_assert(
|
||||
IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
|
||||
"");
|
||||
}
|
||||
|
||||
{
|
||||
auto cleanup = absl::MakeCleanup(&FnPtrFunction);
|
||||
|
||||
static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
|
||||
"");
|
||||
}
|
||||
|
||||
{
|
||||
auto cleanup = absl::MakeCleanup(FnPtrFunction);
|
||||
|
||||
static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
|
||||
"");
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
|
||||
TYPED_TEST(CleanupTest, CTADProducesCorrectType) {
|
||||
{
|
||||
auto callback = TypeParam::AsCallback([] {});
|
||||
absl::Cleanup cleanup = std::move(callback);
|
||||
|
||||
static_assert(
|
||||
IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
|
||||
"");
|
||||
}
|
||||
|
||||
{
|
||||
absl::Cleanup cleanup = &FnPtrFunction;
|
||||
|
||||
static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
|
||||
"");
|
||||
}
|
||||
|
||||
{
|
||||
absl::Cleanup cleanup = FnPtrFunction;
|
||||
|
||||
static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
|
||||
"");
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST(CleanupTest, FactoryAndCTADProduceSameType) {
|
||||
{
|
||||
auto callback = IdentityFactory::AsCallback([] {});
|
||||
auto factory_cleanup = absl::MakeCleanup(callback);
|
||||
absl::Cleanup deduction_cleanup = callback;
|
||||
|
||||
static_assert(
|
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
|
||||
}
|
||||
|
||||
{
|
||||
auto factory_cleanup =
|
||||
absl::MakeCleanup(FunctorClassFactory::AsCallback([] {}));
|
||||
absl::Cleanup deduction_cleanup = FunctorClassFactory::AsCallback([] {});
|
||||
|
||||
static_assert(
|
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
|
||||
}
|
||||
|
||||
{
|
||||
auto factory_cleanup =
|
||||
absl::MakeCleanup(StdFunctionFactory::AsCallback([] {}));
|
||||
absl::Cleanup deduction_cleanup = StdFunctionFactory::AsCallback([] {});
|
||||
|
||||
static_assert(
|
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
|
||||
}
|
||||
|
||||
{
|
||||
auto factory_cleanup = absl::MakeCleanup(&FnPtrFunction);
|
||||
absl::Cleanup deduction_cleanup = &FnPtrFunction;
|
||||
|
||||
static_assert(
|
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
|
||||
}
|
||||
|
||||
{
|
||||
auto factory_cleanup = absl::MakeCleanup(FnPtrFunction);
|
||||
absl::Cleanup deduction_cleanup = FnPtrFunction;
|
||||
|
||||
static_assert(
|
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
|
||||
}
|
||||
}
|
||||
#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
|
||||
|
||||
TYPED_TEST(CleanupTest, BasicUsage) {
|
||||
bool called = false;
|
||||
|
||||
{
|
||||
auto cleanup =
|
||||
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
|
||||
EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
|
||||
}
|
||||
|
||||
EXPECT_TRUE(called); // Destructor should invoke the callback
|
||||
}
|
||||
|
||||
TYPED_TEST(CleanupTest, BasicUsageWithFunctionPointer) {
|
||||
fn_ptr_called = false;
|
||||
|
||||
{
|
||||
auto cleanup = absl::MakeCleanup(TypeParam::AsCallback(&FnPtrFunction));
|
||||
EXPECT_FALSE(fn_ptr_called); // Constructor shouldn't invoke the callback
|
||||
}
|
||||
|
||||
EXPECT_TRUE(fn_ptr_called); // Destructor should invoke the callback
|
||||
}
|
||||
|
||||
TYPED_TEST(CleanupTest, Cancel) {
|
||||
bool called = false;
|
||||
|
||||
{
|
||||
auto cleanup =
|
||||
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
|
||||
EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
|
||||
|
||||
std::move(cleanup).Cancel();
|
||||
EXPECT_FALSE(called); // Cancel shouldn't invoke the callback
|
||||
}
|
||||
|
||||
EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
|
||||
}
|
||||
|
||||
TYPED_TEST(CleanupTest, Invoke) {
|
||||
bool called = false;
|
||||
|
||||
{
|
||||
auto cleanup =
|
||||
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
|
||||
EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
|
||||
|
||||
std::move(cleanup).Invoke();
|
||||
EXPECT_TRUE(called); // Invoke should invoke the callback
|
||||
|
||||
called = false; // Reset tracker before destructor runs
|
||||
}
|
||||
|
||||
EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
|
||||
}
|
||||
|
||||
TYPED_TEST(CleanupTest, Move) {
|
||||
bool called = false;
|
||||
|
||||
{
|
||||
auto moved_from_cleanup =
|
||||
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
|
||||
EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
|
||||
|
||||
{
|
||||
auto moved_to_cleanup = std::move(moved_from_cleanup);
|
||||
EXPECT_FALSE(called); // Move shouldn't invoke the callback
|
||||
}
|
||||
|
||||
EXPECT_TRUE(called); // Destructor should invoke the callback
|
||||
|
||||
called = false; // Reset tracker before destructor runs
|
||||
}
|
||||
|
||||
EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
|
||||
}
|
||||
|
||||
int DestructionCount = 0;
|
||||
|
||||
struct DestructionCounter {
|
||||
void operator()() {}
|
||||
|
||||
~DestructionCounter() { ++DestructionCount; }
|
||||
};
|
||||
|
||||
TYPED_TEST(CleanupTest, DestructorDestroys) {
|
||||
{
|
||||
auto cleanup =
|
||||
absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
|
||||
DestructionCount = 0;
|
||||
}
|
||||
|
||||
EXPECT_EQ(DestructionCount, 1); // Engaged cleanup destroys
|
||||
}
|
||||
|
||||
TYPED_TEST(CleanupTest, CancelDestroys) {
|
||||
{
|
||||
auto cleanup =
|
||||
absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
|
||||
DestructionCount = 0;
|
||||
|
||||
std::move(cleanup).Cancel();
|
||||
EXPECT_EQ(DestructionCount, 1); // Cancel destroys
|
||||
}
|
||||
|
||||
EXPECT_EQ(DestructionCount, 1); // Canceled cleanup does not double destroy
|
||||
}
|
||||
|
||||
TYPED_TEST(CleanupTest, InvokeDestroys) {
|
||||
{
|
||||
auto cleanup =
|
||||
absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
|
||||
DestructionCount = 0;
|
||||
|
||||
std::move(cleanup).Invoke();
|
||||
EXPECT_EQ(DestructionCount, 1); // Invoke destroys
|
||||
}
|
||||
|
||||
EXPECT_EQ(DestructionCount, 1); // Invoked cleanup does not double destroy
|
||||
}
|
||||
|
||||
} // namespace
|
||||
100
third_party/abseil-cpp/absl/cleanup/internal/cleanup.h
vendored
Normal file
100
third_party/abseil-cpp/absl/cleanup/internal/cleanup.h
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright 2021 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_CLEANUP_INTERNAL_CLEANUP_H_
|
||||
#define ABSL_CLEANUP_INTERNAL_CLEANUP_H_
|
||||
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/internal/invoke.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/utility/utility.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
namespace cleanup_internal {
|
||||
|
||||
struct Tag {};
|
||||
|
||||
template <typename Arg, typename... Args>
|
||||
constexpr bool WasDeduced() {
|
||||
return (std::is_same<cleanup_internal::Tag, Arg>::value) &&
|
||||
(sizeof...(Args) == 0);
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
constexpr bool ReturnsVoid() {
|
||||
return (std::is_same<base_internal::invoke_result_t<Callback>, void>::value);
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
class Storage {
|
||||
public:
|
||||
Storage() = delete;
|
||||
|
||||
explicit Storage(Callback callback) {
|
||||
// Placement-new into a character buffer is used for eager destruction when
|
||||
// the cleanup is invoked or cancelled. To ensure this optimizes well, the
|
||||
// behavior is implemented locally instead of using an absl::optional.
|
||||
::new (GetCallbackBuffer()) Callback(std::move(callback));
|
||||
is_callback_engaged_ = true;
|
||||
}
|
||||
|
||||
Storage(Storage&& other) {
|
||||
ABSL_HARDENING_ASSERT(other.IsCallbackEngaged());
|
||||
|
||||
::new (GetCallbackBuffer()) Callback(std::move(other.GetCallback()));
|
||||
is_callback_engaged_ = true;
|
||||
|
||||
other.DestroyCallback();
|
||||
}
|
||||
|
||||
Storage(const Storage& other) = delete;
|
||||
|
||||
Storage& operator=(Storage&& other) = delete;
|
||||
|
||||
Storage& operator=(const Storage& other) = delete;
|
||||
|
||||
void* GetCallbackBuffer() { return static_cast<void*>(+callback_buffer_); }
|
||||
|
||||
Callback& GetCallback() {
|
||||
return *reinterpret_cast<Callback*>(GetCallbackBuffer());
|
||||
}
|
||||
|
||||
bool IsCallbackEngaged() const { return is_callback_engaged_; }
|
||||
|
||||
void DestroyCallback() {
|
||||
is_callback_engaged_ = false;
|
||||
GetCallback().~Callback();
|
||||
}
|
||||
|
||||
void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS {
|
||||
std::move(GetCallback())();
|
||||
}
|
||||
|
||||
private:
|
||||
bool is_callback_engaged_;
|
||||
alignas(Callback) char callback_buffer_[sizeof(Callback)];
|
||||
};
|
||||
|
||||
} // namespace cleanup_internal
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_CLEANUP_INTERNAL_CLEANUP_H_
|
||||
@ -1,38 +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.
|
||||
|
||||
"""Creates config_setting that allows selecting based on 'compiler' value."""
|
||||
|
||||
def create_llvm_config(name, visibility):
|
||||
# The "do_not_use_tools_cpp_compiler_present" attribute exists to
|
||||
# distinguish between older versions of Bazel that do not support
|
||||
# "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
|
||||
# In the future, the only way to select on the compiler will be through
|
||||
# flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can
|
||||
# be removed.
|
||||
if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"):
|
||||
native.config_setting(
|
||||
name = name,
|
||||
flag_values = {
|
||||
"@bazel_tools//tools/cpp:compiler": "llvm",
|
||||
},
|
||||
visibility = visibility,
|
||||
)
|
||||
else:
|
||||
native.config_setting(
|
||||
name = name,
|
||||
values = {"compiler": "llvm"},
|
||||
visibility = visibility,
|
||||
)
|
||||
100
third_party/abseil-cpp/absl/container/BUILD.bazel
vendored
100
third_party/abseil-cpp/absl/container/BUILD.bazel
vendored
@ -14,7 +14,6 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
|
||||
load(
|
||||
"//absl:copts/configure_copts.bzl",
|
||||
"ABSL_DEFAULT_COPTS",
|
||||
@ -24,7 +23,7 @@ load(
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "compressed_tuple",
|
||||
@ -60,6 +59,7 @@ cc_library(
|
||||
deps = [
|
||||
":compressed_tuple",
|
||||
"//absl/algorithm",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:dynamic_annotations",
|
||||
"//absl/base:throw_delegate",
|
||||
@ -73,7 +73,9 @@ cc_test(
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":counting_allocator",
|
||||
":fixed_array",
|
||||
"//absl/base:config",
|
||||
"//absl/base:exception_testing",
|
||||
"//absl/hash:hash_testing",
|
||||
"//absl/memory",
|
||||
@ -153,6 +155,7 @@ cc_test(
|
||||
":counting_allocator",
|
||||
":inlined_vector",
|
||||
":test_instance_tracker",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:exception_testing",
|
||||
"//absl/base:raw_logging_internal",
|
||||
@ -255,6 +258,7 @@ cc_test(
|
||||
":unordered_map_lookup_test",
|
||||
":unordered_map_members_test",
|
||||
":unordered_map_modifiers_test",
|
||||
"//absl/base:raw_logging_internal",
|
||||
"//absl/types:any",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
@ -288,6 +292,7 @@ cc_test(
|
||||
":unordered_set_lookup_test",
|
||||
":unordered_set_members_test",
|
||||
":unordered_set_modifiers_test",
|
||||
"//absl/base:raw_logging_internal",
|
||||
"//absl/memory",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
@ -363,7 +368,9 @@ cc_library(
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
"//absl/base:config",
|
||||
"//absl/memory",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/utility",
|
||||
],
|
||||
)
|
||||
@ -376,6 +383,7 @@ cc_test(
|
||||
tags = NOTEST_TAGS_NONMOBILE,
|
||||
deps = [
|
||||
":container_memory",
|
||||
":test_instance_tracker",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
@ -390,6 +398,7 @@ cc_library(
|
||||
"//absl/base:config",
|
||||
"//absl/hash",
|
||||
"//absl/strings",
|
||||
"//absl/strings:cord",
|
||||
],
|
||||
)
|
||||
|
||||
@ -402,7 +411,10 @@ cc_test(
|
||||
deps = [
|
||||
":hash_function_defaults",
|
||||
"//absl/hash",
|
||||
"//absl/random",
|
||||
"//absl/strings",
|
||||
"//absl/strings:cord",
|
||||
"//absl/strings:cord_test_helpers",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
@ -497,9 +509,10 @@ cc_library(
|
||||
":have_sse",
|
||||
"//absl/base",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:exponential_biased",
|
||||
"//absl/debugging:stacktrace",
|
||||
"//absl/memory",
|
||||
"//absl/profiling:exponential_biased",
|
||||
"//absl/profiling:sample_recorder",
|
||||
"//absl/synchronization",
|
||||
"//absl/utility",
|
||||
],
|
||||
@ -513,6 +526,7 @@ cc_test(
|
||||
":hashtablez_sampler",
|
||||
":have_sse",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/profiling:sample_recorder",
|
||||
"//absl/synchronization",
|
||||
"//absl/synchronization:thread_pool",
|
||||
"//absl/time",
|
||||
@ -585,13 +599,12 @@ cc_library(
|
||||
":hashtable_debug_hooks",
|
||||
":hashtablez_sampler",
|
||||
":have_sse",
|
||||
":layout",
|
||||
"//absl/base:bits",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:endian",
|
||||
"//absl/memory",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/numeric:bits",
|
||||
"//absl/utility",
|
||||
],
|
||||
)
|
||||
@ -609,6 +622,7 @@ cc_test(
|
||||
":hashtable_debug",
|
||||
":raw_hash_set",
|
||||
"//absl/base",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:raw_logging_internal",
|
||||
"//absl/strings",
|
||||
@ -616,6 +630,45 @@ cc_test(
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "raw_hash_set_benchmark",
|
||||
testonly = 1,
|
||||
srcs = ["internal/raw_hash_set_benchmark.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
tags = ["benchmark"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":hash_function_defaults",
|
||||
":raw_hash_set",
|
||||
"//absl/base:raw_logging_internal",
|
||||
"//absl/strings:str_format",
|
||||
"@com_github_google_benchmark//:benchmark_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "raw_hash_set_probe_benchmark",
|
||||
testonly = 1,
|
||||
srcs = ["internal/raw_hash_set_probe_benchmark.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = select({
|
||||
"//conditions:default": [],
|
||||
}) + ABSL_DEFAULT_LINKOPTS,
|
||||
tags = ["benchmark"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":flat_hash_map",
|
||||
":hash_function_defaults",
|
||||
":hashtable_debug",
|
||||
":raw_hash_set",
|
||||
"//absl/random",
|
||||
"//absl/random:distributions",
|
||||
"//absl/strings",
|
||||
"//absl/strings:str_format",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "raw_hash_set_allocator_test",
|
||||
size = "small",
|
||||
@ -636,6 +689,7 @@ cc_library(
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/strings",
|
||||
@ -654,6 +708,7 @@ cc_test(
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":layout",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:raw_logging_internal",
|
||||
"//absl/types:span",
|
||||
@ -661,6 +716,22 @@ cc_test(
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "layout_benchmark",
|
||||
testonly = 1,
|
||||
srcs = ["internal/layout_benchmark.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
tags = ["benchmark"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":layout",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:raw_logging_internal",
|
||||
"@com_github_google_benchmark//:benchmark_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "tracked",
|
||||
testonly = 1,
|
||||
@ -805,6 +876,22 @@ cc_test(
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "sample_element_size_test",
|
||||
srcs = ["sample_element_size_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
tags = NOTEST_TAGS_NONMOBILE,
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":flat_hash_map",
|
||||
":flat_hash_set",
|
||||
":node_hash_map",
|
||||
":node_hash_set",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "btree",
|
||||
srcs = [
|
||||
@ -828,6 +915,7 @@ cc_library(
|
||||
"//absl/memory",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/strings",
|
||||
"//absl/strings:cord",
|
||||
"//absl/types:compare",
|
||||
"//absl/utility",
|
||||
],
|
||||
@ -844,6 +932,7 @@ cc_library(
|
||||
":btree",
|
||||
":flat_hash_set",
|
||||
"//absl/strings",
|
||||
"//absl/strings:cord",
|
||||
"//absl/time",
|
||||
],
|
||||
)
|
||||
@ -895,6 +984,7 @@ cc_binary(
|
||||
"//absl/flags:flag",
|
||||
"//absl/hash",
|
||||
"//absl/memory",
|
||||
"//absl/strings:cord",
|
||||
"//absl/strings:str_format",
|
||||
"//absl/time",
|
||||
"@com_github_google_benchmark//:benchmark_main",
|
||||
|
||||
104
third_party/abseil-cpp/absl/container/CMakeLists.txt
vendored
104
third_party/abseil-cpp/absl/container/CMakeLists.txt
vendored
@ -14,15 +14,6 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# This is deprecated and will be removed in the future. It also doesn't do
|
||||
# anything anyways. Prefer to use the library associated with the API you are
|
||||
# using.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
container
|
||||
PUBLIC
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
btree
|
||||
@ -40,6 +31,7 @@ absl_cc_library(
|
||||
absl::compare
|
||||
absl::compressed_tuple
|
||||
absl::container_memory
|
||||
absl::cord
|
||||
absl::core_headers
|
||||
absl::layout
|
||||
absl::memory
|
||||
@ -60,6 +52,7 @@ absl_cc_library(
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::btree
|
||||
absl::cord
|
||||
absl::flat_hash_set
|
||||
absl::strings
|
||||
absl::time
|
||||
@ -87,7 +80,7 @@ absl_cc_test(
|
||||
absl::strings
|
||||
absl::test_instance_tracker
|
||||
absl::type_traits
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -116,7 +109,7 @@ absl_cc_test(
|
||||
absl::optional
|
||||
absl::test_instance_tracker
|
||||
absl::utility
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -129,6 +122,7 @@ absl_cc_library(
|
||||
DEPS
|
||||
absl::compressed_tuple
|
||||
absl::algorithm
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::dynamic_annotations
|
||||
absl::throw_delegate
|
||||
@ -145,10 +139,12 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::fixed_array
|
||||
absl::counting_allocator
|
||||
absl::config
|
||||
absl::exception_testing
|
||||
absl::hash_testing
|
||||
absl::memory
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -162,7 +158,7 @@ absl_cc_test(
|
||||
absl::fixed_array
|
||||
absl::config
|
||||
absl::exception_safety_testing
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -219,13 +215,14 @@ absl_cc_test(
|
||||
absl::counting_allocator
|
||||
absl::inlined_vector
|
||||
absl::test_instance_tracker
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::exception_testing
|
||||
absl::hash_testing
|
||||
absl::memory
|
||||
absl::raw_logging_internal
|
||||
absl::strings
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -239,7 +236,7 @@ absl_cc_test(
|
||||
absl::inlined_vector
|
||||
absl::config
|
||||
absl::exception_safety_testing
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -265,7 +262,7 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::test_instance_tracker
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -299,7 +296,8 @@ absl_cc_test(
|
||||
absl::unordered_map_members_test
|
||||
absl::unordered_map_modifiers_test
|
||||
absl::any
|
||||
gmock_main
|
||||
absl::raw_logging_internal
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -335,8 +333,9 @@ absl_cc_test(
|
||||
absl::unordered_set_members_test
|
||||
absl::unordered_set_modifiers_test
|
||||
absl::memory
|
||||
absl::raw_logging_internal
|
||||
absl::strings
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -371,7 +370,7 @@ absl_cc_test(
|
||||
absl::unordered_map_lookup_test
|
||||
absl::unordered_map_members_test
|
||||
absl::unordered_map_modifiers_test
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -405,7 +404,7 @@ absl_cc_test(
|
||||
absl::unordered_set_lookup_test
|
||||
absl::unordered_set_members_test
|
||||
absl::unordered_set_modifiers_test
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -416,7 +415,9 @@ absl_cc_library(
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::memory
|
||||
absl::type_traits
|
||||
absl::utility
|
||||
PUBLIC
|
||||
)
|
||||
@ -431,7 +432,8 @@ absl_cc_test(
|
||||
DEPS
|
||||
absl::container_memory
|
||||
absl::strings
|
||||
gmock_main
|
||||
absl::test_instance_tracker
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -443,6 +445,7 @@ absl_cc_library(
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::cord
|
||||
absl::hash
|
||||
absl::strings
|
||||
PUBLIC
|
||||
@ -456,10 +459,13 @@ absl_cc_test(
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::cord
|
||||
absl::cord_test_helpers
|
||||
absl::hash_function_defaults
|
||||
absl::hash
|
||||
absl::random_random
|
||||
absl::strings
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -501,7 +507,7 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::hash_policy_testing
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -525,7 +531,7 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::hash_policy_traits
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -542,6 +548,7 @@ absl_cc_library(
|
||||
absl::base
|
||||
absl::exponential_biased
|
||||
absl::have_sse
|
||||
absl::sample_recorder
|
||||
absl::synchronization
|
||||
)
|
||||
|
||||
@ -555,7 +562,7 @@ absl_cc_test(
|
||||
DEPS
|
||||
absl::hashtablez_sampler
|
||||
absl::have_sse
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -612,7 +619,7 @@ absl_cc_test(
|
||||
DEPS
|
||||
absl::hash_policy_traits
|
||||
absl::node_hash_policy
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -660,7 +667,6 @@ absl_cc_library(
|
||||
absl::hash_policy_traits
|
||||
absl::hashtable_debug_hooks
|
||||
absl::have_sse
|
||||
absl::layout
|
||||
absl::memory
|
||||
absl::meta
|
||||
absl::optional
|
||||
@ -683,10 +689,11 @@ absl_cc_test(
|
||||
absl::hashtable_debug
|
||||
absl::raw_hash_set
|
||||
absl::base
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::raw_logging_internal
|
||||
absl::strings
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -700,7 +707,7 @@ absl_cc_test(
|
||||
absl::raw_hash_set
|
||||
absl::tracked
|
||||
absl::core_headers
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -711,6 +718,7 @@ absl_cc_library(
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::meta
|
||||
absl::strings
|
||||
@ -728,10 +736,11 @@ absl_cc_test(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::layout
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::raw_logging_internal
|
||||
absl::span
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
@ -756,7 +765,7 @@ absl_cc_library(
|
||||
DEPS
|
||||
absl::hash_generator_testing
|
||||
absl::hash_policy_testing
|
||||
gmock
|
||||
GTest::gmock
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -770,7 +779,7 @@ absl_cc_library(
|
||||
DEPS
|
||||
absl::hash_generator_testing
|
||||
absl::hash_policy_testing
|
||||
gmock
|
||||
GTest::gmock
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -783,7 +792,7 @@ absl_cc_library(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::type_traits
|
||||
gmock
|
||||
GTest::gmock
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -797,7 +806,7 @@ absl_cc_library(
|
||||
DEPS
|
||||
absl::hash_generator_testing
|
||||
absl::hash_policy_testing
|
||||
gmock
|
||||
GTest::gmock
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -811,7 +820,7 @@ absl_cc_library(
|
||||
DEPS
|
||||
absl::hash_generator_testing
|
||||
absl::hash_policy_testing
|
||||
gmock
|
||||
GTest::gmock
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -825,7 +834,7 @@ absl_cc_library(
|
||||
DEPS
|
||||
absl::hash_generator_testing
|
||||
absl::hash_policy_testing
|
||||
gmock
|
||||
GTest::gmock
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -838,7 +847,7 @@ absl_cc_library(
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::type_traits
|
||||
gmock
|
||||
GTest::gmock
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -852,7 +861,7 @@ absl_cc_library(
|
||||
DEPS
|
||||
absl::hash_generator_testing
|
||||
absl::hash_policy_testing
|
||||
gmock
|
||||
GTest::gmock
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
@ -868,7 +877,7 @@ absl_cc_test(
|
||||
absl::unordered_set_lookup_test
|
||||
absl::unordered_set_members_test
|
||||
absl::unordered_set_modifiers_test
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
@ -883,5 +892,20 @@ absl_cc_test(
|
||||
absl::unordered_map_lookup_test
|
||||
absl::unordered_map_members_test
|
||||
absl::unordered_map_modifiers_test
|
||||
gmock_main
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
sample_element_size_test
|
||||
SRCS
|
||||
"sample_element_size_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::flat_hash_map
|
||||
absl::flat_hash_set
|
||||
absl::node_hash_map
|
||||
absl::node_hash_set
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/container/btree_map.h"
|
||||
#include "absl/container/btree_set.h"
|
||||
@ -36,9 +37,9 @@
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/hash/hash.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/cord.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
@ -100,36 +101,24 @@ void BM_InsertSorted(benchmark::State& state) {
|
||||
BM_InsertImpl<T>(state, true);
|
||||
}
|
||||
|
||||
// container::insert sometimes returns a pair<iterator, bool> and sometimes
|
||||
// returns an iterator (for multi- containers).
|
||||
template <typename Iter>
|
||||
Iter GetIterFromInsert(const std::pair<Iter, bool>& pair) {
|
||||
return pair.first;
|
||||
}
|
||||
template <typename Iter>
|
||||
Iter GetIterFromInsert(const Iter iter) {
|
||||
return iter;
|
||||
}
|
||||
|
||||
// Benchmark insertion of values into a container at the end.
|
||||
// Benchmark inserting the first few elements in a container. In b-tree, this is
|
||||
// when the root node grows.
|
||||
template <typename T>
|
||||
void BM_InsertEnd(benchmark::State& state) {
|
||||
void BM_InsertSmall(benchmark::State& state) {
|
||||
using V = typename remove_pair_const<typename T::value_type>::type;
|
||||
typename KeyOfValue<typename T::key_type, V>::type key_of_value;
|
||||
|
||||
const int kSize = 8;
|
||||
std::vector<V> values = GenerateValues<V>(kSize);
|
||||
T container;
|
||||
const int kSize = 10000;
|
||||
for (int i = 0; i < kSize; ++i) {
|
||||
container.insert(Generator<V>(kSize)(i));
|
||||
}
|
||||
V v = Generator<V>(kSize)(kSize - 1);
|
||||
typename T::key_type k = key_of_value(v);
|
||||
|
||||
auto it = container.find(k);
|
||||
while (state.KeepRunning()) {
|
||||
// Repeatedly removing then adding v.
|
||||
container.erase(it);
|
||||
it = GetIterFromInsert(container.insert(v));
|
||||
while (state.KeepRunningBatch(kSize)) {
|
||||
for (int i = 0; i < kSize; ++i) {
|
||||
benchmark::DoNotOptimize(container.insert(values[i]));
|
||||
}
|
||||
state.PauseTiming();
|
||||
// Do not measure the time it takes to clear the container.
|
||||
container.clear();
|
||||
state.ResumeTiming();
|
||||
}
|
||||
}
|
||||
|
||||
@ -438,6 +427,7 @@ using StdString = std::string;
|
||||
STL_ORDERED_TYPES(int32_t);
|
||||
STL_ORDERED_TYPES(int64_t);
|
||||
STL_ORDERED_TYPES(StdString);
|
||||
STL_ORDERED_TYPES(Cord);
|
||||
STL_ORDERED_TYPES(Time);
|
||||
|
||||
#define STL_UNORDERED_TYPES(value) \
|
||||
@ -458,6 +448,8 @@ STL_ORDERED_TYPES(Time);
|
||||
using stl_unordered_multimap_##value = \
|
||||
std::unordered_multimap<value, intptr_t, hash>
|
||||
|
||||
STL_UNORDERED_TYPES_CUSTOM_HASH(Cord, absl::Hash<absl::Cord>);
|
||||
|
||||
STL_UNORDERED_TYPES(int32_t);
|
||||
STL_UNORDERED_TYPES(int64_t);
|
||||
STL_UNORDERED_TYPES(StdString);
|
||||
@ -478,6 +470,7 @@ STL_UNORDERED_TYPES_CUSTOM_HASH(Time, absl::Hash<absl::Time>);
|
||||
BTREE_TYPES(int32_t);
|
||||
BTREE_TYPES(int64_t);
|
||||
BTREE_TYPES(StdString);
|
||||
BTREE_TYPES(Cord);
|
||||
BTREE_TYPES(Time);
|
||||
|
||||
#define MY_BENCHMARK4(type, func) \
|
||||
@ -487,7 +480,7 @@ BTREE_TYPES(Time);
|
||||
#define MY_BENCHMARK3(type) \
|
||||
MY_BENCHMARK4(type, Insert); \
|
||||
MY_BENCHMARK4(type, InsertSorted); \
|
||||
MY_BENCHMARK4(type, InsertEnd); \
|
||||
MY_BENCHMARK4(type, InsertSmall); \
|
||||
MY_BENCHMARK4(type, Lookup); \
|
||||
MY_BENCHMARK4(type, FullLookup); \
|
||||
MY_BENCHMARK4(type, Delete); \
|
||||
@ -526,6 +519,7 @@ BTREE_TYPES(Time);
|
||||
MY_BENCHMARK(int32_t);
|
||||
MY_BENCHMARK(int64_t);
|
||||
MY_BENCHMARK(StdString);
|
||||
MY_BENCHMARK(Cord);
|
||||
MY_BENCHMARK(Time);
|
||||
|
||||
// Define a type whose size and cost of moving are independently customizable.
|
||||
@ -538,19 +532,19 @@ struct BigType {
|
||||
BigType() : BigType(0) {}
|
||||
explicit BigType(int x) { std::iota(values.begin(), values.end(), x); }
|
||||
|
||||
void Copy(const BigType& x) {
|
||||
for (int i = 0; i < Size && i < Copies; ++i) values[i] = x.values[i];
|
||||
void Copy(const BigType& other) {
|
||||
for (int i = 0; i < Size && i < Copies; ++i) values[i] = other.values[i];
|
||||
// If Copies > Size, do extra copies.
|
||||
for (int i = Size, idx = 0; i < Copies; ++i) {
|
||||
int64_t tmp = x.values[idx];
|
||||
int64_t tmp = other.values[idx];
|
||||
benchmark::DoNotOptimize(tmp);
|
||||
idx = idx + 1 == Size ? 0 : idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
BigType(const BigType& x) { Copy(x); }
|
||||
BigType& operator=(const BigType& x) {
|
||||
Copy(x);
|
||||
BigType(const BigType& other) { Copy(other); }
|
||||
BigType& operator=(const BigType& other) {
|
||||
Copy(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -641,14 +635,14 @@ struct BigTypePtr {
|
||||
explicit BigTypePtr(int x) {
|
||||
ptr = absl::make_unique<BigType<Size, Size>>(x);
|
||||
}
|
||||
BigTypePtr(const BigTypePtr& x) {
|
||||
ptr = absl::make_unique<BigType<Size, Size>>(*x.ptr);
|
||||
BigTypePtr(const BigTypePtr& other) {
|
||||
ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr);
|
||||
}
|
||||
BigTypePtr(BigTypePtr&& x) noexcept = default;
|
||||
BigTypePtr& operator=(const BigTypePtr& x) {
|
||||
ptr = absl::make_unique<BigType<Size, Size>>(*x.ptr);
|
||||
BigTypePtr(BigTypePtr&& other) noexcept = default;
|
||||
BigTypePtr& operator=(const BigTypePtr& other) {
|
||||
ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr);
|
||||
}
|
||||
BigTypePtr& operator=(BigTypePtr&& x) noexcept = default;
|
||||
BigTypePtr& operator=(BigTypePtr&& other) noexcept = default;
|
||||
|
||||
bool operator<(const BigTypePtr& other) const { return *ptr < *other.ptr; }
|
||||
bool operator==(const BigTypePtr& other) const { return *ptr == *other.ptr; }
|
||||
|
||||
100
third_party/abseil-cpp/absl/container/btree_map.h
vendored
100
third_party/abseil-cpp/absl/container/btree_map.h
vendored
@ -185,7 +185,7 @@ class btree_map
|
||||
// template <typename K> size_type erase(const K& key):
|
||||
//
|
||||
// Erases the element with the matching key, if it exists, returning the
|
||||
// number of elements erased.
|
||||
// number of elements erased (0 or 1).
|
||||
using Base::erase;
|
||||
|
||||
// btree_map::insert()
|
||||
@ -318,13 +318,18 @@ class btree_map
|
||||
// Extracts the element at the indicated position and returns a node handle
|
||||
// owning that extracted data.
|
||||
//
|
||||
// template <typename K> node_type extract(const K& x):
|
||||
// template <typename K> node_type extract(const K& k):
|
||||
//
|
||||
// Extracts the element with the key matching the passed key value and
|
||||
// returns a node handle owning that extracted data. If the `btree_map`
|
||||
// does not contain an element with a matching key, this function returns an
|
||||
// empty node handle.
|
||||
//
|
||||
// NOTE: when compiled in an earlier version of C++ than C++17,
|
||||
// `node_type::key()` returns a const reference to the key instead of a
|
||||
// mutable reference. We cannot safely return a mutable reference without
|
||||
// std::launder (which is not available before C++17).
|
||||
//
|
||||
// NOTE: In this context, `node_type` refers to the C++17 concept of a
|
||||
// move-only type that owns and provides access to the elements in associative
|
||||
// containers (https://en.cppreference.com/w/cpp/container/node_handle).
|
||||
@ -361,8 +366,8 @@ class btree_map
|
||||
// Determines whether an element comparing equal to the given `key` exists
|
||||
// within the `btree_map`, returning `true` if so or `false` otherwise.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::contains;
|
||||
|
||||
// btree_map::count()
|
||||
@ -373,15 +378,14 @@ class btree_map
|
||||
// the `btree_map`. Note that this function will return either `1` or `0`
|
||||
// since duplicate elements are not allowed within a `btree_map`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::count;
|
||||
|
||||
// btree_map::equal_range()
|
||||
//
|
||||
// Returns a closed range [first, last], defined by a `std::pair` of two
|
||||
// iterators, containing all elements with the passed key in the
|
||||
// `btree_map`.
|
||||
// Returns a half-open range [first, last), defined by a `std::pair` of two
|
||||
// iterators, containing all elements with the passed key in the `btree_map`.
|
||||
using Base::equal_range;
|
||||
|
||||
// btree_map::find()
|
||||
@ -391,10 +395,34 @@ class btree_map
|
||||
//
|
||||
// Finds an element with the passed `key` within the `btree_map`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::find;
|
||||
|
||||
// btree_map::lower_bound()
|
||||
//
|
||||
// template <typename K> iterator lower_bound(const K& key):
|
||||
// template <typename K> const_iterator lower_bound(const K& key) const:
|
||||
//
|
||||
// Finds the first element with a key that is not less than `key` within the
|
||||
// `btree_map`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::lower_bound;
|
||||
|
||||
// btree_map::upper_bound()
|
||||
//
|
||||
// template <typename K> iterator upper_bound(const K& key):
|
||||
// template <typename K> const_iterator upper_bound(const K& key) const:
|
||||
//
|
||||
// Finds the first element with a key that is greater than `key` within the
|
||||
// `btree_map`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::upper_bound;
|
||||
|
||||
// btree_map::operator[]()
|
||||
//
|
||||
// Returns a reference to the value mapped to the passed key within the
|
||||
@ -645,13 +673,18 @@ class btree_multimap
|
||||
// Extracts the element at the indicated position and returns a node handle
|
||||
// owning that extracted data.
|
||||
//
|
||||
// template <typename K> node_type extract(const K& x):
|
||||
// template <typename K> node_type extract(const K& k):
|
||||
//
|
||||
// Extracts the element with the key matching the passed key value and
|
||||
// returns a node handle owning that extracted data. If the `btree_multimap`
|
||||
// does not contain an element with a matching key, this function returns an
|
||||
// empty node handle.
|
||||
//
|
||||
// NOTE: when compiled in an earlier version of C++ than C++17,
|
||||
// `node_type::key()` returns a const reference to the key instead of a
|
||||
// mutable reference. We cannot safely return a mutable reference without
|
||||
// std::launder (which is not available before C++17).
|
||||
//
|
||||
// NOTE: In this context, `node_type` refers to the C++17 concept of a
|
||||
// move-only type that owns and provides access to the elements in associative
|
||||
// containers (https://en.cppreference.com/w/cpp/container/node_handle).
|
||||
@ -660,9 +693,8 @@ class btree_multimap
|
||||
|
||||
// btree_multimap::merge()
|
||||
//
|
||||
// Extracts elements from a given `source` btree_multimap into this
|
||||
// `btree_multimap`. If the destination `btree_multimap` already contains an
|
||||
// element with an equivalent key, that element is not extracted.
|
||||
// Extracts all elements from a given `source` btree_multimap into this
|
||||
// `btree_multimap`.
|
||||
using Base::merge;
|
||||
|
||||
// btree_multimap::swap(btree_multimap& other)
|
||||
@ -682,8 +714,8 @@ class btree_multimap
|
||||
// Determines whether an element comparing equal to the given `key` exists
|
||||
// within the `btree_multimap`, returning `true` if so or `false` otherwise.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::contains;
|
||||
|
||||
// btree_multimap::count()
|
||||
@ -693,13 +725,13 @@ class btree_multimap
|
||||
// Returns the number of elements comparing equal to the given `key` within
|
||||
// the `btree_multimap`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::count;
|
||||
|
||||
// btree_multimap::equal_range()
|
||||
//
|
||||
// Returns a closed range [first, last], defined by a `std::pair` of two
|
||||
// Returns a half-open range [first, last), defined by a `std::pair` of two
|
||||
// iterators, containing all elements with the passed key in the
|
||||
// `btree_multimap`.
|
||||
using Base::equal_range;
|
||||
@ -711,10 +743,34 @@ class btree_multimap
|
||||
//
|
||||
// Finds an element with the passed `key` within the `btree_multimap`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::find;
|
||||
|
||||
// btree_multimap::lower_bound()
|
||||
//
|
||||
// template <typename K> iterator lower_bound(const K& key):
|
||||
// template <typename K> const_iterator lower_bound(const K& key) const:
|
||||
//
|
||||
// Finds the first element with a key that is not less than `key` within the
|
||||
// `btree_multimap`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::lower_bound;
|
||||
|
||||
// btree_multimap::upper_bound()
|
||||
//
|
||||
// template <typename K> iterator upper_bound(const K& key):
|
||||
// template <typename K> const_iterator upper_bound(const K& key) const:
|
||||
//
|
||||
// Finds the first element with a key that is greater than `key` within the
|
||||
// `btree_multimap`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the map has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::upper_bound;
|
||||
|
||||
// btree_multimap::get_allocator()
|
||||
//
|
||||
// Returns the allocator function associated with this `btree_multimap`.
|
||||
|
||||
@ -183,7 +183,7 @@ class btree_set
|
||||
// template <typename K> size_type erase(const K& key):
|
||||
//
|
||||
// Erases the element with the matching key, if it exists, returning the
|
||||
// number of elements erased.
|
||||
// number of elements erased (0 or 1).
|
||||
using Base::erase;
|
||||
|
||||
// btree_set::insert()
|
||||
@ -263,7 +263,7 @@ class btree_set
|
||||
// Extracts the element at the indicated position and returns a node handle
|
||||
// owning that extracted data.
|
||||
//
|
||||
// template <typename K> node_type extract(const K& x):
|
||||
// template <typename K> node_type extract(const K& k):
|
||||
//
|
||||
// Extracts the element with the key matching the passed key value and
|
||||
// returns a node handle owning that extracted data. If the `btree_set`
|
||||
@ -300,8 +300,8 @@ class btree_set
|
||||
// Determines whether an element comparing equal to the given `key` exists
|
||||
// within the `btree_set`, returning `true` if so or `false` otherwise.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::contains;
|
||||
|
||||
// btree_set::count()
|
||||
@ -312,8 +312,8 @@ class btree_set
|
||||
// the `btree_set`. Note that this function will return either `1` or `0`
|
||||
// since duplicate elements are not allowed within a `btree_set`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::count;
|
||||
|
||||
// btree_set::equal_range()
|
||||
@ -330,10 +330,32 @@ class btree_set
|
||||
//
|
||||
// Finds an element with the passed `key` within the `btree_set`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::find;
|
||||
|
||||
// btree_set::lower_bound()
|
||||
//
|
||||
// template <typename K> iterator lower_bound(const K& key):
|
||||
// template <typename K> const_iterator lower_bound(const K& key) const:
|
||||
//
|
||||
// Finds the first element that is not less than `key` within the `btree_set`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::lower_bound;
|
||||
|
||||
// btree_set::upper_bound()
|
||||
//
|
||||
// template <typename K> iterator upper_bound(const K& key):
|
||||
// template <typename K> const_iterator upper_bound(const K& key) const:
|
||||
//
|
||||
// Finds the first element that is greater than `key` within the `btree_set`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::upper_bound;
|
||||
|
||||
// btree_set::get_allocator()
|
||||
//
|
||||
// Returns the allocator function associated with this `btree_set`.
|
||||
@ -567,7 +589,7 @@ class btree_multiset
|
||||
// Extracts the element at the indicated position and returns a node handle
|
||||
// owning that extracted data.
|
||||
//
|
||||
// template <typename K> node_type extract(const K& x):
|
||||
// template <typename K> node_type extract(const K& k):
|
||||
//
|
||||
// Extracts the element with the key matching the passed key value and
|
||||
// returns a node handle owning that extracted data. If the `btree_multiset`
|
||||
@ -582,9 +604,8 @@ class btree_multiset
|
||||
|
||||
// btree_multiset::merge()
|
||||
//
|
||||
// Extracts elements from a given `source` btree_multiset into this
|
||||
// `btree_multiset`. If the destination `btree_multiset` already contains an
|
||||
// element with an equivalent key, that element is not extracted.
|
||||
// Extracts all elements from a given `source` btree_multiset into this
|
||||
// `btree_multiset`.
|
||||
using Base::merge;
|
||||
|
||||
// btree_multiset::swap(btree_multiset& other)
|
||||
@ -604,8 +625,8 @@ class btree_multiset
|
||||
// Determines whether an element comparing equal to the given `key` exists
|
||||
// within the `btree_multiset`, returning `true` if so or `false` otherwise.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::contains;
|
||||
|
||||
// btree_multiset::count()
|
||||
@ -615,8 +636,8 @@ class btree_multiset
|
||||
// Returns the number of elements comparing equal to the given `key` within
|
||||
// the `btree_multiset`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::count;
|
||||
|
||||
// btree_multiset::equal_range()
|
||||
@ -633,10 +654,34 @@ class btree_multiset
|
||||
//
|
||||
// Finds an element with the passed `key` within the `btree_multiset`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set is provided a
|
||||
// compatible heterogeneous comparator.
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::find;
|
||||
|
||||
// btree_multiset::lower_bound()
|
||||
//
|
||||
// template <typename K> iterator lower_bound(const K& key):
|
||||
// template <typename K> const_iterator lower_bound(const K& key) const:
|
||||
//
|
||||
// Finds the first element that is not less than `key` within the
|
||||
// `btree_multiset`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::lower_bound;
|
||||
|
||||
// btree_multiset::upper_bound()
|
||||
//
|
||||
// template <typename K> iterator upper_bound(const K& key):
|
||||
// template <typename K> const_iterator upper_bound(const K& key) const:
|
||||
//
|
||||
// Finds the first element that is greater than `key` within the
|
||||
// `btree_multiset`.
|
||||
//
|
||||
// Supports heterogeneous lookup, provided that the set has a compatible
|
||||
// heterogeneous comparator.
|
||||
using Base::upper_bound;
|
||||
|
||||
// btree_multiset::get_allocator()
|
||||
//
|
||||
// Returns the allocator function associated with this `btree_multiset`.
|
||||
|
||||
712
third_party/abseil-cpp/absl/container/btree_test.cc
vendored
712
third_party/abseil-cpp/absl/container/btree_test.cc
vendored
@ -15,6 +15,7 @@
|
||||
#include "absl/container/btree_test.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
@ -52,7 +53,9 @@ using ::absl::test_internal::MovableOnlyInstance;
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::ElementsAreArray;
|
||||
using ::testing::IsEmpty;
|
||||
using ::testing::IsNull;
|
||||
using ::testing::Pair;
|
||||
using ::testing::SizeIs;
|
||||
|
||||
template <typename T, typename U>
|
||||
void CheckPairEquals(const T &x, const U &y) {
|
||||
@ -89,8 +92,8 @@ class base_checker {
|
||||
|
||||
public:
|
||||
base_checker() : const_tree_(tree_) {}
|
||||
base_checker(const base_checker &x)
|
||||
: tree_(x.tree_), const_tree_(tree_), checker_(x.checker_) {}
|
||||
base_checker(const base_checker &other)
|
||||
: tree_(other.tree_), const_tree_(tree_), checker_(other.checker_) {}
|
||||
template <typename InputIterator>
|
||||
base_checker(InputIterator b, InputIterator e)
|
||||
: tree_(b, e), const_tree_(tree_), checker_(b, e) {}
|
||||
@ -124,11 +127,11 @@ class base_checker {
|
||||
}
|
||||
return tree_iter;
|
||||
}
|
||||
void value_check(const value_type &x) {
|
||||
void value_check(const value_type &v) {
|
||||
typename KeyOfValue<typename TreeType::key_type,
|
||||
typename TreeType::value_type>::type key_of_value;
|
||||
const key_type &key = key_of_value(x);
|
||||
CheckPairEquals(*find(key), x);
|
||||
const key_type &key = key_of_value(v);
|
||||
CheckPairEquals(*find(key), v);
|
||||
lower_bound(key);
|
||||
upper_bound(key);
|
||||
equal_range(key);
|
||||
@ -187,9 +190,9 @@ class base_checker {
|
||||
return res;
|
||||
}
|
||||
|
||||
base_checker &operator=(const base_checker &x) {
|
||||
tree_ = x.tree_;
|
||||
checker_ = x.checker_;
|
||||
base_checker &operator=(const base_checker &other) {
|
||||
tree_ = other.tree_;
|
||||
checker_ = other.checker_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -250,9 +253,9 @@ class base_checker {
|
||||
tree_.clear();
|
||||
checker_.clear();
|
||||
}
|
||||
void swap(base_checker &x) {
|
||||
tree_.swap(x.tree_);
|
||||
checker_.swap(x.checker_);
|
||||
void swap(base_checker &other) {
|
||||
tree_.swap(other.tree_);
|
||||
checker_.swap(other.checker_);
|
||||
}
|
||||
|
||||
void verify() const {
|
||||
@ -323,28 +326,28 @@ class unique_checker : public base_checker<TreeType, CheckerType> {
|
||||
|
||||
public:
|
||||
unique_checker() : super_type() {}
|
||||
unique_checker(const unique_checker &x) : super_type(x) {}
|
||||
unique_checker(const unique_checker &other) : super_type(other) {}
|
||||
template <class InputIterator>
|
||||
unique_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
|
||||
unique_checker &operator=(const unique_checker &) = default;
|
||||
|
||||
// Insertion routines.
|
||||
std::pair<iterator, bool> insert(const value_type &x) {
|
||||
std::pair<iterator, bool> insert(const value_type &v) {
|
||||
int size = this->tree_.size();
|
||||
std::pair<typename CheckerType::iterator, bool> checker_res =
|
||||
this->checker_.insert(x);
|
||||
std::pair<iterator, bool> tree_res = this->tree_.insert(x);
|
||||
this->checker_.insert(v);
|
||||
std::pair<iterator, bool> tree_res = this->tree_.insert(v);
|
||||
CheckPairEquals(*tree_res.first, *checker_res.first);
|
||||
EXPECT_EQ(tree_res.second, checker_res.second);
|
||||
EXPECT_EQ(this->tree_.size(), this->checker_.size());
|
||||
EXPECT_EQ(this->tree_.size(), size + tree_res.second);
|
||||
return tree_res;
|
||||
}
|
||||
iterator insert(iterator position, const value_type &x) {
|
||||
iterator insert(iterator position, const value_type &v) {
|
||||
int size = this->tree_.size();
|
||||
std::pair<typename CheckerType::iterator, bool> checker_res =
|
||||
this->checker_.insert(x);
|
||||
iterator tree_res = this->tree_.insert(position, x);
|
||||
this->checker_.insert(v);
|
||||
iterator tree_res = this->tree_.insert(position, v);
|
||||
CheckPairEquals(*tree_res, *checker_res.first);
|
||||
EXPECT_EQ(this->tree_.size(), this->checker_.size());
|
||||
EXPECT_EQ(this->tree_.size(), size + checker_res.second);
|
||||
@ -371,25 +374,25 @@ class multi_checker : public base_checker<TreeType, CheckerType> {
|
||||
|
||||
public:
|
||||
multi_checker() : super_type() {}
|
||||
multi_checker(const multi_checker &x) : super_type(x) {}
|
||||
multi_checker(const multi_checker &other) : super_type(other) {}
|
||||
template <class InputIterator>
|
||||
multi_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
|
||||
multi_checker &operator=(const multi_checker &) = default;
|
||||
|
||||
// Insertion routines.
|
||||
iterator insert(const value_type &x) {
|
||||
iterator insert(const value_type &v) {
|
||||
int size = this->tree_.size();
|
||||
auto checker_res = this->checker_.insert(x);
|
||||
iterator tree_res = this->tree_.insert(x);
|
||||
auto checker_res = this->checker_.insert(v);
|
||||
iterator tree_res = this->tree_.insert(v);
|
||||
CheckPairEquals(*tree_res, *checker_res);
|
||||
EXPECT_EQ(this->tree_.size(), this->checker_.size());
|
||||
EXPECT_EQ(this->tree_.size(), size + 1);
|
||||
return tree_res;
|
||||
}
|
||||
iterator insert(iterator position, const value_type &x) {
|
||||
iterator insert(iterator position, const value_type &v) {
|
||||
int size = this->tree_.size();
|
||||
auto checker_res = this->checker_.insert(x);
|
||||
iterator tree_res = this->tree_.insert(position, x);
|
||||
auto checker_res = this->checker_.insert(v);
|
||||
iterator tree_res = this->tree_.insert(position, v);
|
||||
CheckPairEquals(*tree_res, *checker_res);
|
||||
EXPECT_EQ(this->tree_.size(), this->checker_.size());
|
||||
EXPECT_EQ(this->tree_.size(), size + 1);
|
||||
@ -592,7 +595,7 @@ void BtreeTest() {
|
||||
using V = typename remove_pair_const<typename T::value_type>::type;
|
||||
const std::vector<V> random_values = GenerateValuesWithSeed<V>(
|
||||
absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),
|
||||
testing::GTEST_FLAG(random_seed));
|
||||
GTEST_FLAG_GET(random_seed));
|
||||
|
||||
unique_checker<T, C> container;
|
||||
|
||||
@ -616,7 +619,7 @@ void BtreeMultiTest() {
|
||||
using V = typename remove_pair_const<typename T::value_type>::type;
|
||||
const std::vector<V> random_values = GenerateValuesWithSeed<V>(
|
||||
absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),
|
||||
testing::GTEST_FLAG(random_seed));
|
||||
GTEST_FLAG_GET(random_seed));
|
||||
|
||||
multi_checker<T, C> container;
|
||||
|
||||
@ -812,10 +815,12 @@ void MapTest() {
|
||||
TEST(Btree, set_int32) { SetTest<int32_t>(); }
|
||||
TEST(Btree, set_int64) { SetTest<int64_t>(); }
|
||||
TEST(Btree, set_string) { SetTest<std::string>(); }
|
||||
TEST(Btree, set_cord) { SetTest<absl::Cord>(); }
|
||||
TEST(Btree, set_pair) { SetTest<std::pair<int, int>>(); }
|
||||
TEST(Btree, map_int32) { MapTest<int32_t>(); }
|
||||
TEST(Btree, map_int64) { MapTest<int64_t>(); }
|
||||
TEST(Btree, map_string) { MapTest<std::string>(); }
|
||||
TEST(Btree, map_cord) { MapTest<absl::Cord>(); }
|
||||
TEST(Btree, map_pair) { MapTest<std::pair<int, int>>(); }
|
||||
|
||||
template <typename K, int N = 256>
|
||||
@ -847,10 +852,12 @@ void MultiMapTest() {
|
||||
TEST(Btree, multiset_int32) { MultiSetTest<int32_t>(); }
|
||||
TEST(Btree, multiset_int64) { MultiSetTest<int64_t>(); }
|
||||
TEST(Btree, multiset_string) { MultiSetTest<std::string>(); }
|
||||
TEST(Btree, multiset_cord) { MultiSetTest<absl::Cord>(); }
|
||||
TEST(Btree, multiset_pair) { MultiSetTest<std::pair<int, int>>(); }
|
||||
TEST(Btree, multimap_int32) { MultiMapTest<int32_t>(); }
|
||||
TEST(Btree, multimap_int64) { MultiMapTest<int64_t>(); }
|
||||
TEST(Btree, multimap_string) { MultiMapTest<std::string>(); }
|
||||
TEST(Btree, multimap_cord) { MultiMapTest<absl::Cord>(); }
|
||||
TEST(Btree, multimap_pair) { MultiMapTest<std::pair<int, int>>(); }
|
||||
|
||||
struct CompareIntToString {
|
||||
@ -1176,6 +1183,103 @@ TEST(Btree, RangeCtorSanity) {
|
||||
EXPECT_EQ(1, tmap.size());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class BtreeNodePeer {
|
||||
public:
|
||||
// Yields the size of a leaf node with a specific number of values.
|
||||
template <typename ValueType>
|
||||
constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
|
||||
return btree_node<
|
||||
set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
|
||||
/*TargetNodeSize=*/256, // This parameter isn't used here.
|
||||
/*Multi=*/false>>::SizeWithNSlots(target_values_per_node);
|
||||
}
|
||||
|
||||
// Yields the number of slots in a (non-root) leaf node for this btree.
|
||||
template <typename Btree>
|
||||
constexpr static size_t GetNumSlotsPerNode() {
|
||||
return btree_node<typename Btree::params_type>::kNodeSlots;
|
||||
}
|
||||
|
||||
template <typename Btree>
|
||||
constexpr static size_t GetMaxFieldType() {
|
||||
return std::numeric_limits<
|
||||
typename btree_node<typename Btree::params_type>::field_type>::max();
|
||||
}
|
||||
|
||||
template <typename Btree>
|
||||
constexpr static bool UsesLinearNodeSearch() {
|
||||
return btree_node<typename Btree::params_type>::use_linear_search::value;
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
class BtreeMapTest : public ::testing::Test {
|
||||
public:
|
||||
struct Key {};
|
||||
struct Cmp {
|
||||
template <typename T>
|
||||
bool operator()(T, T) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct KeyLin {
|
||||
using absl_btree_prefer_linear_node_search = std::true_type;
|
||||
};
|
||||
struct CmpLin : Cmp {
|
||||
using absl_btree_prefer_linear_node_search = std::true_type;
|
||||
};
|
||||
|
||||
struct KeyBin {
|
||||
using absl_btree_prefer_linear_node_search = std::false_type;
|
||||
};
|
||||
struct CmpBin : Cmp {
|
||||
using absl_btree_prefer_linear_node_search = std::false_type;
|
||||
};
|
||||
|
||||
template <typename K, typename C>
|
||||
static bool IsLinear() {
|
||||
return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) {
|
||||
// Test requesting linear search by directly exporting an alias.
|
||||
EXPECT_FALSE((IsLinear<Key, Cmp>()));
|
||||
EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
|
||||
EXPECT_TRUE((IsLinear<Key, CmpLin>()));
|
||||
EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
|
||||
}
|
||||
|
||||
TEST_F(BtreeMapTest, LinearChoiceTree) {
|
||||
// Cmp has precedence, and is forcing binary
|
||||
EXPECT_FALSE((IsLinear<Key, CmpBin>()));
|
||||
EXPECT_FALSE((IsLinear<KeyLin, CmpBin>()));
|
||||
EXPECT_FALSE((IsLinear<KeyBin, CmpBin>()));
|
||||
EXPECT_FALSE((IsLinear<int, CmpBin>()));
|
||||
EXPECT_FALSE((IsLinear<std::string, CmpBin>()));
|
||||
// Cmp has precedence, and is forcing linear
|
||||
EXPECT_TRUE((IsLinear<Key, CmpLin>()));
|
||||
EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
|
||||
EXPECT_TRUE((IsLinear<KeyBin, CmpLin>()));
|
||||
EXPECT_TRUE((IsLinear<int, CmpLin>()));
|
||||
EXPECT_TRUE((IsLinear<std::string, CmpLin>()));
|
||||
// Cmp has no preference, Key determines linear vs binary.
|
||||
EXPECT_FALSE((IsLinear<Key, Cmp>()));
|
||||
EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
|
||||
EXPECT_FALSE((IsLinear<KeyBin, Cmp>()));
|
||||
// arithmetic key w/ std::less or std::greater: linear
|
||||
EXPECT_TRUE((IsLinear<int, std::less<int>>()));
|
||||
EXPECT_TRUE((IsLinear<double, std::greater<double>>()));
|
||||
// arithmetic key w/ custom compare: binary
|
||||
EXPECT_FALSE((IsLinear<int, Cmp>()));
|
||||
// non-arithmetic key: binary
|
||||
EXPECT_FALSE((IsLinear<std::string, std::less<std::string>>()));
|
||||
}
|
||||
|
||||
TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {
|
||||
absl::btree_map<std::string, std::unique_ptr<std::string>> m;
|
||||
|
||||
@ -1268,6 +1372,8 @@ TEST(Btree, KeyCompareToAdapter) {
|
||||
AssertKeyCompareToAdapted<std::less<absl::string_view>, absl::string_view>();
|
||||
AssertKeyCompareToAdapted<std::greater<absl::string_view>,
|
||||
absl::string_view>();
|
||||
AssertKeyCompareToAdapted<std::less<absl::Cord>, absl::Cord>();
|
||||
AssertKeyCompareToAdapted<std::greater<absl::Cord>, absl::Cord>();
|
||||
AssertKeyCompareToNotAdapted<std::less<int>, int>();
|
||||
AssertKeyCompareToNotAdapted<std::greater<int>, int>();
|
||||
}
|
||||
@ -1319,28 +1425,6 @@ TEST(Btree, RValueInsert) {
|
||||
EXPECT_EQ(tracker.swaps(), 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class BtreeNodePeer {
|
||||
public:
|
||||
// Yields the size of a leaf node with a specific number of values.
|
||||
template <typename ValueType>
|
||||
constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
|
||||
return btree_node<
|
||||
set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
|
||||
/*TargetNodeSize=*/256, // This parameter isn't used here.
|
||||
/*Multi=*/false>>::SizeWithNValues(target_values_per_node);
|
||||
}
|
||||
|
||||
// Yields the number of values in a (non-root) leaf node for this set.
|
||||
template <typename Set>
|
||||
constexpr static size_t GetNumValuesPerNode() {
|
||||
return btree_node<typename Set::params_type>::kNodeValues;
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
// A btree set with a specific number of values per node.
|
||||
template <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>>
|
||||
class SizedBtreeSet
|
||||
@ -1374,7 +1458,7 @@ void ExpectOperationCounts(const int expected_moves,
|
||||
TEST(Btree, MovesComparisonsCopiesSwapsTracking) {
|
||||
InstanceTracker tracker;
|
||||
// Note: this is minimum number of values per node.
|
||||
SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/3> set3;
|
||||
SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4> set4;
|
||||
// Note: this is the default number of values per node for a set of int32s
|
||||
// (with 64-bit pointers).
|
||||
SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61> set61;
|
||||
@ -1385,28 +1469,28 @@ TEST(Btree, MovesComparisonsCopiesSwapsTracking) {
|
||||
std::vector<int> values =
|
||||
GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);
|
||||
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set3)>(), 3);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>(), 61);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set100)>(), 100);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set4)>(), 4);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>(), 61);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set100)>(), 100);
|
||||
if (sizeof(void *) == 8) {
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<absl::btree_set<int32_t>>(),
|
||||
BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>());
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),
|
||||
BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>());
|
||||
}
|
||||
|
||||
// Test key insertion/deletion in random order.
|
||||
ExpectOperationCounts(45281, 132551, values, &tracker, &set3);
|
||||
ExpectOperationCounts(56540, 134212, values, &tracker, &set4);
|
||||
ExpectOperationCounts(386718, 129807, values, &tracker, &set61);
|
||||
ExpectOperationCounts(586761, 130310, values, &tracker, &set100);
|
||||
|
||||
// Test key insertion/deletion in sorted order.
|
||||
std::sort(values.begin(), values.end());
|
||||
ExpectOperationCounts(26638, 92134, values, &tracker, &set3);
|
||||
ExpectOperationCounts(24972, 85563, values, &tracker, &set4);
|
||||
ExpectOperationCounts(20208, 87757, values, &tracker, &set61);
|
||||
ExpectOperationCounts(20124, 96583, values, &tracker, &set100);
|
||||
|
||||
// Test key insertion/deletion in reverse sorted order.
|
||||
std::reverse(values.begin(), values.end());
|
||||
ExpectOperationCounts(49951, 119325, values, &tracker, &set3);
|
||||
ExpectOperationCounts(54949, 127531, values, &tracker, &set4);
|
||||
ExpectOperationCounts(338813, 118266, values, &tracker, &set61);
|
||||
ExpectOperationCounts(534529, 125279, values, &tracker, &set100);
|
||||
}
|
||||
@ -1423,9 +1507,9 @@ struct MovableOnlyInstanceThreeWayCompare {
|
||||
TEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) {
|
||||
InstanceTracker tracker;
|
||||
// Note: this is minimum number of values per node.
|
||||
SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/3,
|
||||
SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4,
|
||||
MovableOnlyInstanceThreeWayCompare>
|
||||
set3;
|
||||
set4;
|
||||
// Note: this is the default number of values per node for a set of int32s
|
||||
// (with 64-bit pointers).
|
||||
SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61,
|
||||
@ -1440,28 +1524,28 @@ TEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) {
|
||||
std::vector<int> values =
|
||||
GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);
|
||||
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set3)>(), 3);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>(), 61);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set100)>(), 100);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set4)>(), 4);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>(), 61);
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set100)>(), 100);
|
||||
if (sizeof(void *) == 8) {
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<absl::btree_set<int32_t>>(),
|
||||
BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>());
|
||||
EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),
|
||||
BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>());
|
||||
}
|
||||
|
||||
// Test key insertion/deletion in random order.
|
||||
ExpectOperationCounts(45281, 122560, values, &tracker, &set3);
|
||||
ExpectOperationCounts(56540, 124221, values, &tracker, &set4);
|
||||
ExpectOperationCounts(386718, 119816, values, &tracker, &set61);
|
||||
ExpectOperationCounts(586761, 120319, values, &tracker, &set100);
|
||||
|
||||
// Test key insertion/deletion in sorted order.
|
||||
std::sort(values.begin(), values.end());
|
||||
ExpectOperationCounts(26638, 92134, values, &tracker, &set3);
|
||||
ExpectOperationCounts(24972, 85563, values, &tracker, &set4);
|
||||
ExpectOperationCounts(20208, 87757, values, &tracker, &set61);
|
||||
ExpectOperationCounts(20124, 96583, values, &tracker, &set100);
|
||||
|
||||
// Test key insertion/deletion in reverse sorted order.
|
||||
std::reverse(values.begin(), values.end());
|
||||
ExpectOperationCounts(49951, 109326, values, &tracker, &set3);
|
||||
ExpectOperationCounts(54949, 117532, values, &tracker, &set4);
|
||||
ExpectOperationCounts(338813, 108267, values, &tracker, &set61);
|
||||
ExpectOperationCounts(534529, 115280, values, &tracker, &set100);
|
||||
}
|
||||
@ -1537,7 +1621,7 @@ TEST(Btree, MapAt) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
EXPECT_THROW(map.at(3), std::out_of_range);
|
||||
#else
|
||||
EXPECT_DEATH(map.at(3), "absl::btree_map::at");
|
||||
EXPECT_DEATH_IF_SUPPORTED(map.at(3), "absl::btree_map::at");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1624,10 +1708,25 @@ TEST(Btree, StrSplitCompatible) {
|
||||
EXPECT_EQ(split_set, expected_set);
|
||||
}
|
||||
|
||||
// We can't use EXPECT_EQ/etc. to compare absl::weak_ordering because they
|
||||
// convert literal 0 to int and absl::weak_ordering can only be compared with
|
||||
// literal 0. Defining this function allows for avoiding ClangTidy warnings.
|
||||
bool Identity(const bool b) { return b; }
|
||||
TEST(Btree, KeyComp) {
|
||||
absl::btree_set<int> s;
|
||||
EXPECT_TRUE(s.key_comp()(1, 2));
|
||||
EXPECT_FALSE(s.key_comp()(2, 2));
|
||||
EXPECT_FALSE(s.key_comp()(2, 1));
|
||||
|
||||
absl::btree_map<int, int> m1;
|
||||
EXPECT_TRUE(m1.key_comp()(1, 2));
|
||||
EXPECT_FALSE(m1.key_comp()(2, 2));
|
||||
EXPECT_FALSE(m1.key_comp()(2, 1));
|
||||
|
||||
// Even though we internally adapt the comparator of `m2` to be three-way and
|
||||
// heterogeneous, the comparator we expose through key_comp() is the original
|
||||
// unadapted comparator.
|
||||
absl::btree_map<std::string, int> m2;
|
||||
EXPECT_TRUE(m2.key_comp()("a", "b"));
|
||||
EXPECT_FALSE(m2.key_comp()("b", "b"));
|
||||
EXPECT_FALSE(m2.key_comp()("b", "a"));
|
||||
}
|
||||
|
||||
TEST(Btree, ValueComp) {
|
||||
absl::btree_set<int> s;
|
||||
@ -1640,13 +1739,13 @@ TEST(Btree, ValueComp) {
|
||||
EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(2, 0)));
|
||||
EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(1, 0)));
|
||||
|
||||
// Even though we internally adapt the comparator of `m2` to be three-way and
|
||||
// heterogeneous, the comparator we expose through value_comp() is based on
|
||||
// the original unadapted comparator.
|
||||
absl::btree_map<std::string, int> m2;
|
||||
EXPECT_TRUE(Identity(
|
||||
m2.value_comp()(std::make_pair("a", 0), std::make_pair("b", 0)) < 0));
|
||||
EXPECT_TRUE(Identity(
|
||||
m2.value_comp()(std::make_pair("b", 0), std::make_pair("b", 0)) == 0));
|
||||
EXPECT_TRUE(Identity(
|
||||
m2.value_comp()(std::make_pair("b", 0), std::make_pair("a", 0)) > 0));
|
||||
EXPECT_TRUE(m2.value_comp()(std::make_pair("a", 0), std::make_pair("b", 0)));
|
||||
EXPECT_FALSE(m2.value_comp()(std::make_pair("b", 0), std::make_pair("b", 0)));
|
||||
EXPECT_FALSE(m2.value_comp()(std::make_pair("b", 0), std::make_pair("a", 0)));
|
||||
}
|
||||
|
||||
TEST(Btree, DefaultConstruction) {
|
||||
@ -1954,6 +2053,30 @@ TEST(Btree, ExtractAndInsertNodeHandleMultiMap) {
|
||||
EXPECT_EQ(res, ++other.begin());
|
||||
}
|
||||
|
||||
TEST(Btree, ExtractMultiMapEquivalentKeys) {
|
||||
// Note: using string keys means a three-way comparator.
|
||||
absl::btree_multimap<std::string, int> map;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
for (int j = 0; j < 100; ++j) {
|
||||
map.insert({absl::StrCat(i), j});
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
const std::string key = absl::StrCat(i);
|
||||
auto node_handle = map.extract(key);
|
||||
EXPECT_EQ(node_handle.key(), key);
|
||||
EXPECT_EQ(node_handle.mapped(), 0) << i;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
const std::string key = absl::StrCat(i);
|
||||
auto node_handle = map.extract(key);
|
||||
EXPECT_EQ(node_handle.key(), key);
|
||||
EXPECT_EQ(node_handle.mapped(), 1) << i;
|
||||
}
|
||||
}
|
||||
|
||||
// For multisets, insert with hint also affects correctness because we need to
|
||||
// insert immediately before the hint if possible.
|
||||
struct InsertMultiHintData {
|
||||
@ -2095,6 +2218,31 @@ TEST(Btree, MergeIntoMultiMapsWithDifferentComparators) {
|
||||
Pair(4, 1), Pair(4, 4), Pair(5, 5)));
|
||||
}
|
||||
|
||||
TEST(Btree, MergeIntoSetMovableOnly) {
|
||||
absl::btree_set<MovableOnlyInstance> src;
|
||||
src.insert(MovableOnlyInstance(1));
|
||||
absl::btree_multiset<MovableOnlyInstance> dst1;
|
||||
dst1.insert(MovableOnlyInstance(2));
|
||||
absl::btree_set<MovableOnlyInstance> dst2;
|
||||
|
||||
// Test merge into multiset.
|
||||
dst1.merge(src);
|
||||
|
||||
EXPECT_TRUE(src.empty());
|
||||
// ElementsAre/ElementsAreArray don't work with move-only types.
|
||||
ASSERT_THAT(dst1, SizeIs(2));
|
||||
EXPECT_EQ(*dst1.begin(), MovableOnlyInstance(1));
|
||||
EXPECT_EQ(*std::next(dst1.begin()), MovableOnlyInstance(2));
|
||||
|
||||
// Test merge into set.
|
||||
dst2.merge(dst1);
|
||||
|
||||
EXPECT_TRUE(dst1.empty());
|
||||
ASSERT_THAT(dst2, SizeIs(2));
|
||||
EXPECT_EQ(*dst2.begin(), MovableOnlyInstance(1));
|
||||
EXPECT_EQ(*std::next(dst2.begin()), MovableOnlyInstance(2));
|
||||
}
|
||||
|
||||
struct KeyCompareToWeakOrdering {
|
||||
template <typename T>
|
||||
absl::weak_ordering operator()(const T &a, const T &b) const {
|
||||
@ -2126,11 +2274,11 @@ TEST(Btree, UserProvidedKeyCompareToComparators) {
|
||||
TEST(Btree, TryEmplaceBasicTest) {
|
||||
absl::btree_map<int, std::string> m;
|
||||
|
||||
// Should construct a std::string from the literal.
|
||||
// Should construct a string from the literal.
|
||||
m.try_emplace(1, "one");
|
||||
EXPECT_EQ(1, m.size());
|
||||
|
||||
// Try other std::string constructors and const lvalue key.
|
||||
// Try other string constructors and const lvalue key.
|
||||
const int key(42);
|
||||
m.try_emplace(key, 3, 'a');
|
||||
m.try_emplace(2, std::string("two"));
|
||||
@ -2398,6 +2546,408 @@ TEST(Btree, BitfieldArgument) {
|
||||
m[n];
|
||||
}
|
||||
|
||||
TEST(Btree, SetRangeConstructorAndInsertSupportExplicitConversionComparable) {
|
||||
const absl::string_view names[] = {"n1", "n2"};
|
||||
|
||||
absl::btree_set<std::string> name_set1{std::begin(names), std::end(names)};
|
||||
EXPECT_THAT(name_set1, ElementsAreArray(names));
|
||||
|
||||
absl::btree_set<std::string> name_set2;
|
||||
name_set2.insert(std::begin(names), std::end(names));
|
||||
EXPECT_THAT(name_set2, ElementsAreArray(names));
|
||||
}
|
||||
|
||||
// A type that is explicitly convertible from int and counts constructor calls.
|
||||
struct ConstructorCounted {
|
||||
explicit ConstructorCounted(int i) : i(i) { ++constructor_calls; }
|
||||
bool operator==(int other) const { return i == other; }
|
||||
|
||||
int i;
|
||||
static int constructor_calls;
|
||||
};
|
||||
int ConstructorCounted::constructor_calls = 0;
|
||||
|
||||
struct ConstructorCountedCompare {
|
||||
bool operator()(int a, const ConstructorCounted &b) const { return a < b.i; }
|
||||
bool operator()(const ConstructorCounted &a, int b) const { return a.i < b; }
|
||||
bool operator()(const ConstructorCounted &a,
|
||||
const ConstructorCounted &b) const {
|
||||
return a.i < b.i;
|
||||
}
|
||||
using is_transparent = void;
|
||||
};
|
||||
|
||||
TEST(Btree,
|
||||
SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
|
||||
const int i[] = {0, 1, 1};
|
||||
ConstructorCounted::constructor_calls = 0;
|
||||
|
||||
absl::btree_set<ConstructorCounted, ConstructorCountedCompare> set{
|
||||
std::begin(i), std::end(i)};
|
||||
EXPECT_THAT(set, ElementsAre(0, 1));
|
||||
EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
|
||||
|
||||
set.insert(std::begin(i), std::end(i));
|
||||
EXPECT_THAT(set, ElementsAre(0, 1));
|
||||
EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
|
||||
}
|
||||
|
||||
TEST(Btree,
|
||||
SetRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
|
||||
const int i[] = {0, 1};
|
||||
|
||||
absl::btree_set<std::vector<void *>> s1{std::begin(i), std::end(i)};
|
||||
EXPECT_THAT(s1, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
|
||||
|
||||
absl::btree_set<std::vector<void *>> s2;
|
||||
s2.insert(std::begin(i), std::end(i));
|
||||
EXPECT_THAT(s2, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
|
||||
}
|
||||
|
||||
// libstdc++ included with GCC 4.9 has a bug in the std::pair constructors that
|
||||
// prevents explicit conversions between pair types.
|
||||
// We only run this test for the libstdc++ from GCC 7 or newer because we can't
|
||||
// reliably check the libstdc++ version prior to that release.
|
||||
#if !defined(__GLIBCXX__) || \
|
||||
(defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7)
|
||||
TEST(Btree, MapRangeConstructorAndInsertSupportExplicitConversionComparable) {
|
||||
const std::pair<absl::string_view, int> names[] = {{"n1", 1}, {"n2", 2}};
|
||||
|
||||
absl::btree_map<std::string, int> name_map1{std::begin(names),
|
||||
std::end(names)};
|
||||
EXPECT_THAT(name_map1, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
|
||||
|
||||
absl::btree_map<std::string, int> name_map2;
|
||||
name_map2.insert(std::begin(names), std::end(names));
|
||||
EXPECT_THAT(name_map2, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
|
||||
}
|
||||
|
||||
TEST(Btree,
|
||||
MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
|
||||
const std::pair<int, int> i[] = {{0, 1}, {1, 2}, {1, 3}};
|
||||
ConstructorCounted::constructor_calls = 0;
|
||||
|
||||
absl::btree_map<ConstructorCounted, int, ConstructorCountedCompare> map{
|
||||
std::begin(i), std::end(i)};
|
||||
EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
|
||||
EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
|
||||
|
||||
map.insert(std::begin(i), std::end(i));
|
||||
EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
|
||||
EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
|
||||
}
|
||||
|
||||
TEST(Btree,
|
||||
MapRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
|
||||
const std::pair<int, int> i[] = {{0, 1}, {1, 2}};
|
||||
|
||||
absl::btree_map<std::vector<void *>, int> m1{std::begin(i), std::end(i)};
|
||||
EXPECT_THAT(m1,
|
||||
ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
|
||||
|
||||
absl::btree_map<std::vector<void *>, int> m2;
|
||||
m2.insert(std::begin(i), std::end(i));
|
||||
EXPECT_THAT(m2,
|
||||
ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
|
||||
}
|
||||
|
||||
TEST(Btree, HeterogeneousTryEmplace) {
|
||||
absl::btree_map<std::string, int> m;
|
||||
std::string s = "key";
|
||||
absl::string_view sv = s;
|
||||
m.try_emplace(sv, 1);
|
||||
EXPECT_EQ(m[s], 1);
|
||||
|
||||
m.try_emplace(m.end(), sv, 2);
|
||||
EXPECT_EQ(m[s], 1);
|
||||
}
|
||||
|
||||
TEST(Btree, HeterogeneousOperatorMapped) {
|
||||
absl::btree_map<std::string, int> m;
|
||||
std::string s = "key";
|
||||
absl::string_view sv = s;
|
||||
m[sv] = 1;
|
||||
EXPECT_EQ(m[s], 1);
|
||||
|
||||
m[sv] = 2;
|
||||
EXPECT_EQ(m[s], 2);
|
||||
}
|
||||
|
||||
TEST(Btree, HeterogeneousInsertOrAssign) {
|
||||
absl::btree_map<std::string, int> m;
|
||||
std::string s = "key";
|
||||
absl::string_view sv = s;
|
||||
m.insert_or_assign(sv, 1);
|
||||
EXPECT_EQ(m[s], 1);
|
||||
|
||||
m.insert_or_assign(m.end(), sv, 2);
|
||||
EXPECT_EQ(m[s], 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// This test requires std::launder for mutable key access in node handles.
|
||||
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
|
||||
TEST(Btree, NodeHandleMutableKeyAccess) {
|
||||
{
|
||||
absl::btree_map<std::string, std::string> map;
|
||||
|
||||
map["key1"] = "mapped";
|
||||
|
||||
auto nh = map.extract(map.begin());
|
||||
nh.key().resize(3);
|
||||
map.insert(std::move(nh));
|
||||
|
||||
EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
|
||||
}
|
||||
// Also for multimap.
|
||||
{
|
||||
absl::btree_multimap<std::string, std::string> map;
|
||||
|
||||
map.emplace("key1", "mapped");
|
||||
|
||||
auto nh = map.extract(map.begin());
|
||||
nh.key().resize(3);
|
||||
map.insert(std::move(nh));
|
||||
|
||||
EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct MultiKey {
|
||||
int i1;
|
||||
int i2;
|
||||
};
|
||||
|
||||
bool operator==(const MultiKey a, const MultiKey b) {
|
||||
return a.i1 == b.i1 && a.i2 == b.i2;
|
||||
}
|
||||
|
||||
// A heterogeneous comparator that has different equivalence classes for
|
||||
// different lookup types.
|
||||
struct MultiKeyComp {
|
||||
using is_transparent = void;
|
||||
bool operator()(const MultiKey a, const MultiKey b) const {
|
||||
if (a.i1 != b.i1) return a.i1 < b.i1;
|
||||
return a.i2 < b.i2;
|
||||
}
|
||||
bool operator()(const int a, const MultiKey b) const { return a < b.i1; }
|
||||
bool operator()(const MultiKey a, const int b) const { return a.i1 < b; }
|
||||
};
|
||||
|
||||
// A heterogeneous, three-way comparator that has different equivalence classes
|
||||
// for different lookup types.
|
||||
struct MultiKeyThreeWayComp {
|
||||
using is_transparent = void;
|
||||
absl::weak_ordering operator()(const MultiKey a, const MultiKey b) const {
|
||||
if (a.i1 < b.i1) return absl::weak_ordering::less;
|
||||
if (a.i1 > b.i1) return absl::weak_ordering::greater;
|
||||
if (a.i2 < b.i2) return absl::weak_ordering::less;
|
||||
if (a.i2 > b.i2) return absl::weak_ordering::greater;
|
||||
return absl::weak_ordering::equivalent;
|
||||
}
|
||||
absl::weak_ordering operator()(const int a, const MultiKey b) const {
|
||||
if (a < b.i1) return absl::weak_ordering::less;
|
||||
if (a > b.i1) return absl::weak_ordering::greater;
|
||||
return absl::weak_ordering::equivalent;
|
||||
}
|
||||
absl::weak_ordering operator()(const MultiKey a, const int b) const {
|
||||
if (a.i1 < b) return absl::weak_ordering::less;
|
||||
if (a.i1 > b) return absl::weak_ordering::greater;
|
||||
return absl::weak_ordering::equivalent;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Compare>
|
||||
class BtreeMultiKeyTest : public ::testing::Test {};
|
||||
using MultiKeyComps = ::testing::Types<MultiKeyComp, MultiKeyThreeWayComp>;
|
||||
TYPED_TEST_SUITE(BtreeMultiKeyTest, MultiKeyComps);
|
||||
|
||||
TYPED_TEST(BtreeMultiKeyTest, EqualRange) {
|
||||
absl::btree_set<MultiKey, TypeParam> set;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
for (int j = 0; j < 100; ++j) {
|
||||
set.insert({i, j});
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
auto equal_range = set.equal_range(i);
|
||||
EXPECT_EQ(equal_range.first->i1, i);
|
||||
EXPECT_EQ(equal_range.first->i2, 0) << i;
|
||||
EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) << i;
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST(BtreeMultiKeyTest, Extract) {
|
||||
absl::btree_set<MultiKey, TypeParam> set;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
for (int j = 0; j < 100; ++j) {
|
||||
set.insert({i, j});
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
auto node_handle = set.extract(i);
|
||||
EXPECT_EQ(node_handle.value().i1, i);
|
||||
EXPECT_EQ(node_handle.value().i2, 0) << i;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
auto node_handle = set.extract(i);
|
||||
EXPECT_EQ(node_handle.value().i1, i);
|
||||
EXPECT_EQ(node_handle.value().i2, 1) << i;
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST(BtreeMultiKeyTest, Erase) {
|
||||
absl::btree_set<MultiKey, TypeParam> set = {
|
||||
{1, 1}, {2, 1}, {2, 2}, {3, 1}};
|
||||
EXPECT_EQ(set.erase(2), 2);
|
||||
EXPECT_THAT(set, ElementsAre(MultiKey{1, 1}, MultiKey{3, 1}));
|
||||
}
|
||||
|
||||
TYPED_TEST(BtreeMultiKeyTest, Count) {
|
||||
const absl::btree_set<MultiKey, TypeParam> set = {
|
||||
{1, 1}, {2, 1}, {2, 2}, {3, 1}};
|
||||
EXPECT_EQ(set.count(2), 2);
|
||||
}
|
||||
|
||||
TEST(Btree, AllocConstructor) {
|
||||
using Alloc = CountingAllocator<int>;
|
||||
using Set = absl::btree_set<int, std::less<int>, Alloc>;
|
||||
int64_t bytes_used = 0;
|
||||
Alloc alloc(&bytes_used);
|
||||
Set set(alloc);
|
||||
|
||||
set.insert({1, 2, 3});
|
||||
|
||||
EXPECT_THAT(set, ElementsAre(1, 2, 3));
|
||||
EXPECT_GT(bytes_used, set.size() * sizeof(int));
|
||||
}
|
||||
|
||||
TEST(Btree, AllocInitializerListConstructor) {
|
||||
using Alloc = CountingAllocator<int>;
|
||||
using Set = absl::btree_set<int, std::less<int>, Alloc>;
|
||||
int64_t bytes_used = 0;
|
||||
Alloc alloc(&bytes_used);
|
||||
Set set({1, 2, 3}, alloc);
|
||||
|
||||
EXPECT_THAT(set, ElementsAre(1, 2, 3));
|
||||
EXPECT_GT(bytes_used, set.size() * sizeof(int));
|
||||
}
|
||||
|
||||
TEST(Btree, AllocRangeConstructor) {
|
||||
using Alloc = CountingAllocator<int>;
|
||||
using Set = absl::btree_set<int, std::less<int>, Alloc>;
|
||||
int64_t bytes_used = 0;
|
||||
Alloc alloc(&bytes_used);
|
||||
std::vector<int> v = {1, 2, 3};
|
||||
Set set(v.begin(), v.end(), alloc);
|
||||
|
||||
EXPECT_THAT(set, ElementsAre(1, 2, 3));
|
||||
EXPECT_GT(bytes_used, set.size() * sizeof(int));
|
||||
}
|
||||
|
||||
TEST(Btree, AllocCopyConstructor) {
|
||||
using Alloc = CountingAllocator<int>;
|
||||
using Set = absl::btree_set<int, std::less<int>, Alloc>;
|
||||
int64_t bytes_used1 = 0;
|
||||
Alloc alloc1(&bytes_used1);
|
||||
Set set1(alloc1);
|
||||
|
||||
set1.insert({1, 2, 3});
|
||||
|
||||
int64_t bytes_used2 = 0;
|
||||
Alloc alloc2(&bytes_used2);
|
||||
Set set2(set1, alloc2);
|
||||
|
||||
EXPECT_THAT(set1, ElementsAre(1, 2, 3));
|
||||
EXPECT_THAT(set2, ElementsAre(1, 2, 3));
|
||||
EXPECT_GT(bytes_used1, set1.size() * sizeof(int));
|
||||
EXPECT_EQ(bytes_used1, bytes_used2);
|
||||
}
|
||||
|
||||
TEST(Btree, AllocMoveConstructor_SameAlloc) {
|
||||
using Alloc = CountingAllocator<int>;
|
||||
using Set = absl::btree_set<int, std::less<int>, Alloc>;
|
||||
int64_t bytes_used = 0;
|
||||
Alloc alloc(&bytes_used);
|
||||
Set set1(alloc);
|
||||
|
||||
set1.insert({1, 2, 3});
|
||||
|
||||
const int64_t original_bytes_used = bytes_used;
|
||||
EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
|
||||
|
||||
Set set2(std::move(set1), alloc);
|
||||
|
||||
EXPECT_THAT(set2, ElementsAre(1, 2, 3));
|
||||
EXPECT_EQ(bytes_used, original_bytes_used);
|
||||
}
|
||||
|
||||
TEST(Btree, AllocMoveConstructor_DifferentAlloc) {
|
||||
using Alloc = CountingAllocator<int>;
|
||||
using Set = absl::btree_set<int, std::less<int>, Alloc>;
|
||||
int64_t bytes_used1 = 0;
|
||||
Alloc alloc1(&bytes_used1);
|
||||
Set set1(alloc1);
|
||||
|
||||
set1.insert({1, 2, 3});
|
||||
|
||||
const int64_t original_bytes_used = bytes_used1;
|
||||
EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
|
||||
|
||||
int64_t bytes_used2 = 0;
|
||||
Alloc alloc2(&bytes_used2);
|
||||
Set set2(std::move(set1), alloc2);
|
||||
|
||||
EXPECT_THAT(set2, ElementsAre(1, 2, 3));
|
||||
// We didn't free these bytes allocated by `set1` yet.
|
||||
EXPECT_EQ(bytes_used1, original_bytes_used);
|
||||
EXPECT_EQ(bytes_used2, original_bytes_used);
|
||||
}
|
||||
|
||||
bool IntCmp(const int a, const int b) { return a < b; }
|
||||
|
||||
TEST(Btree, SupportsFunctionPtrComparator) {
|
||||
absl::btree_set<int, decltype(IntCmp) *> set(IntCmp);
|
||||
set.insert({1, 2, 3});
|
||||
EXPECT_THAT(set, ElementsAre(1, 2, 3));
|
||||
EXPECT_TRUE(set.key_comp()(1, 2));
|
||||
EXPECT_TRUE(set.value_comp()(1, 2));
|
||||
|
||||
absl::btree_map<int, int, decltype(IntCmp) *> map(&IntCmp);
|
||||
map[1] = 1;
|
||||
EXPECT_THAT(map, ElementsAre(Pair(1, 1)));
|
||||
EXPECT_TRUE(map.key_comp()(1, 2));
|
||||
EXPECT_TRUE(map.value_comp()(std::make_pair(1, 1), std::make_pair(2, 2)));
|
||||
}
|
||||
|
||||
template <typename Compare>
|
||||
struct TransparentPassThroughComp {
|
||||
using is_transparent = void;
|
||||
|
||||
// This will fail compilation if we attempt a comparison that Compare does not
|
||||
// support, and the failure will happen inside the function implementation so
|
||||
// it can't be avoided by using SFINAE on this comparator.
|
||||
template <typename T, typename U>
|
||||
bool operator()(const T &lhs, const U &rhs) const {
|
||||
return Compare()(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Btree,
|
||||
SupportsTransparentComparatorThatDoesNotImplementAllVisibleOperators) {
|
||||
absl::btree_set<MultiKey, TransparentPassThroughComp<MultiKeyComp>> set;
|
||||
set.insert(MultiKey{1, 2});
|
||||
EXPECT_TRUE(set.contains(1));
|
||||
}
|
||||
|
||||
TEST(Btree, ConstructImplicitlyWithUnadaptedComparator) {
|
||||
absl::btree_set<MultiKey, MultiKeyComp> set = {{}, MultiKeyComp{}};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace container_internal
|
||||
ABSL_NAMESPACE_END
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include "absl/container/btree_map.h"
|
||||
#include "absl/container/btree_set.h"
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/strings/cord.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
namespace absl {
|
||||
@ -100,6 +101,16 @@ struct Generator<std::string> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Generator<Cord> {
|
||||
int maxval;
|
||||
explicit Generator(int m) : maxval(m) {}
|
||||
Cord operator()(int i) const {
|
||||
char buf[16];
|
||||
return Cord(GenerateDigits(buf, i, maxval));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct Generator<std::pair<T, U> > {
|
||||
Generator<typename remove_pair_const<T>::type> tgen;
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/algorithm/algorithm.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/dynamic_annotations.h"
|
||||
#include "absl/base/internal/throw_delegate.h"
|
||||
#include "absl/base/macros.h"
|
||||
@ -72,11 +73,6 @@ constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
|
||||
// uninitialized (e.g. int, int[4], double), and others default-constructed.
|
||||
// This matches the behavior of c-style arrays and `std::array`, but not
|
||||
// `std::vector`.
|
||||
//
|
||||
// Note that `FixedArray` does not provide a public allocator; if it requires a
|
||||
// heap allocation, it will do so with global `::operator new[]()` and
|
||||
// `::operator delete[]()`, even if T provides class-scope overrides for these
|
||||
// operators.
|
||||
template <typename T, size_t N = kFixedArrayUseDefault,
|
||||
typename A = std::allocator<T>>
|
||||
class FixedArray {
|
||||
@ -106,13 +102,13 @@ class FixedArray {
|
||||
|
||||
public:
|
||||
using allocator_type = typename AllocatorTraits::allocator_type;
|
||||
using value_type = typename allocator_type::value_type;
|
||||
using pointer = typename allocator_type::pointer;
|
||||
using const_pointer = typename allocator_type::const_pointer;
|
||||
using reference = typename allocator_type::reference;
|
||||
using const_reference = typename allocator_type::const_reference;
|
||||
using size_type = typename allocator_type::size_type;
|
||||
using difference_type = typename allocator_type::difference_type;
|
||||
using value_type = typename AllocatorTraits::value_type;
|
||||
using pointer = typename AllocatorTraits::pointer;
|
||||
using const_pointer = typename AllocatorTraits::const_pointer;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using size_type = typename AllocatorTraits::size_type;
|
||||
using difference_type = typename AllocatorTraits::difference_type;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
@ -217,7 +213,7 @@ class FixedArray {
|
||||
// Returns a reference the ith element of the fixed array.
|
||||
// REQUIRES: 0 <= i < size()
|
||||
reference operator[](size_type i) {
|
||||
assert(i < size());
|
||||
ABSL_HARDENING_ASSERT(i < size());
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
@ -225,14 +221,14 @@ class FixedArray {
|
||||
// ith element of the fixed array.
|
||||
// REQUIRES: 0 <= i < size()
|
||||
const_reference operator[](size_type i) const {
|
||||
assert(i < size());
|
||||
ABSL_HARDENING_ASSERT(i < size());
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
// FixedArray::at
|
||||
//
|
||||
// Bounds-checked access. Returns a reference to the ith element of the
|
||||
// fiexed array, or throws std::out_of_range
|
||||
// Bounds-checked access. Returns a reference to the ith element of the fixed
|
||||
// array, or throws std::out_of_range
|
||||
reference at(size_type i) {
|
||||
if (ABSL_PREDICT_FALSE(i >= size())) {
|
||||
base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
|
||||
@ -252,20 +248,32 @@ class FixedArray {
|
||||
// FixedArray::front()
|
||||
//
|
||||
// Returns a reference to the first element of the fixed array.
|
||||
reference front() { return *begin(); }
|
||||
reference front() {
|
||||
ABSL_HARDENING_ASSERT(!empty());
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
// Overload of FixedArray::front() to return a reference to the first element
|
||||
// of a fixed array of const values.
|
||||
const_reference front() const { return *begin(); }
|
||||
const_reference front() const {
|
||||
ABSL_HARDENING_ASSERT(!empty());
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
// FixedArray::back()
|
||||
//
|
||||
// Returns a reference to the last element of the fixed array.
|
||||
reference back() { return *(end() - 1); }
|
||||
reference back() {
|
||||
ABSL_HARDENING_ASSERT(!empty());
|
||||
return data()[size() - 1];
|
||||
}
|
||||
|
||||
// Overload of FixedArray::back() to return a reference to the last element
|
||||
// of a fixed array of const values.
|
||||
const_reference back() const { return *(end() - 1); }
|
||||
const_reference back() const {
|
||||
ABSL_HARDENING_ASSERT(!empty());
|
||||
return data()[size() - 1];
|
||||
}
|
||||
|
||||
// FixedArray::begin()
|
||||
//
|
||||
@ -410,15 +418,15 @@ class FixedArray {
|
||||
void AnnotateConstruct(size_type n);
|
||||
void AnnotateDestruct(size_type n);
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
|
||||
void* RedzoneBegin() { return &redzone_begin_; }
|
||||
void* RedzoneEnd() { return &redzone_end_ + 1; }
|
||||
#endif // ADDRESS_SANITIZER
|
||||
#endif // ABSL_HAVE_ADDRESS_SANITIZER
|
||||
|
||||
private:
|
||||
ADDRESS_SANITIZER_REDZONE(redzone_begin_);
|
||||
ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_);
|
||||
alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
|
||||
ADDRESS_SANITIZER_REDZONE(redzone_end_);
|
||||
ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_);
|
||||
};
|
||||
|
||||
class EmptyInlinedStorage {
|
||||
@ -491,22 +499,26 @@ constexpr typename FixedArray<T, N, A>::size_type
|
||||
template <typename T, size_t N, typename A>
|
||||
void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateConstruct(
|
||||
typename FixedArray<T, N, A>::size_type n) {
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
|
||||
if (!n) return;
|
||||
ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n);
|
||||
ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), RedzoneBegin());
|
||||
#endif // ADDRESS_SANITIZER
|
||||
ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(),
|
||||
data() + n);
|
||||
ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(),
|
||||
RedzoneBegin());
|
||||
#endif // ABSL_HAVE_ADDRESS_SANITIZER
|
||||
static_cast<void>(n); // Mark used when not in asan mode
|
||||
}
|
||||
|
||||
template <typename T, size_t N, typename A>
|
||||
void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateDestruct(
|
||||
typename FixedArray<T, N, A>::size_type n) {
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
|
||||
if (!n) return;
|
||||
ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd());
|
||||
ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), data());
|
||||
#endif // ADDRESS_SANITIZER
|
||||
ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n,
|
||||
RedzoneEnd());
|
||||
ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(),
|
||||
data());
|
||||
#endif // ABSL_HAVE_ADDRESS_SANITIZER
|
||||
static_cast<void>(n); // Mark used when not in asan mode
|
||||
}
|
||||
ABSL_NAMESPACE_END
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user