parent
fa1c832514
commit
61dd9043e1
1113 changed files with 11445 additions and 45183 deletions
@ -0,0 +1,41 @@ |
||||
--- |
||||
name: Bug report |
||||
about: Create a report to help us improve |
||||
title: '' |
||||
labels: 'bug' |
||||
assignees: '' |
||||
--- |
||||
|
||||
**Describe the bug** |
||||
|
||||
Include a clear and concise description of what the problem is, including what |
||||
you expected to happen, and what actually happened. |
||||
|
||||
**Steps to reproduce the bug** |
||||
|
||||
It's important that we are able to reproduce the problem that you are |
||||
experiencing. Please provide all code and relevant steps to reproduce the |
||||
problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links |
||||
to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the |
||||
problem are also helpful. |
||||
|
||||
**What version of Abseil are you using?** |
||||
|
||||
**What operating system and version are you using** |
||||
|
||||
If you are using a Linux distribution please include the name and version of the |
||||
distribution as well. |
||||
|
||||
**What compiler and version are you using?** |
||||
|
||||
Please include the output of `gcc -v` or `clang -v`, or the equivalent for your |
||||
compiler. |
||||
|
||||
**What build system are you using?** |
||||
|
||||
Please include the output of `bazel --version` or `cmake --version`, or the |
||||
equivalent for your build system. |
||||
|
||||
**Additional context** |
||||
|
||||
Add any other context about the problem here. |
@ -0,0 +1,7 @@ |
||||
--- |
||||
name: Question |
||||
about: Have a question? Ask us anything! :-) |
||||
title: '' |
||||
labels: 'question' |
||||
assignees: '' |
||||
--- |
@ -0,0 +1 @@ |
||||
blank_issues_enables: true |
@ -0,0 +1,15 @@ |
||||
# Ignore all bazel-* symlinks. |
||||
/bazel-* |
||||
# Ignore Bazel verbose explanations |
||||
--verbose_explanations |
||||
# Ignore CMake usual build directory |
||||
build |
||||
# Ignore Vim files |
||||
*.swp |
||||
# Ignore QtCreator Project file |
||||
CMakeLists.txt.user |
||||
# Ignore VS Code files |
||||
.vscode/* |
||||
# Ignore generated python artifacts |
||||
*.pyc |
||||
copts/__pycache__/ |
@ -0,0 +1,20 @@ |
||||
include(GNUInstallDirs) |
||||
|
||||
# absl_VERSION is only set if we are an LTS release being installed, in which |
||||
# case it may be into a system directory and so we need to make subdirectories |
||||
# for each installed version of Abseil. This mechanism is implemented in |
||||
# Abseil's internal Copybara (https://github.com/google/copybara) workflows and |
||||
# isn't visible in the CMake buildsystem itself. |
||||
|
||||
if(absl_VERSION) |
||||
set(ABSL_SUBDIR "${PROJECT_NAME}_${PROJECT_VERSION}") |
||||
set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}/${ABSL_SUBDIR}") |
||||
set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${ABSL_SUBDIR}") |
||||
set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/${ABSL_SUBDIR}") |
||||
set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}/${ABSL_SUBDIR}") |
||||
else() |
||||
set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}") |
||||
set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") |
||||
set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") |
||||
set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}") |
||||
endif() |
@ -0,0 +1,16 @@ |
||||
# Long Term Support (LTS) Branches |
||||
|
||||
This repository contains periodic snapshots of the Abseil codebase that are |
||||
Long Term Support (LTS) branches. An LTS branch allows you to use a known |
||||
version of Abseil without interfering with other projects which may also, in |
||||
turn, use Abseil. (For more information about our releases, see the |
||||
[Abseil Release Management](https://abseil.io/about/releases) guide.) |
||||
|
||||
## LTS Branches |
||||
|
||||
The following lists LTS branches and the dates on which they have been released: |
||||
|
||||
* [LTS Branch December 18, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_12_18/) |
||||
* [LTS Branch June 20, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_06_20/) |
||||
* [LTS Branch August 8, 2019](https://github.com/abseil/abseil-cpp/tree/lts_2019_08_08/) |
||||
* [LTS Branch February 25, 2020](https://github.com/abseil/abseil-cpp/tree/lts_2020_02_25/) |
@ -0,0 +1,219 @@ |
||||
// Copyright 2018 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_BITS_H_ |
||||
#define ABSL_BASE_INTERNAL_BITS_H_ |
||||
|
||||
// This file contains bitwise ops which are implementation details of various
|
||||
// absl libraries.
|
||||
|
||||
#include <cstdint> |
||||
|
||||
#include "absl/base/config.h" |
||||
|
||||
// Clang on Windows has __builtin_clzll; otherwise we need to use the
|
||||
// windows intrinsic functions.
|
||||
#if defined(_MSC_VER) && !defined(__clang__) |
||||
#include <intrin.h> |
||||
#if defined(_M_X64) |
||||
#pragma intrinsic(_BitScanReverse64) |
||||
#pragma intrinsic(_BitScanForward64) |
||||
#endif |
||||
#pragma intrinsic(_BitScanReverse) |
||||
#pragma intrinsic(_BitScanForward) |
||||
#endif |
||||
|
||||
#include "absl/base/attributes.h" |
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__) |
||||
// We can achieve something similar to attribute((always_inline)) with MSVC by
|
||||
// using the __forceinline keyword, however this is not perfect. MSVC is
|
||||
// much less aggressive about inlining, and even with the __forceinline keyword.
|
||||
#define ABSL_BASE_INTERNAL_FORCEINLINE __forceinline |
||||
#else |
||||
// Use default attribute inline.
|
||||
#define ABSL_BASE_INTERNAL_FORCEINLINE inline ABSL_ATTRIBUTE_ALWAYS_INLINE |
||||
#endif |
||||
|
||||
|
||||
namespace absl { |
||||
ABSL_NAMESPACE_BEGIN |
||||
namespace base_internal { |
||||
|
||||
ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64Slow(uint64_t n) { |
||||
int zeroes = 60; |
||||
if (n >> 32) { |
||||
zeroes -= 32; |
||||
n >>= 32; |
||||
} |
||||
if (n >> 16) { |
||||
zeroes -= 16; |
||||
n >>= 16; |
||||
} |
||||
if (n >> 8) { |
||||
zeroes -= 8; |
||||
n >>= 8; |
||||
} |
||||
if (n >> 4) { |
||||
zeroes -= 4; |
||||
n >>= 4; |
||||
} |
||||
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes; |
||||
} |
||||
|
||||
ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) { |
||||
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_X64) |
||||
// MSVC does not have __buitin_clzll. Use _BitScanReverse64.
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if (_BitScanReverse64(&result, n)) { |
||||
return 63 - result; |
||||
} |
||||
return 64; |
||||
#elif defined(_MSC_VER) && !defined(__clang__) |
||||
// MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if ((n >> 32) && |
||||
_BitScanReverse(&result, static_cast<unsigned long>(n >> 32))) { |
||||
return 31 - result; |
||||
} |
||||
if (_BitScanReverse(&result, static_cast<unsigned long>(n))) { |
||||
return 63 - result; |
||||
} |
||||
return 64; |
||||
#elif defined(__GNUC__) || defined(__clang__) |
||||
// Use __builtin_clzll, which uses the following instructions:
|
||||
// x86: bsr
|
||||
// ARM64: clz
|
||||
// PPC: cntlzd
|
||||
static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
|
||||
"__builtin_clzll does not take 64-bit arg"); |
||||
|
||||
// Handle 0 as a special case because __builtin_clzll(0) is undefined.
|
||||
if (n == 0) { |
||||
return 64; |
||||
} |
||||
return __builtin_clzll(n); |
||||
#else |
||||
return CountLeadingZeros64Slow(n); |
||||
#endif |
||||
} |
||||
|
||||
ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32Slow(uint64_t n) { |
||||
int zeroes = 28; |
||||
if (n >> 16) { |
||||
zeroes -= 16; |
||||
n >>= 16; |
||||
} |
||||
if (n >> 8) { |
||||
zeroes -= 8; |
||||
n >>= 8; |
||||
} |
||||
if (n >> 4) { |
||||
zeroes -= 4; |
||||
n >>= 4; |
||||
} |
||||
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes; |
||||
} |
||||
|
||||
ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32(uint32_t n) { |
||||
#if defined(_MSC_VER) && !defined(__clang__) |
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if (_BitScanReverse(&result, n)) { |
||||
return 31 - result; |
||||
} |
||||
return 32; |
||||
#elif defined(__GNUC__) || defined(__clang__) |
||||
// Use __builtin_clz, which uses the following instructions:
|
||||
// x86: bsr
|
||||
// ARM64: clz
|
||||
// PPC: cntlzd
|
||||
static_assert(sizeof(int) == sizeof(n), |
||||
"__builtin_clz does not take 32-bit arg"); |
||||
|
||||
// Handle 0 as a special case because __builtin_clz(0) is undefined.
|
||||
if (n == 0) { |
||||
return 32; |
||||
} |
||||
return __builtin_clz(n); |
||||
#else |
||||
return CountLeadingZeros32Slow(n); |
||||
#endif |
||||
} |
||||
|
||||
ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64Slow(uint64_t n) { |
||||
int c = 63; |
||||
n &= ~n + 1; |
||||
if (n & 0x00000000FFFFFFFF) c -= 32; |
||||
if (n & 0x0000FFFF0000FFFF) c -= 16; |
||||
if (n & 0x00FF00FF00FF00FF) c -= 8; |
||||
if (n & 0x0F0F0F0F0F0F0F0F) c -= 4; |
||||
if (n & 0x3333333333333333) c -= 2; |
||||
if (n & 0x5555555555555555) c -= 1; |
||||
return c; |
||||
} |
||||
|
||||
ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64(uint64_t n) { |
||||
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_X64) |
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
_BitScanForward64(&result, n); |
||||
return result; |
||||
#elif defined(_MSC_VER) && !defined(__clang__) |
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if (static_cast<uint32_t>(n) == 0) { |
||||
_BitScanForward(&result, static_cast<unsigned long>(n >> 32)); |
||||
return result + 32; |
||||
} |
||||
_BitScanForward(&result, static_cast<unsigned long>(n)); |
||||
return result; |
||||
#elif defined(__GNUC__) || defined(__clang__) |
||||
static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
|
||||
"__builtin_ctzll does not take 64-bit arg"); |
||||
return __builtin_ctzll(n); |
||||
#else |
||||
return CountTrailingZerosNonZero64Slow(n); |
||||
#endif |
||||
} |
||||
|
||||
ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32Slow(uint32_t n) { |
||||
int c = 31; |
||||
n &= ~n + 1; |
||||
if (n & 0x0000FFFF) c -= 16; |
||||
if (n & 0x00FF00FF) c -= 8; |
||||
if (n & 0x0F0F0F0F) c -= 4; |
||||
if (n & 0x33333333) c -= 2; |
||||
if (n & 0x55555555) c -= 1; |
||||
return c; |
||||
} |
||||
|
||||
ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32(uint32_t n) { |
||||
#if defined(_MSC_VER) && !defined(__clang__) |
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
_BitScanForward(&result, n); |
||||
return result; |
||||
#elif defined(__GNUC__) || defined(__clang__) |
||||
static_assert(sizeof(int) == sizeof(n), |
||||
"__builtin_ctz does not take 32-bit arg"); |
||||
return __builtin_ctz(n); |
||||
#else |
||||
return CountTrailingZerosNonZero32Slow(n); |
||||
#endif |
||||
} |
||||
|
||||
#undef ABSL_BASE_INTERNAL_FORCEINLINE |
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END |
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_BITS_H_
|
@ -0,0 +1,97 @@ |
||||
// Copyright 2018 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/bits.h" |
||||
|
||||
#include "gtest/gtest.h" |
||||
|
||||
namespace { |
||||
|
||||
int CLZ64(uint64_t n) { |
||||
int fast = absl::base_internal::CountLeadingZeros64(n); |
||||
int slow = absl::base_internal::CountLeadingZeros64Slow(n); |
||||
EXPECT_EQ(fast, slow) << n; |
||||
return fast; |
||||
} |
||||
|
||||
TEST(BitsTest, CountLeadingZeros64) { |
||||
EXPECT_EQ(64, CLZ64(uint64_t{})); |
||||
EXPECT_EQ(0, CLZ64(~uint64_t{})); |
||||
|
||||
for (int index = 0; index < 64; index++) { |
||||
uint64_t x = static_cast<uint64_t>(1) << index; |
||||
const auto cnt = 63 - index; |
||||
ASSERT_EQ(cnt, CLZ64(x)) << index; |
||||
ASSERT_EQ(cnt, CLZ64(x + x - 1)) << index; |
||||
} |
||||
} |
||||
|
||||
int CLZ32(uint32_t n) { |
||||
int fast = absl::base_internal::CountLeadingZeros32(n); |
||||
int slow = absl::base_internal::CountLeadingZeros32Slow(n); |
||||
EXPECT_EQ(fast, slow) << n; |
||||
return fast; |
||||
} |
||||
|
||||
TEST(BitsTest, CountLeadingZeros32) { |
||||
EXPECT_EQ(32, CLZ32(uint32_t{})); |
||||
EXPECT_EQ(0, CLZ32(~uint32_t{})); |
||||
|
||||
for (int index = 0; index < 32; index++) { |
||||
uint32_t x = static_cast<uint32_t>(1) << index; |
||||
const auto cnt = 31 - index; |
||||
ASSERT_EQ(cnt, CLZ32(x)) << index; |
||||
ASSERT_EQ(cnt, CLZ32(x + x - 1)) << index; |
||||
ASSERT_EQ(CLZ64(x), CLZ32(x) + 32); |
||||
} |
||||
} |
||||
|
||||
int CTZ64(uint64_t n) { |
||||
int fast = absl::base_internal::CountTrailingZerosNonZero64(n); |
||||
int slow = absl::base_internal::CountTrailingZerosNonZero64Slow(n); |
||||
EXPECT_EQ(fast, slow) << n; |
||||
return fast; |
||||
} |
||||
|
||||
TEST(BitsTest, CountTrailingZerosNonZero64) { |
||||
EXPECT_EQ(0, CTZ64(~uint64_t{})); |
||||
|
||||
for (int index = 0; index < 64; index++) { |
||||
uint64_t x = static_cast<uint64_t>(1) << index; |
||||
const auto cnt = index; |
||||
ASSERT_EQ(cnt, CTZ64(x)) << index; |
||||
ASSERT_EQ(cnt, CTZ64(~(x - 1))) << index; |
||||
} |
||||
} |
||||
|
||||
int CTZ32(uint32_t n) { |
||||
int fast = absl::base_internal::CountTrailingZerosNonZero32(n); |
||||
int slow = absl::base_internal::CountTrailingZerosNonZero32Slow(n); |
||||
EXPECT_EQ(fast, slow) << n; |
||||
return fast; |
||||
} |
||||
|
||||
TEST(BitsTest, CountTrailingZerosNonZero32) { |
||||
EXPECT_EQ(0, CTZ32(~uint32_t{})); |
||||
|
||||
for (int index = 0; index < 32; index++) { |
||||
uint32_t x = static_cast<uint32_t>(1) << index; |
||||
const auto cnt = index; |
||||
ASSERT_EQ(cnt, CTZ32(x)) << index; |
||||
ASSERT_EQ(cnt, CTZ32(~(x - 1))) << index; |
||||
} |
||||
} |
||||
|
||||
|
||||
} // namespace
|
@ -1,138 +0,0 @@ |
||||
// Copyright 2022 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_PREFETCH_H_ |
||||
#define ABSL_BASE_INTERNAL_PREFETCH_H_ |
||||
|
||||
#include "absl/base/config.h" |
||||
|
||||
#ifdef __SSE__ |
||||
#include <xmmintrin.h> |
||||
#endif |
||||
|
||||
#if defined(_MSC_VER) && defined(ABSL_INTERNAL_HAVE_SSE) |
||||
#include <intrin.h> |
||||
#pragma intrinsic(_mm_prefetch) |
||||
#endif |
||||
|
||||
// Compatibility wrappers around __builtin_prefetch, to prefetch data
|
||||
// for read if supported by the toolchain.
|
||||
|
||||
// Move data into the cache before it is read, or "prefetch" it.
|
||||
//
|
||||
// The value of `addr` is the address of the memory to prefetch. If
|
||||
// the target and compiler support it, data prefetch instructions are
|
||||
// generated. If the prefetch is done some time before the memory is
|
||||
// read, it may be in the cache by the time the read occurs.
|
||||
//
|
||||
// The function names specify the temporal locality heuristic applied,
|
||||
// using the names of Intel prefetch instructions:
|
||||
//
|
||||
// T0 - high degree of temporal locality; data should be left in as
|
||||
// many levels of the cache possible
|
||||
// T1 - moderate degree of temporal locality
|
||||
// T2 - low degree of temporal locality
|
||||
// Nta - no temporal locality, data need not be left in the cache
|
||||
// after the read
|
||||
//
|
||||
// Incorrect or gratuitous use of these functions can degrade
|
||||
// performance, so use them only when representative benchmarks show
|
||||
// an improvement.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// absl::base_internal::PrefetchT0(addr);
|
||||
//
|
||||
// Currently, the different prefetch calls behave on some Intel
|
||||
// architectures as follows:
|
||||
//
|
||||
// SNB..SKL SKX
|
||||
// PrefetchT0() L1/L2/L3 L1/L2
|
||||
// PrefetchT1() L2/L3 L2
|
||||
// PrefetchT2() L2/L3 L2
|
||||
// PrefetchNta() L1/--/L3 L1*
|
||||
//
|
||||
// * On SKX PrefetchNta() will bring the line into L1 but will evict
|
||||
// from L3 cache. This might result in surprising behavior.
|
||||
//
|
||||
// SNB = Sandy Bridge, SKL = Skylake, SKX = Skylake Xeon.
|
||||
//
|
||||
namespace absl { |
||||
ABSL_NAMESPACE_BEGIN |
||||
namespace base_internal { |
||||
|
||||
void PrefetchT0(const void* addr); |
||||
void PrefetchT1(const void* addr); |
||||
void PrefetchT2(const void* addr); |
||||
void PrefetchNta(const void* addr); |
||||
|
||||
// Implementation details follow.
|
||||
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__) |
||||
|
||||
#define ABSL_INTERNAL_HAVE_PREFETCH 1 |
||||
|
||||
// See __builtin_prefetch:
|
||||
// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
|
||||
//
|
||||
// These functions speculatively load for read only. This is
|
||||
// safe for all currently supported platforms. However, prefetch for
|
||||
// store may have problems depending on the target platform.
|
||||
//
|
||||
inline void PrefetchT0(const void* addr) { |
||||
// Note: this uses prefetcht0 on Intel.
|
||||
__builtin_prefetch(addr, 0, 3); |
||||
} |
||||
inline void PrefetchT1(const void* addr) { |
||||
// Note: this uses prefetcht1 on Intel.
|
||||
__builtin_prefetch(addr, 0, 2); |
||||
} |
||||
inline void PrefetchT2(const void* addr) { |
||||
// Note: this uses prefetcht2 on Intel.
|
||||
__builtin_prefetch(addr, 0, 1); |
||||
} |
||||
inline void PrefetchNta(const void* addr) { |
||||
// Note: this uses prefetchtnta on Intel.
|
||||
__builtin_prefetch(addr, 0, 0); |
||||
} |
||||
|
||||
#elif defined(ABSL_INTERNAL_HAVE_SSE) |
||||
|
||||
#define ABSL_INTERNAL_HAVE_PREFETCH 1 |
||||
|
||||
inline void PrefetchT0(const void* addr) { |
||||
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0); |
||||
} |
||||
inline void PrefetchT1(const void* addr) { |
||||
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T1); |
||||
} |
||||
inline void PrefetchT2(const void* addr) { |
||||
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T2); |
||||
} |
||||
inline void PrefetchNta(const void* addr) { |
||||
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA); |
||||
} |
||||
|
||||
#else |
||||
inline void PrefetchT0(const void*) {} |
||||
inline void PrefetchT1(const void*) {} |
||||
inline void PrefetchT2(const void*) {} |
||||
inline void PrefetchNta(const void*) {} |
||||
#endif |
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END |
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_PREFETCH_H_
|
@ -1,43 +0,0 @@ |
||||
// Copyright 2022 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/prefetch.h" |
||||
|
||||
#include "gtest/gtest.h" |
||||
|
||||
namespace { |
||||
|
||||
int number = 42; |
||||
|
||||
TEST(Prefetch, TemporalLocalityNone) { |
||||
absl::base_internal::PrefetchNta(&number); |
||||
EXPECT_EQ(number, 42); |
||||
} |
||||
|
||||
TEST(Prefetch, TemporalLocalityLow) { |
||||
absl::base_internal::PrefetchT2(&number); |
||||
EXPECT_EQ(number, 42); |
||||
} |
||||
|
||||
TEST(Prefetch, TemporalLocalityMedium) { |
||||
absl::base_internal::PrefetchT1(&number); |
||||
EXPECT_EQ(number, 42); |
||||
} |
||||
|
||||
TEST(Prefetch, TemporalLocalityHigh) { |
||||
absl::base_internal::PrefetchT0(&number); |
||||
EXPECT_EQ(number, 42); |
||||
} |
||||
|
||||
} // namespace
|
@ -1,65 +0,0 @@ |
||||
# Copyright 2021 The Abseil Authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# https://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
load( |
||||
"//absl:copts/configure_copts.bzl", |
||||
"ABSL_DEFAULT_COPTS", |
||||
"ABSL_DEFAULT_LINKOPTS", |
||||
"ABSL_TEST_COPTS", |
||||
) |
||||
|
||||
package(default_visibility = ["//visibility:public"]) |
||||
|
||||
licenses(["notice"]) |
||||
|
||||
cc_library( |
||||
name = "cleanup_internal", |
||||
hdrs = ["internal/cleanup.h"], |
||||
copts = ABSL_DEFAULT_COPTS, |
||||
linkopts = ABSL_DEFAULT_LINKOPTS, |
||||
deps = [ |
||||
"//absl/base:base_internal", |
||||
"//absl/base:core_headers", |
||||
"//absl/utility", |
||||
], |
||||
) |
||||
|
||||
cc_library( |
||||
name = "cleanup", |
||||
hdrs = [ |
||||
"cleanup.h", |
||||
], |
||||
copts = ABSL_DEFAULT_COPTS, |
||||
linkopts = ABSL_DEFAULT_LINKOPTS, |
||||
deps = [ |
||||
":cleanup_internal", |
||||
"//absl/base:config", |
||||
"//absl/base:core_headers", |
||||
], |
||||
) |
||||
|
||||
cc_test( |
||||
name = "cleanup_test", |
||||
size = "small", |
||||
srcs = [ |
||||
"cleanup_test.cc", |
||||
], |
||||
copts = ABSL_TEST_COPTS, |
||||
deps = [ |
||||
":cleanup", |
||||
"//absl/base:config", |
||||
"//absl/utility", |
||||
"@com_google_googletest//:gtest_main", |
||||
], |
||||
) |
@ -1,56 +0,0 @@ |
||||
# Copyright 2021 The Abseil Authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# https://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# Internal-only target, do not depend on directly. |
||||
absl_cc_library( |
||||
NAME |
||||
cleanup_internal |
||||
HDRS |
||||
"internal/cleanup.h" |
||||
COPTS |
||||
${ABSL_DEFAULT_COPTS} |
||||
DEPS |
||||
absl::base_internal |
||||
absl::core_headers |
||||
absl::utility |
||||
PUBLIC |
||||
) |
||||
|
||||
absl_cc_library( |
||||
NAME |
||||
cleanup |
||||
HDRS |
||||
"cleanup.h" |
||||
COPTS |
||||
${ABSL_DEFAULT_COPTS} |
||||
DEPS |
||||
absl::cleanup_internal |
||||
absl::config |
||||
absl::core_headers |
||||
PUBLIC |
||||
) |
||||
|
||||
absl_cc_test( |
||||
NAME |
||||
cleanup_test |
||||
SRCS |
||||
"cleanup_test.cc" |
||||
COPTS |
||||
${ABSL_TEST_COPTS} |
||||
DEPS |
||||
absl::cleanup |
||||
absl::config |
||||
absl::utility |
||||
GTest::gmock_main |
||||
) |
@ -1,140 +0,0 @@ |
||||
// Copyright 2021 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: cleanup.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// `absl::Cleanup` implements the scope guard idiom, invoking the contained
|
||||
// callback's `operator()() &&` on scope exit.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ```
|
||||
// absl::Status CopyGoodData(const char* source_path, const char* sink_path) {
|
||||
// FILE* source_file = fopen(source_path, "r");
|
||||
// if (source_file == nullptr) {
|
||||
// return absl::NotFoundError("No source file"); // No cleanups execute
|
||||
// }
|
||||
//
|
||||
// // C++17 style cleanup using class template argument deduction
|
||||
// absl::Cleanup source_closer = [source_file] { fclose(source_file); };
|
||||
//
|
||||
// FILE* sink_file = fopen(sink_path, "w");
|
||||
// if (sink_file == nullptr) {
|
||||
// return absl::NotFoundError("No sink file"); // First cleanup executes
|
||||
// }
|
||||
//
|
||||
// // C++11 style cleanup using the factory function
|
||||
// auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); });
|
||||
//
|
||||
// Data data;
|
||||
// while (ReadData(source_file, &data)) {
|
||||
// if (!data.IsGood()) {
|
||||
// absl::Status result = absl::FailedPreconditionError("Read bad data");
|
||||
// return result; // Both cleanups execute
|
||||
// }
|
||||
// SaveData(sink_file, &data);
|
||||
// }
|
||||
//
|
||||
// return absl::OkStatus(); // Both cleanups execute
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Methods:
|
||||
//
|
||||
// `std::move(cleanup).Cancel()` will prevent the callback from executing.
|
||||
//
|
||||
// `std::move(cleanup).Invoke()` will execute the callback early, before
|
||||
// destruction, and prevent the callback from executing in the destructor.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// `absl::Cleanup` is not an interface type. It is only intended to be used
|
||||
// within the body of a function. It is not a value type and instead models a
|
||||
// control flow construct. Check out `defer` in Golang for something similar.
|
||||
|
||||
#ifndef ABSL_CLEANUP_CLEANUP_H_ |
||||
#define ABSL_CLEANUP_CLEANUP_H_ |
||||
|
||||
#include <utility> |
||||
|
||||
#include "absl/base/config.h" |
||||
#include "absl/base/macros.h" |
||||
#include "absl/cleanup/internal/cleanup.h" |
||||
|
||||
namespace absl { |
||||
ABSL_NAMESPACE_BEGIN |
||||
|
||||
template <typename Arg, typename Callback = void()> |
||||
class ABSL_MUST_USE_RESULT Cleanup final { |
||||
static_assert(cleanup_internal::WasDeduced<Arg>(), |
||||
"Explicit template parameters are not supported."); |
||||
|
||||
static_assert(cleanup_internal::ReturnsVoid<Callback>(), |
||||
"Callbacks that return values are not supported."); |
||||
|
||||
public: |
||||
Cleanup(Callback callback) : storage_(std::move(callback)) {} // NOLINT
|
||||
|
||||
Cleanup(Cleanup&& other) = default; |
||||
|
||||
void Cancel() && { |
||||
ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged()); |
||||
storage_.DestroyCallback(); |
||||
} |
||||
|
||||
void Invoke() && { |
||||
ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged()); |
||||
storage_.InvokeCallback(); |
||||
storage_.DestroyCallback(); |
||||
} |
||||
|
||||
~Cleanup() { |
||||
if (storage_.IsCallbackEngaged()) { |
||||
storage_.InvokeCallback(); |
||||
storage_.DestroyCallback(); |
||||
} |
||||
} |
||||
|
||||
private: |
||||
cleanup_internal::Storage<Callback> storage_; |
||||
}; |
||||
|
||||
// `absl::Cleanup c = /* callback */;`
|
||||
//
|
||||
// C++17 type deduction API for creating an instance of `absl::Cleanup`
|
||||
#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) |
||||
template <typename Callback> |
||||
Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>; |
||||
#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
|
||||
|
||||
// `auto c = absl::MakeCleanup(/* callback */);`
|
||||
//
|
||||
// C++11 type deduction API for creating an instance of `absl::Cleanup`
|
||||
template <typename... Args, typename Callback> |
||||
absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) { |
||||
static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(), |
||||
"Explicit template parameters are not supported."); |
||||
|
||||
static_assert(cleanup_internal::ReturnsVoid<Callback>(), |
||||
"Callbacks that return values are not supported."); |
||||
|
||||
return {std::move(callback)}; |
||||
} |
||||
|
||||
ABSL_NAMESPACE_END |
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_CLEANUP_CLEANUP_H_
|
@ -1,311 +0,0 @@ |
||||
// Copyright 2021 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/cleanup/cleanup.h" |
||||
|
||||
#include <functional> |
||||
#include <type_traits> |
||||
#include <utility> |
||||
|
||||
#include "gtest/gtest.h" |
||||
#include "absl/base/config.h" |
||||
#include "absl/utility/utility.h" |
||||
|
||||
namespace { |
||||
|
||||
using Tag = absl::cleanup_internal::Tag; |
||||
|
||||
template <typename Type1, typename Type2> |
||||
constexpr bool IsSame() { |
||||
return (std::is_same<Type1, Type2>::value); |
||||
} |
||||
|
||||
struct IdentityFactory { |
||||
template <typename Callback> |
||||
static Callback AsCallback(Callback callback) { |
||||
return Callback(std::move(callback)); |
||||
} |
||||
}; |
||||
|
||||
// `FunctorClass` is a type used for testing `absl::Cleanup`. It is intended to
|
||||
// represent users that make their own move-only callback types outside of
|
||||
// `std::function` and lambda literals.
|
||||
class FunctorClass { |
||||
using Callback = std::function<void()>; |
||||
|
||||
public: |
||||
explicit FunctorClass(Callback callback) : callback_(std::move(callback)) {} |
||||
|
||||
FunctorClass(FunctorClass&& other) |
||||
: callback_(absl::exchange(other.callback_, Callback())) {} |
||||
|
||||
FunctorClass(const FunctorClass&) = delete; |
||||
|
||||
FunctorClass& operator=(const FunctorClass&) = delete; |
||||
|
||||
FunctorClass& operator=(FunctorClass&&) = delete; |
||||
|
||||
void operator()() const& = delete; |
||||
|
||||
void operator()() && { |
||||
ASSERT_TRUE(callback_); |
||||
callback_(); |
||||
callback_ = nullptr; |
||||
} |
||||
|
||||
private: |
||||
Callback callback_; |
||||
}; |
||||
|
||||
struct FunctorClassFactory { |
||||
template <typename Callback> |
||||
static FunctorClass AsCallback(Callback callback) { |
||||
return FunctorClass(std::move(callback)); |
||||
} |
||||
}; |
||||
|
||||
struct StdFunctionFactory { |
||||
template <typename Callback> |
||||
static std::function<void()> AsCallback(Callback callback) { |
||||
return std::function<void()>(std::move(callback)); |
||||
} |
||||
}; |
||||
|
||||
using CleanupTestParams = |
||||
::testing::Types<IdentityFactory, FunctorClassFactory, StdFunctionFactory>; |
||||
template <typename> |
||||
struct CleanupTest : public ::testing::Test {}; |
||||
TYPED_TEST_SUITE(CleanupTest, CleanupTestParams); |
||||
|
||||
bool fn_ptr_called = false; |
||||
void FnPtrFunction() { fn_ptr_called = true; } |
||||
|
||||
TYPED_TEST(CleanupTest, FactoryProducesCorrectType) { |
||||
{ |
||||
auto callback = TypeParam::AsCallback([] {}); |
||||
auto cleanup = absl::MakeCleanup(std::move(callback)); |
||||
|
||||
static_assert( |
||||
IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(), |
||||
""); |
||||
} |
||||
|
||||
{ |
||||
auto cleanup = absl::MakeCleanup(&FnPtrFunction); |
||||
|
||||
static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(), |
||||
""); |
||||
} |
||||
|
||||
{ |
||||
auto cleanup = absl::MakeCleanup(FnPtrFunction); |
||||
|
||||
static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(), |
||||
""); |
||||
} |
||||
} |
||||
|
||||
#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) |
||||
TYPED_TEST(CleanupTest, CTADProducesCorrectType) { |
||||
{ |
||||
auto callback = TypeParam::AsCallback([] {}); |
||||
absl::Cleanup cleanup = std::move(callback); |
||||
|
||||
static_assert( |
||||
IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(), |
||||
""); |
||||
} |
||||
|
||||
{ |
||||
absl::Cleanup cleanup = &FnPtrFunction; |
||||
|
||||
static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(), |
||||
""); |
||||
} |
||||
|
||||
{ |
||||
absl::Cleanup cleanup = FnPtrFunction; |
||||
|
||||
static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(), |
||||
""); |
||||
} |
||||
} |
||||
|
||||
TYPED_TEST(CleanupTest, FactoryAndCTADProduceSameType) { |
||||
{ |
||||
auto callback = IdentityFactory::AsCallback([] {}); |
||||
auto factory_cleanup = absl::MakeCleanup(callback); |
||||
absl::Cleanup deduction_cleanup = callback; |
||||
|
||||
static_assert( |
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), ""); |
||||
} |
||||
|
||||
{ |
||||
auto factory_cleanup = |
||||
absl::MakeCleanup(FunctorClassFactory::AsCallback([] {})); |
||||
absl::Cleanup deduction_cleanup = FunctorClassFactory::AsCallback([] {}); |
||||
|
||||
static_assert( |
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), ""); |
||||
} |
||||
|
||||
{ |
||||
auto factory_cleanup = |
||||
absl::MakeCleanup(StdFunctionFactory::AsCallback([] {})); |
||||
absl::Cleanup deduction_cleanup = StdFunctionFactory::AsCallback([] {}); |
||||
|
||||
static_assert( |
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), ""); |
||||
} |
||||
|
||||
{ |
||||
auto factory_cleanup = absl::MakeCleanup(&FnPtrFunction); |
||||
absl::Cleanup deduction_cleanup = &FnPtrFunction; |
||||
|
||||
static_assert( |
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), ""); |
||||
} |
||||
|
||||
{ |
||||
auto factory_cleanup = absl::MakeCleanup(FnPtrFunction); |
||||
absl::Cleanup deduction_cleanup = FnPtrFunction; |
||||
|
||||
static_assert( |
||||
IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), ""); |
||||
} |
||||
} |
||||
#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
|
||||
|
||||
TYPED_TEST(CleanupTest, BasicUsage) { |
||||
bool called = false; |
||||
|
||||
{ |
||||
auto cleanup = |
||||
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; })); |
||||
EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
|
||||
} |
||||
|
||||
EXPECT_TRUE(called); // Destructor should invoke the callback
|
||||
} |
||||
|
||||
TYPED_TEST(CleanupTest, BasicUsageWithFunctionPointer) { |
||||
fn_ptr_called = false; |
||||
|
||||
{ |
||||
auto cleanup = absl::MakeCleanup(TypeParam::AsCallback(&FnPtrFunction)); |
||||
EXPECT_FALSE(fn_ptr_called); // Constructor shouldn't invoke the callback
|
||||
} |
||||
|
||||
EXPECT_TRUE(fn_ptr_called); // Destructor should invoke the callback
|
||||
} |
||||
|
||||
TYPED_TEST(CleanupTest, Cancel) { |
||||
bool called = false; |
||||
|
||||
{ |
||||
auto cleanup = |
||||
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; })); |
||||
EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
|
||||
|
||||
std::move(cleanup).Cancel(); |
||||
EXPECT_FALSE(called); // Cancel shouldn't invoke the callback
|
||||
} |
||||
|
||||
EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
|
||||
} |
||||
|
||||
TYPED_TEST(CleanupTest, Invoke) { |
||||
bool called = false; |
||||
|
||||
{ |
||||
auto cleanup = |
||||
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; })); |
||||
EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
|
||||
|
||||
std::move(cleanup).Invoke(); |
||||
EXPECT_TRUE(called); // Invoke should invoke the callback
|
||||
|
||||
called = false; // Reset tracker before destructor runs
|
||||
} |
||||
|
||||
EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
|
||||
} |
||||
|
||||
TYPED_TEST(CleanupTest, Move) { |
||||
bool called = false; |
||||
|
||||
{ |
||||
auto moved_from_cleanup = |
||||
absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; })); |
||||
EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
|
||||
|
||||
{ |
||||
auto moved_to_cleanup = std::move(moved_from_cleanup); |
||||
EXPECT_FALSE(called); // Move shouldn't invoke the callback
|
||||
} |
||||
|
||||
EXPECT_TRUE(called); // Destructor should invoke the callback
|
||||
|
||||
called = false; // Reset tracker before destructor runs
|
||||
} |
||||
|
||||
EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
|
||||
} |
||||
|
||||
int DestructionCount = 0; |
||||
|
||||
struct DestructionCounter { |
||||
void operator()() {} |
||||
|
||||
~DestructionCounter() { ++DestructionCount; } |
||||
}; |
||||
|
||||
TYPED_TEST(CleanupTest, DestructorDestroys) { |
||||
{ |
||||
auto cleanup = |
||||
absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter())); |
||||
DestructionCount = 0; |
||||
} |
||||
|
||||
EXPECT_EQ(DestructionCount, 1); // Engaged cleanup destroys
|
||||
} |
||||
|
||||
TYPED_TEST(CleanupTest, CancelDestroys) { |
||||
{ |
||||
auto cleanup = |
||||
absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter())); |
||||
DestructionCount = 0; |
||||
|
||||
std::move(cleanup).Cancel(); |
||||
EXPECT_EQ(DestructionCount, 1); // Cancel destroys
|
||||
} |
||||
|
||||
EXPECT_EQ(DestructionCount, 1); // Canceled cleanup does not double destroy
|
||||
} |
||||
|
||||
TYPED_TEST(CleanupTest, InvokeDestroys) { |
||||
{ |
||||
auto cleanup = |
||||
absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter())); |
||||
DestructionCount = 0; |
||||
|
||||
std::move(cleanup).Invoke(); |
||||
EXPECT_EQ(DestructionCount, 1); // Invoke destroys
|
||||
} |
||||
|
||||
EXPECT_EQ(DestructionCount, 1); // Invoked cleanup does not double destroy
|
||||
} |
||||
|
||||
} // namespace
|
@ -1,100 +0,0 @@ |
||||
// Copyright 2021 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_CLEANUP_INTERNAL_CLEANUP_H_ |
||||
#define ABSL_CLEANUP_INTERNAL_CLEANUP_H_ |
||||
|
||||
#include <new> |
||||
#include <type_traits> |
||||
#include <utility> |
||||
|
||||
#include "absl/base/internal/invoke.h" |
||||
#include "absl/base/macros.h" |
||||
#include "absl/base/thread_annotations.h" |
||||
#include "absl/utility/utility.h" |
||||
|
||||
namespace absl { |
||||
ABSL_NAMESPACE_BEGIN |
||||
|
||||
namespace cleanup_internal { |
||||
|
||||
struct Tag {}; |
||||
|
||||
template <typename Arg, typename... Args> |
||||
constexpr bool WasDeduced() { |
||||
return (std::is_same<cleanup_internal::Tag, Arg>::value) && |
||||
(sizeof...(Args) == 0); |
||||
} |
||||
|
||||
template <typename Callback> |
||||
constexpr bool ReturnsVoid() { |
||||
return (std::is_same<base_internal::invoke_result_t<Callback>, void>::value); |
||||
} |
||||
|
||||
template <typename Callback> |
||||
class Storage { |
||||
public: |
||||
Storage() = delete; |
||||
|
||||
explicit Storage(Callback callback) { |
||||
// Placement-new into a character buffer is used for eager destruction when
|
||||
// the cleanup is invoked or cancelled. To ensure this optimizes well, the
|
||||
// behavior is implemented locally instead of using an absl::optional.
|
||||
::new (GetCallbackBuffer()) Callback(std::move(callback)); |
||||
is_callback_engaged_ = true; |
||||
} |
||||
|
||||
Storage(Storage&& other) { |
||||
ABSL_HARDENING_ASSERT(other.IsCallbackEngaged()); |
||||
|
||||
::new (GetCallbackBuffer()) Callback(std::move(other.GetCallback())); |
||||
is_callback_engaged_ = true; |
||||
|
||||
other.DestroyCallback(); |
||||
} |
||||
|
||||
Storage(const Storage& other) = delete; |
||||
|
||||
Storage& operator=(Storage&& other) = delete; |
||||
|
||||
Storage& operator=(const Storage& other) = delete; |
||||
|
||||
void* GetCallbackBuffer() { return static_cast<void*>(+callback_buffer_); } |
||||
|
||||
Callback& GetCallback() { |
||||
return *reinterpret_cast<Callback*>(GetCallbackBuffer()); |
||||
} |
||||
|
||||
bool IsCallbackEngaged() const { return is_callback_engaged_; } |
||||
|
||||
void DestroyCallback() { |
||||
is_callback_engaged_ = false; |
||||
GetCallback().~Callback(); |
||||
} |
||||
|
||||
void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS { |
||||
std::move(GetCallback())(); |
||||
} |
||||
|
||||
private: |
||||
bool is_callback_engaged_; |
||||
alignas(Callback) char callback_buffer_[sizeof(Callback)]; |
||||
}; |
||||
|
||||
} // namespace cleanup_internal
|
||||
|
||||
ABSL_NAMESPACE_END |
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_CLEANUP_INTERNAL_CLEANUP_H_
|
@ -0,0 +1,38 @@ |
||||
# |
||||
# Copyright 2018 The Abseil Authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# https://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
"""Creates config_setting that allows selecting based on 'compiler' value.""" |
||||
|
||||
def create_llvm_config(name, visibility): |
||||
# The "do_not_use_tools_cpp_compiler_present" attribute exists to |
||||
# distinguish between older versions of Bazel that do not support |
||||
# "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do. |
||||
# In the future, the only way to select on the compiler will be through |
||||
# flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can |
||||
# be removed. |
||||
if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"): |
||||
native.config_setting( |
||||
name = name, |
||||
flag_values = { |
||||
"@bazel_tools//tools/cpp:compiler": "llvm", |
||||
}, |
||||
visibility = visibility, |
||||
) |
||||
else: |
||||
native.config_setting( |
||||
name = name, |
||||
values = {"compiler": "llvm"}, |
||||
visibility = visibility, |
||||
) |
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue