Export of internal Abseil changes.
-- 5f1cf6547231f1b1daad6d1b785df6b0b999b3c9 by Samuel Benzaquen <sbenza@google.com>: Fix uninitialized member in the `iterator` class by using a union of the two possible states of the iterator. This silences a Wuninitialized warning in gcc>=7. PiperOrigin-RevId: 228175148 -- 98b4e3204c0ec3cfd4cb037e24d443ea4b63fc84 by CJ Johnson <johnsoncj@google.com>: Factors out the implementation of InlinedVector::swap(...) into a private member function PiperOrigin-RevId: 228173383 -- f1432ad3a8b05285c6d55bc4754cfae765485b7f by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 227891984 -- 03fc00c7a4efc6000e6d9125cb2e252bffda76fe by Andy Getzendanner <durandal@google.com>: Add a missing linebreak to a comment and markdownify two unordered lists. PiperOrigin-RevId: 227861389 -- 0d66c9afba4fc9aa52e61d9fb410e165018a7b48 by Abseil Team <absl-team@google.com>: Add an API to register a new source for the cycle clock. PiperOrigin-RevId: 227779218 -- 14d3f9b70c8818b8541e5fb2f6ca4c59d479de31 by Andy Getzendanner <durandal@google.com>: Correct a typo in a stripping marker. PiperOrigin-RevId: 227750014 -- 59df88740f4e315beb57a8772f8bcf7879440c74 by Matt Kulukundis <kfm@google.com>: Switch thread local handling to be more cross platform PiperOrigin-RevId: 227695133 -- 75deed5bfcb5c42534e933f104aa7d94e11e348d by Abseil Team <absl-team@google.com>: Rollback workaround toolchain bug for incorrect handling of thread_local in inline functions PiperOrigin-RevId: 227689133 -- 54994bf0afec026e6e0e7a199df0bbb4b7d9a4aa by Derek Mauro <dmauro@google.com>: Add -pthread to linkopts where it actually belongs, on the library that uses it. Fixes https://github.com/abseil/abseil-cpp/issues/240. PiperOrigin-RevId: 227612492 -- 893875f3536b7e0a1bad993aa6b2e083abb3b25a by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 227582833 -- 506c9b8e9002ca3389c7040473b68d4cbf94bdcc by Matt Kulukundis <kfm@google.com>: Workaround toolchain bug for incorrect handling of thread_local in inline functions PiperOrigin-RevId: 227561449 -- 29ee90d96dfe3114cf93f9bb92ea0cc9e768a407 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 227054634 GitOrigin-RevId: 5f1cf6547231f1b1daad6d1b785df6b0b999b3c9 Change-Id: Ibc90566d92ee6e0ad7e150f513ec7f5d22ec0a94
This commit is contained in:
parent
7ffbe09f3d
commit
b16aeb6756
41 changed files with 253 additions and 161 deletions
|
@ -89,6 +89,10 @@ cc_library(
|
||||||
"internal/low_level_alloc.h",
|
"internal/low_level_alloc.h",
|
||||||
],
|
],
|
||||||
copts = ABSL_DEFAULT_COPTS,
|
copts = ABSL_DEFAULT_COPTS,
|
||||||
|
linkopts = select({
|
||||||
|
"//absl:windows": [],
|
||||||
|
"//conditions:default": ["-pthread"],
|
||||||
|
}),
|
||||||
visibility = [
|
visibility = [
|
||||||
"//absl:__subpackages__",
|
"//absl:__subpackages__",
|
||||||
],
|
],
|
||||||
|
@ -142,6 +146,10 @@ cc_library(
|
||||||
"log_severity.h",
|
"log_severity.h",
|
||||||
],
|
],
|
||||||
copts = ABSL_DEFAULT_COPTS,
|
copts = ABSL_DEFAULT_COPTS,
|
||||||
|
linkopts = select({
|
||||||
|
"//absl:windows": [],
|
||||||
|
"//conditions:default": ["-pthread"],
|
||||||
|
}),
|
||||||
deps = [
|
deps = [
|
||||||
":base_internal",
|
":base_internal",
|
||||||
":config",
|
":config",
|
||||||
|
@ -423,10 +431,6 @@ cc_test(
|
||||||
size = "small",
|
size = "small",
|
||||||
srcs = ["internal/low_level_alloc_test.cc"],
|
srcs = ["internal/low_level_alloc_test.cc"],
|
||||||
copts = ABSL_TEST_COPTS,
|
copts = ABSL_TEST_COPTS,
|
||||||
linkopts = select({
|
|
||||||
"//absl:windows": [],
|
|
||||||
"//conditions:default": ["-pthread"],
|
|
||||||
}),
|
|
||||||
tags = ["no_test_ios_x86_64"],
|
tags = ["no_test_ios_x86_64"],
|
||||||
deps = [":malloc_internal"],
|
deps = [":malloc_internal"],
|
||||||
)
|
)
|
||||||
|
@ -436,10 +440,6 @@ cc_test(
|
||||||
size = "small",
|
size = "small",
|
||||||
srcs = ["internal/thread_identity_test.cc"],
|
srcs = ["internal/thread_identity_test.cc"],
|
||||||
copts = ABSL_TEST_COPTS,
|
copts = ABSL_TEST_COPTS,
|
||||||
linkopts = select({
|
|
||||||
"//absl:windows": [],
|
|
||||||
"//conditions:default": ["-pthread"],
|
|
||||||
}),
|
|
||||||
tags = [
|
tags = [
|
||||||
"no_test_wasm",
|
"no_test_wasm",
|
||||||
],
|
],
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "absl/base/internal/cycleclock.h"
|
#include "absl/base/internal/cycleclock.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <chrono> // NOLINT(build/c++11)
|
#include <chrono> // NOLINT(build/c++11)
|
||||||
|
|
||||||
#include "absl/base/internal/unscaledcycleclock.h"
|
#include "absl/base/internal/unscaledcycleclock.h"
|
||||||
|
@ -52,17 +53,26 @@ static constexpr int32_t kShift = 2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
|
static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
|
||||||
|
static std::atomic<CycleClockSourceFunc> cycle_clock_source;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int64_t CycleClock::Now() {
|
int64_t CycleClock::Now() {
|
||||||
return base_internal::UnscaledCycleClock::Now() >> kShift;
|
auto fn = cycle_clock_source.load(std::memory_order_relaxed);
|
||||||
|
if (fn == nullptr) {
|
||||||
|
return base_internal::UnscaledCycleClock::Now() >> kShift;
|
||||||
|
}
|
||||||
|
return fn() >> kShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
double CycleClock::Frequency() {
|
double CycleClock::Frequency() {
|
||||||
return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();
|
return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CycleClockSource::Register(CycleClockSourceFunc source) {
|
||||||
|
cycle_clock_source.store(source, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
int64_t CycleClock::Now() {
|
int64_t CycleClock::Now() {
|
||||||
|
|
|
@ -71,6 +71,20 @@ class CycleClock {
|
||||||
CycleClock& operator=(const CycleClock&) = delete;
|
CycleClock& operator=(const CycleClock&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using CycleClockSourceFunc = int64_t (*)();
|
||||||
|
|
||||||
|
class CycleClockSource {
|
||||||
|
private:
|
||||||
|
// CycleClockSource::Register()
|
||||||
|
//
|
||||||
|
// Register a function that provides an alternate source for the unscaled CPU
|
||||||
|
// cycle count value. The source function must be async signal safe, must not
|
||||||
|
// call CycleClock::Now(), and must have a frequency that matches that of the
|
||||||
|
// unscaled clock used by CycleClock. A nullptr value resets CycleClock to use
|
||||||
|
// the default source.
|
||||||
|
static void Register(CycleClockSourceFunc source);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace base_internal
|
} // namespace base_internal
|
||||||
} // namespace absl
|
} // namespace absl
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,17 @@
|
||||||
#define ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_
|
#define ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_
|
||||||
|
|
||||||
// This header defines two macros:
|
// This header defines two macros:
|
||||||
|
//
|
||||||
// If the platform supports thread-local storage:
|
// If the platform supports thread-local storage:
|
||||||
// ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a
|
//
|
||||||
// thread-local variable ABSL_PER_THREAD_TLS is 1
|
// * ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a
|
||||||
|
// thread-local variable
|
||||||
|
// * ABSL_PER_THREAD_TLS is 1
|
||||||
//
|
//
|
||||||
// Otherwise:
|
// Otherwise:
|
||||||
// ABSL_PER_THREAD_TLS_KEYWORD is empty
|
//
|
||||||
// ABSL_PER_THREAD_TLS is 0
|
// * ABSL_PER_THREAD_TLS_KEYWORD is empty
|
||||||
|
// * ABSL_PER_THREAD_TLS is 0
|
||||||
//
|
//
|
||||||
// Microsoft C supports thread-local storage.
|
// Microsoft C supports thread-local storage.
|
||||||
// GCC supports it if the appropriate version of glibc is available,
|
// GCC supports it if the appropriate version of glibc is available,
|
||||||
|
|
|
@ -123,12 +123,21 @@ cc_library(
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "counting_allocator",
|
||||||
|
testonly = 1,
|
||||||
|
hdrs = ["internal/counting_allocator.h"],
|
||||||
|
copts = ABSL_DEFAULT_COPTS,
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
cc_test(
|
cc_test(
|
||||||
name = "inlined_vector_test",
|
name = "inlined_vector_test",
|
||||||
srcs = ["inlined_vector_test.cc"],
|
srcs = ["inlined_vector_test.cc"],
|
||||||
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
|
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
|
||||||
linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
|
linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
|
||||||
deps = [
|
deps = [
|
||||||
|
":counting_allocator",
|
||||||
":inlined_vector",
|
":inlined_vector",
|
||||||
":test_instance_tracker",
|
":test_instance_tracker",
|
||||||
"//absl/base",
|
"//absl/base",
|
||||||
|
@ -146,6 +155,7 @@ cc_test(
|
||||||
srcs = ["inlined_vector_test.cc"],
|
srcs = ["inlined_vector_test.cc"],
|
||||||
copts = ABSL_TEST_COPTS,
|
copts = ABSL_TEST_COPTS,
|
||||||
deps = [
|
deps = [
|
||||||
|
":counting_allocator",
|
||||||
":inlined_vector",
|
":inlined_vector",
|
||||||
":test_instance_tracker",
|
":test_instance_tracker",
|
||||||
"//absl/base",
|
"//absl/base",
|
||||||
|
@ -443,6 +453,7 @@ cc_library(
|
||||||
copts = ABSL_DEFAULT_COPTS,
|
copts = ABSL_DEFAULT_COPTS,
|
||||||
deps = [
|
deps = [
|
||||||
":have_sse",
|
":have_sse",
|
||||||
|
"//absl/base",
|
||||||
"//absl/base:core_headers",
|
"//absl/base:core_headers",
|
||||||
"//absl/debugging:stacktrace",
|
"//absl/debugging:stacktrace",
|
||||||
"//absl/memory",
|
"//absl/memory",
|
||||||
|
|
|
@ -122,6 +122,15 @@ absl_cc_library(
|
||||||
PUBLIC
|
PUBLIC
|
||||||
)
|
)
|
||||||
|
|
||||||
|
absl_cc_library(
|
||||||
|
NAME
|
||||||
|
counting_allocator
|
||||||
|
HDRS
|
||||||
|
"internal/counting_allocator.h"
|
||||||
|
COPTS
|
||||||
|
${ABSL_DEFAULT_COPTS}
|
||||||
|
)
|
||||||
|
|
||||||
absl_cc_test(
|
absl_cc_test(
|
||||||
NAME
|
NAME
|
||||||
inlined_vector_test
|
inlined_vector_test
|
||||||
|
@ -132,6 +141,7 @@ absl_cc_test(
|
||||||
LINKOPTS
|
LINKOPTS
|
||||||
${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
|
${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
|
||||||
DEPS
|
DEPS
|
||||||
|
absl::counting_allocator
|
||||||
absl::inlined_vector
|
absl::inlined_vector
|
||||||
absl::test_instance_tracker
|
absl::test_instance_tracker
|
||||||
absl::base
|
absl::base
|
||||||
|
@ -437,6 +447,7 @@ absl_cc_library(
|
||||||
COPTS
|
COPTS
|
||||||
${ABSL_DEFAULT_COPTS}
|
${ABSL_DEFAULT_COPTS}
|
||||||
DEPS
|
DEPS
|
||||||
|
absl::base
|
||||||
absl::have_sse
|
absl::have_sse
|
||||||
absl::synchronization
|
absl::synchronization
|
||||||
)
|
)
|
||||||
|
|
|
@ -795,79 +795,7 @@ class InlinedVector {
|
||||||
void swap(InlinedVector& other) {
|
void swap(InlinedVector& other) {
|
||||||
if (ABSL_PREDICT_FALSE(this == &other)) return;
|
if (ABSL_PREDICT_FALSE(this == &other)) return;
|
||||||
|
|
||||||
using std::swap; // Augment ADL with `std::swap`.
|
SwapImpl(other);
|
||||||
if (allocated() && other.allocated()) {
|
|
||||||
// Both out of line, so just swap the tag, allocation, and allocator.
|
|
||||||
swap(tag(), other.tag());
|
|
||||||
swap(allocation(), other.allocation());
|
|
||||||
swap(allocator(), other.allocator());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!allocated() && !other.allocated()) {
|
|
||||||
// Both inlined: swap up to smaller size, then move remaining elements.
|
|
||||||
InlinedVector* a = this;
|
|
||||||
InlinedVector* b = &other;
|
|
||||||
if (size() < other.size()) {
|
|
||||||
swap(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_type a_size = a->size();
|
|
||||||
const size_type b_size = b->size();
|
|
||||||
assert(a_size >= b_size);
|
|
||||||
// `a` is larger. Swap the elements up to the smaller array size.
|
|
||||||
std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
|
|
||||||
b->inlined_space());
|
|
||||||
|
|
||||||
// Move the remaining elements:
|
|
||||||
// [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b`
|
|
||||||
b->UninitializedCopy(a->inlined_space() + b_size,
|
|
||||||
a->inlined_space() + a_size,
|
|
||||||
b->inlined_space() + b_size);
|
|
||||||
a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size);
|
|
||||||
|
|
||||||
swap(a->tag(), b->tag());
|
|
||||||
swap(a->allocator(), b->allocator());
|
|
||||||
assert(b->size() == a_size);
|
|
||||||
assert(a->size() == b_size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// One is out of line, one is inline.
|
|
||||||
// We first move the elements from the inlined vector into the
|
|
||||||
// inlined space in the other vector. We then put the other vector's
|
|
||||||
// pointer/capacity into the originally inlined vector and swap
|
|
||||||
// the tags.
|
|
||||||
InlinedVector* a = this;
|
|
||||||
InlinedVector* b = &other;
|
|
||||||
if (a->allocated()) {
|
|
||||||
swap(a, b);
|
|
||||||
}
|
|
||||||
assert(!a->allocated());
|
|
||||||
assert(b->allocated());
|
|
||||||
const size_type a_size = a->size();
|
|
||||||
const size_type b_size = b->size();
|
|
||||||
// In an optimized build, `b_size` would be unused.
|
|
||||||
static_cast<void>(b_size);
|
|
||||||
|
|
||||||
// Made Local copies of `size()`, don't need `tag()` accurate anymore
|
|
||||||
swap(a->tag(), b->tag());
|
|
||||||
|
|
||||||
// Copy `b_allocation` out before `b`'s union gets clobbered by
|
|
||||||
// `inline_space`
|
|
||||||
Allocation b_allocation = b->allocation();
|
|
||||||
|
|
||||||
b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size,
|
|
||||||
b->inlined_space());
|
|
||||||
a->Destroy(a->inlined_space(), a->inlined_space() + a_size);
|
|
||||||
|
|
||||||
a->allocation() = b_allocation;
|
|
||||||
|
|
||||||
if (a->allocator() != b->allocator()) {
|
|
||||||
swap(a->allocator(), b->allocator());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(b->size() == a_size);
|
|
||||||
assert(a->size() == b_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1238,6 +1166,83 @@ class InlinedVector {
|
||||||
return begin() + index;
|
return begin() + index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwapImpl(InlinedVector& other) {
|
||||||
|
using std::swap; // Augment ADL with `std::swap`.
|
||||||
|
|
||||||
|
if (allocated() && other.allocated()) {
|
||||||
|
// Both out of line, so just swap the tag, allocation, and allocator.
|
||||||
|
swap(tag(), other.tag());
|
||||||
|
swap(allocation(), other.allocation());
|
||||||
|
swap(allocator(), other.allocator());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!allocated() && !other.allocated()) {
|
||||||
|
// Both inlined: swap up to smaller size, then move remaining elements.
|
||||||
|
InlinedVector* a = this;
|
||||||
|
InlinedVector* b = &other;
|
||||||
|
if (size() < other.size()) {
|
||||||
|
swap(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_type a_size = a->size();
|
||||||
|
const size_type b_size = b->size();
|
||||||
|
assert(a_size >= b_size);
|
||||||
|
// `a` is larger. Swap the elements up to the smaller array size.
|
||||||
|
std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
|
||||||
|
b->inlined_space());
|
||||||
|
|
||||||
|
// Move the remaining elements:
|
||||||
|
// [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b`
|
||||||
|
b->UninitializedCopy(a->inlined_space() + b_size,
|
||||||
|
a->inlined_space() + a_size,
|
||||||
|
b->inlined_space() + b_size);
|
||||||
|
a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size);
|
||||||
|
|
||||||
|
swap(a->tag(), b->tag());
|
||||||
|
swap(a->allocator(), b->allocator());
|
||||||
|
assert(b->size() == a_size);
|
||||||
|
assert(a->size() == b_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One is out of line, one is inline.
|
||||||
|
// We first move the elements from the inlined vector into the
|
||||||
|
// inlined space in the other vector. We then put the other vector's
|
||||||
|
// pointer/capacity into the originally inlined vector and swap
|
||||||
|
// the tags.
|
||||||
|
InlinedVector* a = this;
|
||||||
|
InlinedVector* b = &other;
|
||||||
|
if (a->allocated()) {
|
||||||
|
swap(a, b);
|
||||||
|
}
|
||||||
|
assert(!a->allocated());
|
||||||
|
assert(b->allocated());
|
||||||
|
const size_type a_size = a->size();
|
||||||
|
const size_type b_size = b->size();
|
||||||
|
// In an optimized build, `b_size` would be unused.
|
||||||
|
static_cast<void>(b_size);
|
||||||
|
|
||||||
|
// Made Local copies of `size()`, don't need `tag()` accurate anymore
|
||||||
|
swap(a->tag(), b->tag());
|
||||||
|
|
||||||
|
// Copy `b_allocation` out before `b`'s union gets clobbered by
|
||||||
|
// `inline_space`
|
||||||
|
Allocation b_allocation = b->allocation();
|
||||||
|
|
||||||
|
b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size,
|
||||||
|
b->inlined_space());
|
||||||
|
a->Destroy(a->inlined_space(), a->inlined_space() + a_size);
|
||||||
|
|
||||||
|
a->allocation() = b_allocation;
|
||||||
|
|
||||||
|
if (a->allocator() != b->allocator()) {
|
||||||
|
swap(a->allocator(), b->allocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(b->size() == a_size);
|
||||||
|
assert(a->size() == b_size);
|
||||||
|
}
|
||||||
|
|
||||||
// Stores either the inlined or allocated representation
|
// Stores either the inlined or allocated representation
|
||||||
union Rep {
|
union Rep {
|
||||||
using ValueTypeBuffer =
|
using ValueTypeBuffer =
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "absl/base/internal/exception_testing.h"
|
#include "absl/base/internal/exception_testing.h"
|
||||||
#include "absl/base/internal/raw_logging.h"
|
#include "absl/base/internal/raw_logging.h"
|
||||||
#include "absl/base/macros.h"
|
#include "absl/base/macros.h"
|
||||||
|
#include "absl/container/internal/counting_allocator.h"
|
||||||
#include "absl/container/internal/test_instance_tracker.h"
|
#include "absl/container/internal/test_instance_tracker.h"
|
||||||
#include "absl/hash/hash_testing.h"
|
#include "absl/hash/hash_testing.h"
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using absl::container_internal::CountingAllocator;
|
||||||
using absl::test_internal::CopyableMovableInstance;
|
using absl::test_internal::CopyableMovableInstance;
|
||||||
using absl::test_internal::CopyableOnlyInstance;
|
using absl::test_internal::CopyableOnlyInstance;
|
||||||
using absl::test_internal::InstanceTracker;
|
using absl::test_internal::InstanceTracker;
|
||||||
|
@ -138,57 +140,6 @@ static IntVec Fill(int len, int offset = 0) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a stateful allocator, but the state lives outside of the
|
|
||||||
// allocator (in whatever test is using the allocator). This is odd
|
|
||||||
// but helps in tests where the allocator is propagated into nested
|
|
||||||
// containers - that chain of allocators uses the same state and is
|
|
||||||
// thus easier to query for aggregate allocation information.
|
|
||||||
template <typename T>
|
|
||||||
class CountingAllocator : public std::allocator<T> {
|
|
||||||
public:
|
|
||||||
using Alloc = std::allocator<T>;
|
|
||||||
using pointer = typename Alloc::pointer;
|
|
||||||
using size_type = typename Alloc::size_type;
|
|
||||||
|
|
||||||
CountingAllocator() : bytes_used_(nullptr) {}
|
|
||||||
explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
CountingAllocator(const CountingAllocator<U>& x)
|
|
||||||
: Alloc(x), bytes_used_(x.bytes_used_) {}
|
|
||||||
|
|
||||||
pointer allocate(size_type n,
|
|
||||||
std::allocator<void>::const_pointer hint = nullptr) {
|
|
||||||
assert(bytes_used_ != nullptr);
|
|
||||||
*bytes_used_ += n * sizeof(T);
|
|
||||||
return Alloc::allocate(n, hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate(pointer p, size_type n) {
|
|
||||||
Alloc::deallocate(p, n);
|
|
||||||
assert(bytes_used_ != nullptr);
|
|
||||||
*bytes_used_ -= n * sizeof(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U>
|
|
||||||
class rebind {
|
|
||||||
public:
|
|
||||||
using other = CountingAllocator<U>;
|
|
||||||
};
|
|
||||||
|
|
||||||
friend bool operator==(const CountingAllocator& a,
|
|
||||||
const CountingAllocator& b) {
|
|
||||||
return a.bytes_used_ == b.bytes_used_;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator!=(const CountingAllocator& a,
|
|
||||||
const CountingAllocator& b) {
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t* bytes_used_;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(IntVec, SimpleOps) {
|
TEST(IntVec, SimpleOps) {
|
||||||
for (int len = 0; len < 20; len++) {
|
for (int len = 0; len < 20; len++) {
|
||||||
IntVec v;
|
IntVec v;
|
||||||
|
|
79
absl/container/internal/counting_allocator.h
Normal file
79
absl/container/internal/counting_allocator.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// http://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_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
|
||||||
|
#define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace absl {
|
||||||
|
namespace container_internal {
|
||||||
|
|
||||||
|
// This is a stateful allocator, but the state lives outside of the
|
||||||
|
// allocator (in whatever test is using the allocator). This is odd
|
||||||
|
// but helps in tests where the allocator is propagated into nested
|
||||||
|
// containers - that chain of allocators uses the same state and is
|
||||||
|
// thus easier to query for aggregate allocation information.
|
||||||
|
template <typename T>
|
||||||
|
class CountingAllocator : public std::allocator<T> {
|
||||||
|
public:
|
||||||
|
using Alloc = std::allocator<T>;
|
||||||
|
using pointer = typename Alloc::pointer;
|
||||||
|
using size_type = typename Alloc::size_type;
|
||||||
|
|
||||||
|
CountingAllocator() : bytes_used_(nullptr) {}
|
||||||
|
explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
CountingAllocator(const CountingAllocator<U>& x)
|
||||||
|
: Alloc(x), bytes_used_(x.bytes_used_) {}
|
||||||
|
|
||||||
|
pointer allocate(size_type n,
|
||||||
|
std::allocator<void>::const_pointer hint = nullptr) {
|
||||||
|
assert(bytes_used_ != nullptr);
|
||||||
|
*bytes_used_ += n * sizeof(T);
|
||||||
|
return Alloc::allocate(n, hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(pointer p, size_type n) {
|
||||||
|
Alloc::deallocate(p, n);
|
||||||
|
assert(bytes_used_ != nullptr);
|
||||||
|
*bytes_used_ -= n * sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
class rebind {
|
||||||
|
public:
|
||||||
|
using other = CountingAllocator<U>;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend bool operator==(const CountingAllocator& a,
|
||||||
|
const CountingAllocator& b) {
|
||||||
|
return a.bytes_used_ == b.bytes_used_;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const CountingAllocator& a,
|
||||||
|
const CountingAllocator& b) {
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t* bytes_used_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace container_internal
|
||||||
|
} // namespace absl
|
||||||
|
|
||||||
|
#endif // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
|
|
@ -238,6 +238,10 @@ HashtablezInfo* SampleSlow(int64_t* next_sample) {
|
||||||
return HashtablezSampler::Global().Register();
|
return HashtablezSampler::Global().Register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ABSL_PER_THREAD_TLS == 1
|
||||||
|
ABSL_PER_THREAD_TLS_KEYWORD int64_t next_sample = 0;
|
||||||
|
#endif // ABSL_PER_THREAD_TLS == 1
|
||||||
|
|
||||||
void UnsampleSlow(HashtablezInfo* info) {
|
void UnsampleSlow(HashtablezInfo* info) {
|
||||||
HashtablezSampler::Global().Unregister(info);
|
HashtablezSampler::Global().Unregister(info);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/base/internal/per_thread_tls.h"
|
||||||
#include "absl/base/optimization.h"
|
#include "absl/base/optimization.h"
|
||||||
#include "absl/synchronization/mutex.h"
|
#include "absl/synchronization/mutex.h"
|
||||||
#include "absl/utility/utility.h"
|
#include "absl/utility/utility.h"
|
||||||
|
@ -147,14 +148,16 @@ class HashtablezInfoHandle {
|
||||||
|
|
||||||
// Returns an RAII sampling handle that manages registration and unregistation
|
// Returns an RAII sampling handle that manages registration and unregistation
|
||||||
// with the global sampler.
|
// with the global sampler.
|
||||||
|
#if ABSL_PER_THREAD_TLS == 1
|
||||||
|
extern ABSL_PER_THREAD_TLS_KEYWORD int64_t next_sample;
|
||||||
|
#endif // ABSL_PER_THREAD_TLS
|
||||||
|
|
||||||
inline HashtablezInfoHandle Sample() {
|
inline HashtablezInfoHandle Sample() {
|
||||||
#if ABSL_HAVE_THREAD_LOCAL
|
#if ABSL_PER_THREAD_TLS == 0
|
||||||
thread_local int64_t next_sample = 0;
|
|
||||||
#else // ABSL_HAVE_THREAD_LOCAL
|
|
||||||
static auto* mu = new absl::Mutex;
|
static auto* mu = new absl::Mutex;
|
||||||
static int64_t next_sample = 0;
|
static int64_t next_sample = 0;
|
||||||
absl::MutexLock l(mu);
|
absl::MutexLock l(mu);
|
||||||
#endif // ABSL_HAVE_THREAD_LOCAL
|
#endif // !ABSL_HAVE_THREAD_LOCAL
|
||||||
|
|
||||||
if (ABSL_PREDICT_TRUE(--next_sample > 0)) {
|
if (ABSL_PREDICT_TRUE(--next_sample > 0)) {
|
||||||
return HashtablezInfoHandle(nullptr);
|
return HashtablezInfoHandle(nullptr);
|
||||||
|
|
|
@ -785,7 +785,11 @@ class raw_hash_set {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl_t* ctrl_ = nullptr;
|
ctrl_t* ctrl_ = nullptr;
|
||||||
slot_type* slot_;
|
// To avoid uninitialized member warnigs, put slot_ in an anonymous union.
|
||||||
|
// The member is not initialized on singleton and end iterators.
|
||||||
|
union {
|
||||||
|
slot_type* slot_;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class const_iterator {
|
class const_iterator {
|
||||||
|
|
|
@ -10,8 +10,6 @@ compilation options:
|
||||||
The generated copts are consumed by configure_copts.bzl and
|
The generated copts are consumed by configure_copts.bzl and
|
||||||
AbseilConfigureCopts.cmake.
|
AbseilConfigureCopts.cmake.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import collections # absl:google-only(used for internal flags)
|
|
||||||
COPT_VARS = {
|
COPT_VARS = {
|
||||||
"GCC_FLAGS": [
|
"GCC_FLAGS": [
|
||||||
"-Wall",
|
"-Wall",
|
||||||
|
|
|
@ -69,6 +69,10 @@ cc_library(
|
||||||
"notification.h",
|
"notification.h",
|
||||||
],
|
],
|
||||||
copts = ABSL_DEFAULT_COPTS,
|
copts = ABSL_DEFAULT_COPTS,
|
||||||
|
linkopts = select({
|
||||||
|
"//absl:windows": [],
|
||||||
|
"//conditions:default": ["-pthread"],
|
||||||
|
}),
|
||||||
deps = [
|
deps = [
|
||||||
":graphcycles_internal",
|
":graphcycles_internal",
|
||||||
"//absl/base",
|
"//absl/base",
|
||||||
|
@ -245,10 +249,6 @@ cc_test(
|
||||||
"lifetime_test.cc",
|
"lifetime_test.cc",
|
||||||
],
|
],
|
||||||
copts = ABSL_TEST_COPTS,
|
copts = ABSL_TEST_COPTS,
|
||||||
linkopts = select({
|
|
||||||
"//absl:windows": [],
|
|
||||||
"//conditions:default": ["-pthread"],
|
|
||||||
}),
|
|
||||||
tags = ["no_test_ios_x86_64"],
|
tags = ["no_test_ios_x86_64"],
|
||||||
deps = [
|
deps = [
|
||||||
":synchronization",
|
":synchronization",
|
||||||
|
|
|
@ -98,13 +98,13 @@ cc_test(
|
||||||
cc_test(
|
cc_test(
|
||||||
name = "time_zone_lookup_test",
|
name = "time_zone_lookup_test",
|
||||||
size = "small",
|
size = "small",
|
||||||
|
timeout = "moderate",
|
||||||
srcs = ["src/time_zone_lookup_test.cc"],
|
srcs = ["src/time_zone_lookup_test.cc"],
|
||||||
data = [":zoneinfo"],
|
data = [":zoneinfo"],
|
||||||
tags = [
|
tags = [
|
||||||
"no_test_android_arm",
|
"no_test_android_arm",
|
||||||
"no_test_android_arm64",
|
"no_test_android_arm64",
|
||||||
"no_test_android_x86",
|
"no_test_android_x86",
|
||||||
"no_test_wasm",
|
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
":civil_time",
|
":civil_time",
|
||||||
|
|
|
@ -64,17 +64,6 @@ void TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt,
|
||||||
EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz));
|
EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz));
|
||||||
}
|
}
|
||||||
|
|
||||||
// These tests sometimes run on platforms that have zoneinfo data so old
|
|
||||||
// that the transition we are attempting to check does not exist, most
|
|
||||||
// notably Android emulators. Fortunately, AndroidZoneInfoSource supports
|
|
||||||
// time_zone::version() so, in cases where we've learned that it matters,
|
|
||||||
// we can make the check conditionally.
|
|
||||||
int VersionCmp(time_zone tz, const std::string& target) {
|
|
||||||
std::string version = tz.version();
|
|
||||||
if (version.empty() && !target.empty()) return 1; // unknown > known
|
|
||||||
return version.compare(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -174,7 +163,9 @@ TEST(Format, PosixConversions) {
|
||||||
TestFormatSpecifier(tp, tz, "%M", "00");
|
TestFormatSpecifier(tp, tz, "%M", "00");
|
||||||
TestFormatSpecifier(tp, tz, "%S", "00");
|
TestFormatSpecifier(tp, tz, "%S", "00");
|
||||||
TestFormatSpecifier(tp, tz, "%U", "00");
|
TestFormatSpecifier(tp, tz, "%U", "00");
|
||||||
|
#if !defined(__EMSCRIPTEN__)
|
||||||
TestFormatSpecifier(tp, tz, "%w", "4"); // 4=Thursday
|
TestFormatSpecifier(tp, tz, "%w", "4"); // 4=Thursday
|
||||||
|
#endif
|
||||||
TestFormatSpecifier(tp, tz, "%W", "00");
|
TestFormatSpecifier(tp, tz, "%W", "00");
|
||||||
TestFormatSpecifier(tp, tz, "%y", "70");
|
TestFormatSpecifier(tp, tz, "%y", "70");
|
||||||
TestFormatSpecifier(tp, tz, "%Y", "1970");
|
TestFormatSpecifier(tp, tz, "%Y", "1970");
|
||||||
|
@ -1464,6 +1455,10 @@ TEST(FormatParse, RoundTrip) {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
// Initial investigations indicate the %c does not roundtrip on Windows.
|
// Initial investigations indicate the %c does not roundtrip on Windows.
|
||||||
// TODO: Figure out what is going on here (perhaps a locale problem).
|
// TODO: Figure out what is going on here (perhaps a locale problem).
|
||||||
|
#elif defined(__EMSCRIPTEN__)
|
||||||
|
// strftime() and strptime() use different defintions for "%c" under
|
||||||
|
// emscripten (see https://github.com/kripken/emscripten/pull/7491),
|
||||||
|
// causing its round-trip test to fail.
|
||||||
#else
|
#else
|
||||||
// Even though we don't know what %c will produce, it should roundtrip,
|
// Even though we don't know what %c will produce, it should roundtrip,
|
||||||
// but only in the 0-offset timezone.
|
// but only in the 0-offset timezone.
|
||||||
|
|
|
@ -666,6 +666,7 @@ int VersionCmp(time_zone tz, const std::string& target) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
#if !defined(__EMSCRIPTEN__)
|
||||||
TEST(TimeZones, LoadZonesConcurrently) {
|
TEST(TimeZones, LoadZonesConcurrently) {
|
||||||
std::promise<void> ready_promise;
|
std::promise<void> ready_promise;
|
||||||
std::shared_future<void> ready_future(ready_promise.get_future());
|
std::shared_future<void> ready_future(ready_promise.get_future());
|
||||||
|
@ -713,6 +714,7 @@ TEST(TimeZones, LoadZonesConcurrently) {
|
||||||
}
|
}
|
||||||
EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures);
|
EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST(TimeZone, NamedTimeZones) {
|
TEST(TimeZone, NamedTimeZones) {
|
||||||
const time_zone utc = utc_time_zone();
|
const time_zone utc = utc_time_zone();
|
||||||
|
|
2
absl/time/internal/cctz/testdata/version
vendored
2
absl/time/internal/cctz/testdata/version
vendored
|
@ -1 +1 @@
|
||||||
2018g-9-gf0d2759
|
2018i
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
vendored
Normal file
BIN
absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
absl/time/internal/cctz/testdata/zoneinfo/Hongkong
vendored
BIN
absl/time/internal/cctz/testdata/zoneinfo/Hongkong
vendored
Binary file not shown.
BIN
absl/time/internal/cctz/testdata/zoneinfo/Iran
vendored
BIN
absl/time/internal/cctz/testdata/zoneinfo/Iran
vendored
Binary file not shown.
BIN
absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
vendored
BIN
absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -211,6 +211,7 @@ KP +3901+12545 Asia/Pyongyang
|
||||||
KR +3733+12658 Asia/Seoul
|
KR +3733+12658 Asia/Seoul
|
||||||
KZ +4315+07657 Asia/Almaty Kazakhstan (most areas)
|
KZ +4315+07657 Asia/Almaty Kazakhstan (most areas)
|
||||||
KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
|
KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
|
||||||
|
KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay
|
||||||
KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe
|
KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe
|
||||||
KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau
|
KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau
|
||||||
KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev
|
KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev
|
||||||
|
|
Loading…
Reference in a new issue