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:
Vincent Ambo 2020-11-21 14:43:54 +01:00
parent cc27324d02
commit 082c006c04
854 changed files with 11260 additions and 5296 deletions

View file

@ -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",

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.");

View file

@ -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_

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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.

View 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

View file

@ -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)...);
}

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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() {

View file

@ -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

View file

@ -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));

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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.

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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_

View file

@ -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();

View file

@ -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;

View file

@ -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) {

View file

@ -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_

View file

@ -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_

View file

@ -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().

View file

@ -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

View file

@ -41,7 +41,7 @@
#endif
// -----------------------------------------------------------------------------
// Compiler Check
// Toolchain Check
// -----------------------------------------------------------------------------
// We support MSVC++ 14.0 update 2 and later.

View file

@ -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();

View file

@ -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