merge(3p/absl): subtree merge of Abseil up to e19260f
... notably, this includes Abseil's own StatusOr type, which conflicted with our implementation (that was taken from TensorFlow). Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
This commit is contained in:
parent
cc27324d02
commit
082c006c04
854 changed files with 11260 additions and 5296 deletions
8
third_party/abseil_cpp/absl/base/BUILD.bazel
vendored
8
third_party/abseil_cpp/absl/base/BUILD.bazel
vendored
|
|
@ -24,7 +24,7 @@ load(
|
|||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
name = "atomic_hook",
|
||||
|
|
@ -116,7 +116,6 @@ cc_library(
|
|||
cc_library(
|
||||
name = "dynamic_annotations",
|
||||
srcs = [
|
||||
"dynamic_annotations.cc",
|
||||
"internal/dynamic_annotations.h",
|
||||
],
|
||||
hdrs = [
|
||||
|
|
@ -126,6 +125,7 @@ cc_library(
|
|||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -161,6 +161,7 @@ cc_library(
|
|||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = select({
|
||||
"//absl:windows": [],
|
||||
"//absl:wasm": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}) + ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
|
|
@ -222,6 +223,7 @@ cc_library(
|
|||
"//absl:windows": [
|
||||
"-DEFAULTLIB:advapi32.lib",
|
||||
],
|
||||
"//absl:wasm": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}) + ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
|
|
@ -413,6 +415,7 @@ cc_library(
|
|||
deps = [
|
||||
":base",
|
||||
":base_internal",
|
||||
":config",
|
||||
":core_headers",
|
||||
"//absl/synchronization",
|
||||
"@com_google_googletest//:gtest",
|
||||
|
|
@ -429,6 +432,7 @@ cc_test(
|
|||
deps = [
|
||||
":base",
|
||||
":base_internal",
|
||||
":config",
|
||||
":core_headers",
|
||||
"//absl/synchronization",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ absl_cc_library(
|
|||
HDRS
|
||||
"dynamic_annotations.h"
|
||||
SRCS
|
||||
"dynamic_annotations.cc"
|
||||
"internal/dynamic_annotations.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
|
|
@ -385,6 +384,7 @@ absl_cc_library(
|
|||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::base
|
||||
absl::config
|
||||
absl::base_internal
|
||||
absl::core_headers
|
||||
absl::synchronization
|
||||
|
|
@ -403,6 +403,7 @@ absl_cc_test(
|
|||
DEPS
|
||||
absl::base
|
||||
absl::base_internal
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::synchronization
|
||||
gtest_main
|
||||
|
|
|
|||
134
third_party/abseil_cpp/absl/base/attributes.h
vendored
134
third_party/abseil_cpp/absl/base/attributes.h
vendored
|
|
@ -32,34 +32,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
|
||||
|
|
@ -234,7 +212,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 +220,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 +237,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 +249,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 +263,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 +273,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
|
||||
|
|
@ -594,6 +574,86 @@
|
|||
#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 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_CONST_INIT
|
||||
//
|
||||
// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will
|
||||
|
|
|
|||
2
third_party/abseil_cpp/absl/base/call_once.h
vendored
2
third_party/abseil_cpp/absl/base/call_once.h
vendored
|
|
@ -175,7 +175,7 @@ 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
|
||||
|
|
|
|||
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.");
|
||||
|
|
|
|||
72
third_party/abseil_cpp/absl/base/config.h
vendored
72
third_party/abseil_cpp/absl/base/config.h
vendored
|
|
@ -154,6 +154,12 @@ 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
|
||||
|
||||
// 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.
|
||||
|
|
@ -226,11 +232,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
|
||||
|
|
@ -312,15 +316,15 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
|
||||
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 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)
|
||||
#endif // ABSL_HAVE_FEATURE(cxx_exceptions)
|
||||
#else
|
||||
// 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 // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
|
||||
#endif // __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
|
||||
|
||||
// Handle remaining special cases and default to exceptions being supported.
|
||||
|
|
@ -360,7 +364,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||
defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
|
||||
defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
|
||||
defined(__ASYLO__)
|
||||
defined(__ASYLO__) || defined(__myriad2__)
|
||||
#define ABSL_HAVE_MMAP 1
|
||||
#endif
|
||||
|
||||
|
|
@ -470,9 +474,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
|
||||
|
|
@ -661,4 +665,50 @@ 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(MEMORY_SANITIZER)
|
||||
// The MEMORY_SANITIZER macro is deprecated but we will continue to honor it
|
||||
// for now.
|
||||
#define ABSL_HAVE_MEMORY_SANITIZER 1
|
||||
#elif defined(__SANITIZE_MEMORY__)
|
||||
#define ABSL_HAVE_MEMORY_SANITIZER 1
|
||||
#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer)
|
||||
#define ABSL_HAVE_MEMORY_SANITIZER 1
|
||||
#endif
|
||||
|
||||
// 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(THREAD_SANITIZER)
|
||||
// The THREAD_SANITIZER macro is deprecated but we will continue to honor it
|
||||
// for now.
|
||||
#define ABSL_HAVE_THREAD_SANITIZER 1
|
||||
#elif defined(__SANITIZE_THREAD__)
|
||||
#define ABSL_HAVE_THREAD_SANITIZER 1
|
||||
#elif ABSL_HAVE_FEATURE(thread_sanitizer)
|
||||
#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(ADDRESS_SANITIZER)
|
||||
// The ADDRESS_SANITIZER macro is deprecated but we will continue to honor it
|
||||
// for now.
|
||||
#define ABSL_HAVE_ADDRESS_SANITIZER 1
|
||||
#elif defined(__SANITIZE_ADDRESS__)
|
||||
#define ABSL_HAVE_ADDRESS_SANITIZER 1
|
||||
#elif ABSL_HAVE_FEATURE(address_sanitizer)
|
||||
#define ABSL_HAVE_ADDRESS_SANITIZER 1
|
||||
#endif
|
||||
|
||||
#endif // ABSL_BASE_CONFIG_H_
|
||||
|
|
|
|||
|
|
@ -1,72 +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"
|
||||
|
||||
// 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
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 && !defined(__native_client__)
|
||||
|
||||
extern "C" {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
#endif // DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
|
||||
|
|
@ -47,25 +47,19 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#ifdef __cplusplus
|
||||
#include "absl/base/macros.h"
|
||||
#endif
|
||||
|
||||
// TODO(rogeeff): Remove after the backward compatibility period.
|
||||
#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Decide which features are enabled
|
||||
// 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
|
||||
#else
|
||||
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
|
||||
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
|
||||
|
|
@ -85,25 +79,20 @@
|
|||
// 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 \
|
||||
ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
|
||||
#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
|
||||
|
||||
// Memory annotations are also made available to LLVM's Memory Sanitizer
|
||||
#if defined(MEMORY_SANITIZER) && defined(__has_feature) && \
|
||||
!defined(__native_client__)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
|
||||
#endif
|
||||
#endif // ABSL_HAVE_THREAD_SANITIZER
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
|
||||
|
|
@ -165,7 +154,7 @@
|
|||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that a linker initialized lock has been created at address `lock`.
|
||||
#ifdef THREAD_SANITIZER
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
|
||||
(__FILE__, __LINE__, lock)
|
||||
|
|
@ -243,7 +232,7 @@ ABSL_INTERNAL_END_EXTERN_C
|
|||
// -------------------------------------------------------------------------
|
||||
// Define memory annotations.
|
||||
|
||||
#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1
|
||||
#ifdef ABSL_HAVE_MEMORY_SANITIZER
|
||||
|
||||
#include <sanitizer/msan_interface.h>
|
||||
|
||||
|
|
@ -253,9 +242,10 @@ ABSL_INTERNAL_END_EXTERN_C
|
|||
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
__msan_allocated_memory(address, size)
|
||||
|
||||
#else // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0
|
||||
#else // !defined(ABSL_HAVE_MEMORY_SANITIZER)
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED == 1
|
||||
// TODO(rogeeff): remove this branch
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
|
|
@ -273,24 +263,24 @@ ABSL_INTERNAL_END_EXTERN_C
|
|||
|
||||
#endif
|
||||
|
||||
#endif // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
#endif // ABSL_HAVE_MEMORY_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END attributes.
|
||||
|
||||
#if ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 1
|
||||
#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 // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 0
|
||||
#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 // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
|
||||
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END annotations.
|
||||
|
|
@ -429,46 +419,35 @@ ABSL_NAMESPACE_END
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Return non-zero value if running under valgrind.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
int RunningOnValgrind();
|
||||
double ValgrindSlowdown();
|
||||
ABSL_INTERNAL_END_EXTERN_C
|
||||
#else
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
ABSL_DEPRECATED(
|
||||
"Don't use this interface. It is misleading and is being deleted.")
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline int RunningOnValgrind() { return 0; }
|
||||
ABSL_DEPRECATED(
|
||||
"Don't use this interface. It is misleading and is being deleted.")
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline double ValgrindSlowdown() { return 1.0; }
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
using absl::base_internal::RunningOnValgrind;
|
||||
using absl::base_internal::ValgrindSlowdown;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Address sanitizer annotations
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#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.
|
||||
|
|
@ -483,16 +462,15 @@ ABSL_INTERNAL_END_EXTERN_C
|
|||
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
|
||||
#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) // empty
|
||||
#define ABSL_ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
|
||||
|
||||
#endif // ADDRESS_SANITIZER
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -83,10 +83,11 @@ ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) {
|
|||
#elif defined(_MSC_VER) && !defined(__clang__)
|
||||
// MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if ((n >> 32) && _BitScanReverse(&result, n >> 32)) {
|
||||
if ((n >> 32) &&
|
||||
_BitScanReverse(&result, static_cast<unsigned long>(n >> 32))) {
|
||||
return 31 - result;
|
||||
}
|
||||
if (_BitScanReverse(&result, n)) {
|
||||
if (_BitScanReverse(&result, static_cast<unsigned long>(n))) {
|
||||
return 63 - result;
|
||||
}
|
||||
return 64;
|
||||
|
|
@ -170,10 +171,10 @@ ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64(uint64_t n) {
|
|||
#elif defined(_MSC_VER) && !defined(__clang__)
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if (static_cast<uint32_t>(n) == 0) {
|
||||
_BitScanForward(&result, n >> 32);
|
||||
_BitScanForward(&result, static_cast<unsigned long>(n >> 32));
|
||||
return result + 32;
|
||||
}
|
||||
_BitScanForward(&result, n);
|
||||
_BitScanForward(&result, static_cast<unsigned long>(n));
|
||||
return result;
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@
|
|||
|
||||
#if defined(__clang__) && !defined(SWIG)
|
||||
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
|
||||
#else
|
||||
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
|
||||
|
|
@ -84,19 +82,16 @@
|
|||
|
||||
// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \
|
||||
ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_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(MEMORY_SANITIZER) && defined(__has_feature) && \
|
||||
!defined(__native_client__)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#if defined(ABSL_HAVE_MEMORY_SANITIZER) && !defined(__native_client__)
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
|
||||
|
|
@ -162,7 +157,7 @@
|
|||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that a linker initialized lock has been created at address `lock`.
|
||||
#ifdef THREAD_SANITIZER
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
|
||||
(__FILE__, __LINE__, lock)
|
||||
|
|
@ -250,19 +245,19 @@
|
|||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END attributes.
|
||||
|
||||
#if ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 1
|
||||
#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 // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 0
|
||||
#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 // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
|
||||
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END annotations.
|
||||
|
|
@ -367,7 +362,7 @@
|
|||
// -------------------------------------------------------------------------
|
||||
// Address sanitizer annotations
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#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.
|
||||
|
|
@ -385,7 +380,7 @@
|
|||
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
|
||||
#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
|
||||
|
||||
#endif // ADDRESS_SANITIZER
|
||||
#endif // ABSL_HAVE_ADDRESS_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Undefine the macros intended only for this file.
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ TEST(ExponentialBiasedTest, InitializationModes) {
|
|||
ABSL_CONST_INIT static ExponentialBiased eb_static;
|
||||
EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0));
|
||||
|
||||
#if ABSL_HAVE_THREAD_LOCAL
|
||||
#ifdef ABSL_HAVE_THREAD_LOCAL
|
||||
thread_local ExponentialBiased eb_thread;
|
||||
EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0));
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
|
||||
// Explicitly #error out when not ABSL_LOW_LEVEL_WRITE_SUPPORTED, except for a
|
||||
// whitelisted set of platforms for which we expect not to be able to raw log.
|
||||
// selected set of platforms for which we expect not to be able to raw log.
|
||||
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
|
||||
absl::raw_logging_internal::LogPrefixHook>
|
||||
|
|
@ -227,7 +227,7 @@ bool RawLoggingFullySupported() {
|
|||
#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
|
||||
}
|
||||
|
||||
ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL
|
||||
absl::base_internal::AtomicHook<InternalLogFunction>
|
||||
internal_log_function(DefaultInternalLog);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,7 +174,7 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity,
|
|||
const char* file, int line,
|
||||
const std::string& message);
|
||||
|
||||
ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES extern base_internal::AtomicHook<
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook<
|
||||
InternalLogFunction>
|
||||
internal_log_function;
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,14 @@ class ABSL_LOCKABLE SpinLock {
|
|||
constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode)
|
||||
: lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {}
|
||||
|
||||
// For global SpinLock instances prefer trivial destructor when possible.
|
||||
// Default but non-trivial destructor in some build configurations causes an
|
||||
// extra static initializer.
|
||||
#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
|
||||
~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
|
||||
#else
|
||||
~SpinLock() = default;
|
||||
#endif
|
||||
|
||||
// Acquire this SpinLock.
|
||||
inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "absl/base/internal/strerror.h"
|
||||
|
||||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
|
|
@ -21,13 +22,13 @@
|
|||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#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);
|
||||
|
|
@ -35,15 +36,6 @@ const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
|
|||
if (rc == 0 && strncmp(buf, "Unknown error", buflen) == 0) *buf = '\0';
|
||||
return buf;
|
||||
#else
|
||||
#if defined(__GLIBC__) || defined(__APPLE__)
|
||||
// Use the BSD sys_errlist API provided by GNU glibc and others to
|
||||
// avoid any need to copy the message into the local buffer first.
|
||||
if (0 <= errnum && errnum < sys_nerr) {
|
||||
if (const char* p = sys_errlist[errnum]) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// 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);
|
||||
|
|
@ -57,9 +49,8 @@ const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string StrError(int errnum) {
|
||||
std::string StrErrorInternal(int errnum) {
|
||||
absl::base_internal::ErrnoSaver errno_saver;
|
||||
char buf[100];
|
||||
const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
|
||||
|
|
@ -70,6 +61,28 @@ std::string StrError(int errnum) {
|
|||
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) {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -20,15 +20,6 @@
|
|||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace {
|
||||
#if defined(__GLIBC__) || defined(__APPLE__)
|
||||
void BM_SysErrList(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(std::string(sys_errlist[ERANGE]));
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SysErrList);
|
||||
#endif
|
||||
|
||||
void BM_AbslStrError(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(absl::base_internal::StrError(ERANGE));
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
#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"
|
||||
|
|
@ -420,6 +422,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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -212,7 +211,9 @@ void ClearCurrentThreadIdentity();
|
|||
#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.
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -123,9 +123,7 @@ double UnscaledCycleClock::Frequency() {
|
|||
|
||||
#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.
|
||||
|
|
@ -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>
|
||||
|
|
@ -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_
|
||||
|
|
|
|||
90
third_party/abseil_cpp/absl/base/macros.h
vendored
90
third_party/abseil_cpp/absl/base/macros.h
vendored
|
|
@ -55,85 +55,6 @@ auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
|
|||
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
|
||||
|
|
@ -223,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_
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@
|
|||
// 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)
|
||||
|
|
@ -179,7 +179,7 @@
|
|||
#endif
|
||||
|
||||
// ABSL_INTERNAL_ASSUME(cond)
|
||||
// Informs the compiler than a condition is always true and that it can assume
|
||||
// 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().
|
||||
|
|
|
|||
|
|
@ -74,9 +74,8 @@ TEST(PredictTest, Pointer) {
|
|||
const int *null_intptr = nullptr;
|
||||
EXPECT_TRUE(ABSL_PREDICT_TRUE(good_intptr));
|
||||
EXPECT_FALSE(ABSL_PREDICT_TRUE(null_intptr));
|
||||
// The following doesn't compile:
|
||||
// EXPECT_TRUE(ABSL_PREDICT_FALSE(good_intptr));
|
||||
// EXPECT_FALSE(ABSL_PREDICT_FALSE(null_intptr));
|
||||
EXPECT_TRUE(ABSL_PREDICT_FALSE(good_intptr));
|
||||
EXPECT_FALSE(ABSL_PREDICT_FALSE(null_intptr));
|
||||
}
|
||||
|
||||
TEST(PredictTest, Optional) {
|
||||
|
|
@ -85,9 +84,8 @@ TEST(PredictTest, Optional) {
|
|||
absl::optional<bool> no_value;
|
||||
EXPECT_TRUE(ABSL_PREDICT_TRUE(has_value));
|
||||
EXPECT_FALSE(ABSL_PREDICT_TRUE(no_value));
|
||||
// The following doesn't compile:
|
||||
// EXPECT_TRUE(ABSL_PREDICT_FALSE(has_value));
|
||||
// EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
|
||||
EXPECT_TRUE(ABSL_PREDICT_FALSE(has_value));
|
||||
EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
|
||||
}
|
||||
|
||||
class ImplictlyConvertibleToBool {
|
||||
|
|
@ -124,9 +122,8 @@ TEST(PredictTest, ExplicitBoolConversion) {
|
|||
const ExplictlyConvertibleToBool is_false(false);
|
||||
if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
|
||||
// The following doesn't compile:
|
||||
// if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
|
||||
// if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
|
||||
if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Compiler Check
|
||||
// Toolchain Check
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// We support MSVC++ 14.0 update 2 and later.
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -103,6 +105,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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue