From 62f3fda2711b774333fa5e2632b93c54832e6f03 Mon Sep 17 00:00:00 2001 From: kgotlinux <60880393+kgotlinux@users.noreply.github.com> Date: Tue, 16 Jun 2020 22:15:41 +0200 Subject: Added neccessary headers for FreeBSD 1. Changed order of sys/sysctl.h, because sysctl.h needs types.h 2. Threads.h is neccessary for once_flag 3. absl/base/call_once.h is neccessary for LowLevelCallOnce --- absl/base/internal/unscaledcycleclock.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'absl/base/internal/unscaledcycleclock.cc') diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc index f1e7bbef..83e2134e 100644 --- a/absl/base/internal/unscaledcycleclock.cc +++ b/absl/base/internal/unscaledcycleclock.cc @@ -24,8 +24,10 @@ #ifdef __GLIBC__ #include #elif defined(__FreeBSD__) -#include +#include "absl/base/call_once.h" #include +#include +#include #endif #endif -- cgit v1.2.3 From cfbf5bf948a2656bda7ddab59d3bcb29595c144c Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 10 Sep 2021 12:22:01 -0700 Subject: Export of internal Abseil changes -- 77e710b0ced5792a328e88bcb938a41484bf4cdc by Saleem Abdulrasool : absl: add an implementation for UnscaledCycleClock on RISCV Add an implementation for UnscaledCycleClock on RISC-V targets. PiperOrigin-RevId: 395982312 -- 84430fce6760c488ca36401cd530f44268ac710d by Martijn Vels : Harden CordRepBtreeReader against reading up to or beyond EOF This change hardens the reader to Next() calls on EOF situations. It changes the 'consumed()' property inside CordRepBtreeReader into a 'remaining()' property which is easier to understand and use than the 'consumed()' property QED the function documentation and use in cord.cc This change also adds the CharIterator test to the CordTest fixture enabling them to be run with btree cords. PiperOrigin-RevId: 395971732 -- 6557e628f2613169da8f693189223acb30e07833 by Martijn Vels : Add AdvanceAndRead() test addressing the edge case surfaced in b/197776822 This adds a test explicitly exercising all possible AdvanceAndRead() calls on CharIterator. As per the linked bug, a partial or full small read ending exactly at the end of the last edge of a btree cord results in an attempt to read beyond that last edge and subsequent failure. We will fix the bug and enable these tests for btree in a subsequent change. PiperOrigin-RevId: 395958317 GitOrigin-RevId: 77e710b0ced5792a328e88bcb938a41484bf4cdc Change-Id: Ie6e21ce36980515165af7cf046cf199ecbe0ddb0 --- absl/base/internal/unscaledcycleclock.cc | 12 +++++ absl/base/internal/unscaledcycleclock.h | 8 +-- absl/strings/cord_test.cc | 41 ++++++++++++-- absl/strings/internal/cord_rep_btree_reader.cc | 6 +-- absl/strings/internal/cord_rep_btree_reader.h | 58 +++++++++----------- .../strings/internal/cord_rep_btree_reader_test.cc | 62 ++++++++++++---------- 6 files changed, 117 insertions(+), 70 deletions(-) (limited to 'absl/base/internal/unscaledcycleclock.cc') diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc index 1545288c..fc07e300 100644 --- a/absl/base/internal/unscaledcycleclock.cc +++ b/absl/base/internal/unscaledcycleclock.cc @@ -119,6 +119,18 @@ double UnscaledCycleClock::Frequency() { return aarch64_timer_frequency; } +#elif defined(__riscv) + +int64_t UnscaledCycleClock::Now() { + int64_t virtual_timer_value; + asm volatile("rdcycle %0" : "=r"(virtual_timer_value)); + return virtual_timer_value; +} + +double UnscaledCycleClock::Frequency() { + return base_internal::NominalCPUFrequency(); +} + #elif defined(_M_IX86) || defined(_M_X64) #pragma intrinsic(__rdtsc) diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h index 82f2c87a..681ff8f9 100644 --- a/absl/base/internal/unscaledcycleclock.h +++ b/absl/base/internal/unscaledcycleclock.h @@ -46,8 +46,8 @@ // The following platforms have an implementation of a hardware counter. #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \ - defined(__powerpc__) || defined(__ppc__) || \ - defined(_M_IX86) || defined(_M_X64) + defined(__powerpc__) || defined(__ppc__) || defined(__riscv) || \ + defined(_M_IX86) || defined(_M_X64) #define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1 #else #define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0 @@ -80,8 +80,8 @@ // This macro can be used to test if UnscaledCycleClock::Frequency() // is NominalCPUFrequency() on a particular platform. -#if (defined(__i386__) || defined(__x86_64__) || \ - defined(_M_IX86) || defined(_M_X64)) +#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \ + defined(_M_IX86) || defined(_M_X64)) #define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY #endif diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc index 06a7bd6c..50079b7c 100644 --- a/absl/strings/cord_test.cc +++ b/absl/strings/cord_test.cc @@ -1591,7 +1591,7 @@ TEST_P(CordTest, CordChunkIteratorOperations) { VerifyChunkIterator(subcords, 128); } -TEST(CordCharIterator, Traits) { +TEST_P(CordTest, CharIteratorTraits) { static_assert(std::is_copy_constructible::value, ""); static_assert(std::is_copy_assignable::value, ""); @@ -1700,7 +1700,7 @@ static void VerifyCharIterator(const absl::Cord& cord) { } } -TEST(CordCharIterator, Operations) { +TEST_P(CordTest, CharIteratorOperations) { absl::Cord empty_cord; VerifyCharIterator(empty_cord); @@ -1729,6 +1729,41 @@ TEST(CordCharIterator, Operations) { VerifyCharIterator(subcords); } +TEST_P(CordTest, CharIteratorAdvanceAndRead) { + // Create a Cord holding 6 flats of 2500 bytes each, and then iterate over it + // reading 150, 1500, 2500 and 3000 bytes. This will result in all possible + // partial, full and straddled read combinations including reads below + // kMaxBytesToCopy. b/197776822 surfaced a bug for a specific partial, small + // read 'at end' on Cord which caused a failure on attempting to read past the + // end in CordRepBtreeReader which was not covered by any existing test. + constexpr int kBlocks = 6; + constexpr size_t kBlockSize = 2500; + constexpr size_t kChunkSize1 = 1500; + constexpr size_t kChunkSize2 = 2500; + constexpr size_t kChunkSize3 = 3000; + constexpr size_t kChunkSize4 = 150; + RandomEngine rng; + std::string data = RandomLowercaseString(&rng, kBlocks * kBlockSize); + absl::Cord cord; + for (int i = 0; i < kBlocks; ++i) { + const std::string block = data.substr(i * kBlockSize, kBlockSize); + cord.Append(absl::Cord(block)); + } + + for (size_t chunk_size : + {kChunkSize1, kChunkSize2, kChunkSize3, kChunkSize4}) { + absl::Cord::CharIterator it = cord.char_begin(); + size_t offset = 0; + while (offset < data.length()) { + const size_t n = std::min(data.length() - offset, chunk_size); + absl::Cord chunk = cord.AdvanceAndRead(&it, n); + ASSERT_EQ(chunk.size(), n); + ASSERT_EQ(chunk.Compare(data.substr(offset, n)), 0); + offset += n; + } + } +} + TEST_P(CordTest, StreamingOutput) { absl::Cord c = absl::MakeFragmentedCord({"A ", "small ", "fragmented ", "Cord", "."}); @@ -1778,7 +1813,7 @@ TEST_P(CordTest, Format) { EXPECT_EQ(c, "There were 0003 little pigs.And 1 bad wolf!"); } -TEST(CordDeathTest, Hardening) { +TEST_P(CordTest, Hardening) { absl::Cord cord("hello"); // These statement should abort the program in all builds modes. EXPECT_DEATH_IF_SUPPORTED(cord.RemovePrefix(6), ""); diff --git a/absl/strings/internal/cord_rep_btree_reader.cc b/absl/strings/internal/cord_rep_btree_reader.cc index 3ba43144..5dc76966 100644 --- a/absl/strings/internal/cord_rep_btree_reader.cc +++ b/absl/strings/internal/cord_rep_btree_reader.cc @@ -52,14 +52,14 @@ absl::string_view CordRepBtreeReader::Read(size_t n, size_t chunk_size, // data, calling `navigator_.Current()` is not safe before checking if we // already consumed all remaining data. const size_t consumed_by_read = n - chunk_size - result.n; - if (consumed_ + consumed_by_read >= length()) { - consumed_ = length(); + if (consumed_by_read >= remaining_) { + remaining_ = 0; return {}; } // We did not read all data, return remaining data from current edge. edge = navigator_.Current(); - consumed_ += consumed_by_read + edge->length; + remaining_ -= consumed_by_read + edge->length; return CordRepBtree::EdgeData(edge).substr(result.n); } diff --git a/absl/strings/internal/cord_rep_btree_reader.h b/absl/strings/internal/cord_rep_btree_reader.h index c19fa43d..66e97f5d 100644 --- a/absl/strings/internal/cord_rep_btree_reader.h +++ b/absl/strings/internal/cord_rep_btree_reader.h @@ -31,9 +31,7 @@ namespace cord_internal { // References to the underlying data are returned as absl::string_view values. // The most typical use case is a forward only iteration over tree data. // The class also provides `Skip()`, `Seek()` and `Read()` methods similar to -// CordRepBtreeNavigator that allow more advanced navigation. The class provides -// a `consumed` property which contains the end offset of the chunk last -// returned to the user which is useful in cord iteration logic. +// CordRepBtreeNavigator that allow more advanced navigation. // // Example: iterate over all data inside a cord btree: // @@ -61,9 +59,9 @@ namespace cord_internal { // absl::string_view sv = reader.Next(); // } // -// It is important to notice that `consumed` represents the end position of the -// last data edge returned to the caller, not the cumulative data returned to -// the caller which can be less in cases of skipping or seeking over data. +// It is important to notice that `remaining` is based on the end position of +// the last data edge returned to the caller, not the cumulative data returned +// to the caller which can be less in cases of skipping or seeking over data. // // For example, consider a cord btree with five data edges: "abc", "def", "ghi", // "jkl" and "mno": @@ -71,14 +69,12 @@ namespace cord_internal { // absl::string_view sv; // CordRepBtreeReader reader; // -// sv = reader.Init(tree); // sv = "abc", reader.consumed() = 3 -// sv = reader.Skip(4); // sv = "hi", reader.consumed() = 9 -// sv = reader.Skip(2); // sv = "l", reader.consumed() = 12 -// sv = reader.Next(); // sv = "mno", reader.consumed() = 15 +// sv = reader.Init(tree); // sv = "abc", remaining = 12 +// sv = reader.Skip(4); // sv = "hi", remaining = 6 +// sv = reader.Skip(2); // sv = "l", remaining = 3 +// sv = reader.Next(); // sv = "mno", remaining = 0 +// sv = reader.Seek(1); // sv = "bc", remaining = 12 // -// In the above example, `reader.consumed()` reflects the data edges iterated -// over or skipped by the reader, not the amount of data 'consumed' by the -// caller. class CordRepBtreeReader { public: using ReadResult = CordRepBtreeNavigator::ReadResult; @@ -98,13 +94,14 @@ class CordRepBtreeReader { // Requires that the current instance is not empty. size_t length() const; - // Returns the end offset of the last navigated to chunk, which represents the - // total bytes 'consumed' relative to the start of the tree. The returned - // value is never zero. For example, initializing a reader with a tree with a - // first data edge of 19 bytes will return `consumed() = 19`. See also the - // class comments on the meaning of `consumed`. - // Requires that the current instance is not empty. - size_t consumed() const; + // Returns the number of remaining bytes available for iteration, which is the + // number of bytes directly following the end of the last chunk returned. + // This value will be zero if we iterated over the last edge in the bound + // tree, in which case any call to Next() or Skip() will return an empty + // string_view reflecting the EOF state. + // Note that a call to `Seek()` resets `remaining` to a value based on the + // end position of the chunk returned by that call. + size_t remaining() const { return remaining_; } // Resets this instance to an empty value. void Reset() { navigator_.Reset(); } @@ -157,7 +154,7 @@ class CordRepBtreeReader { absl::string_view Seek(size_t offset); private: - size_t consumed_; + size_t remaining_ = 0; CordRepBtreeNavigator navigator_; }; @@ -166,23 +163,18 @@ inline size_t CordRepBtreeReader::length() const { return btree()->length; } -inline size_t CordRepBtreeReader::consumed() const { - assert(btree() != nullptr); - return consumed_; -} - inline absl::string_view CordRepBtreeReader::Init(CordRepBtree* tree) { assert(tree != nullptr); const CordRep* edge = navigator_.InitFirst(tree); - consumed_ = edge->length; + remaining_ = tree->length - edge->length;; return CordRepBtree::EdgeData(edge); } inline absl::string_view CordRepBtreeReader::Next() { - assert(consumed() < length()); + if (remaining_ == 0) return {}; const CordRep* edge = navigator_.Next(); assert(edge != nullptr); - consumed_ += edge->length; + remaining_ -= edge->length; return CordRepBtree::EdgeData(edge); } @@ -192,23 +184,23 @@ inline absl::string_view CordRepBtreeReader::Skip(size_t skip) { const size_t edge_length = navigator_.Current()->length; CordRepBtreeNavigator::Position pos = navigator_.Skip(skip + edge_length); if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) { - consumed_ = length(); + remaining_ = 0; return {}; } // The combined length of all edges skipped before `pos.edge` is `skip - // pos.offset`, all of which are 'consumed', as well as the current edge. - consumed_ += skip - pos.offset + pos.edge->length; + remaining_ -= skip - pos.offset + pos.edge->length; return CordRepBtree::EdgeData(pos.edge).substr(pos.offset); } inline absl::string_view CordRepBtreeReader::Seek(size_t offset) { const CordRepBtreeNavigator::Position pos = navigator_.Seek(offset); if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) { - consumed_ = length(); + remaining_ = 0; return {}; } absl::string_view chunk = CordRepBtree::EdgeData(pos.edge).substr(pos.offset); - consumed_ = offset + chunk.length(); + remaining_ = length() - offset - chunk.length(); return chunk; } diff --git a/absl/strings/internal/cord_rep_btree_reader_test.cc b/absl/strings/internal/cord_rep_btree_reader_test.cc index 44d3365f..9b27a81f 100644 --- a/absl/strings/internal/cord_rep_btree_reader_test.cc +++ b/absl/strings/internal/cord_rep_btree_reader_test.cc @@ -58,22 +58,26 @@ TEST(CordRepBtreeReaderTest, Next) { CordRepBtree* node = CordRepBtreeFromFlats(flats); CordRepBtreeReader reader; + size_t remaining = data.length(); absl::string_view chunk = reader.Init(node); EXPECT_THAT(chunk, Eq(data.substr(0, chunk.length()))); - size_t consumed = chunk.length(); - EXPECT_THAT(reader.consumed(), Eq(consumed)); + remaining -= chunk.length(); + EXPECT_THAT(reader.remaining(), Eq(remaining)); - while (consumed < data.length()) { + while (remaining > 0) { + const size_t offset = data.length() - remaining; chunk = reader.Next(); - EXPECT_THAT(chunk, Eq(data.substr(consumed, chunk.length()))); + EXPECT_THAT(chunk, Eq(data.substr(offset, chunk.length()))); - consumed += chunk.length(); - EXPECT_THAT(reader.consumed(), Eq(consumed)); + remaining -= chunk.length(); + EXPECT_THAT(reader.remaining(), Eq(remaining)); } - EXPECT_THAT(consumed, Eq(data.length())); - EXPECT_THAT(reader.consumed(), Eq(data.length())); + EXPECT_THAT(reader.remaining(), Eq(0)); + + // Verify trying to read beyond EOF returns empty string_view + EXPECT_THAT(reader.Next(), testing::IsEmpty()); CordRep::Unref(node); } @@ -92,19 +96,22 @@ TEST(CordRepBtreeReaderTest, Skip) { for (size_t skip1 = 0; skip1 < data.length() - kChars; ++skip1) { for (size_t skip2 = 0; skip2 < data.length() - kChars; ++skip2) { CordRepBtreeReader reader; + size_t remaining = data.length(); absl::string_view chunk = reader.Init(node); - size_t consumed = chunk.length(); + remaining -= chunk.length(); chunk = reader.Skip(skip1); - ASSERT_THAT(chunk, Eq(data.substr(consumed + skip1, chunk.length()))); - consumed += chunk.length() + skip1; - ASSERT_THAT(reader.consumed(), Eq(consumed)); + size_t offset = data.length() - remaining; + ASSERT_THAT(chunk, Eq(data.substr(offset + skip1, chunk.length()))); + remaining -= chunk.length() + skip1; + ASSERT_THAT(reader.remaining(), Eq(remaining)); - if (consumed >= data.length()) continue; + if (remaining == 0) continue; - size_t skip = std::min(data.length() - consumed - 1, skip2); + size_t skip = std::min(remaining - 1, skip2); chunk = reader.Skip(skip); - ASSERT_THAT(chunk, Eq(data.substr(consumed + skip, chunk.length()))); + offset = data.length() - remaining; + ASSERT_THAT(chunk, Eq(data.substr(offset + skip, chunk.length()))); } } @@ -118,7 +125,7 @@ TEST(CordRepBtreeReaderTest, SkipBeyondLength) { CordRepBtreeReader reader; reader.Init(tree); EXPECT_THAT(reader.Skip(100), IsEmpty()); - EXPECT_THAT(reader.consumed(), Eq(6)); + EXPECT_THAT(reader.remaining(), Eq(0)); CordRep::Unref(tree); } @@ -138,7 +145,8 @@ TEST(CordRepBtreeReaderTest, Seek) { absl::string_view chunk = reader.Seek(seek); ASSERT_THAT(chunk, Not(IsEmpty())); ASSERT_THAT(chunk, Eq(data.substr(seek, chunk.length()))); - ASSERT_THAT(reader.consumed(), Eq(seek + chunk.length())); + ASSERT_THAT(reader.remaining(), + Eq(data.length() - seek - chunk.length())); } CordRep::Unref(node); @@ -151,9 +159,9 @@ TEST(CordRepBtreeReaderTest, SeekBeyondLength) { CordRepBtreeReader reader; reader.Init(tree); EXPECT_THAT(reader.Seek(6), IsEmpty()); - EXPECT_THAT(reader.consumed(), Eq(6)); + EXPECT_THAT(reader.remaining(), Eq(0)); EXPECT_THAT(reader.Seek(100), IsEmpty()); - EXPECT_THAT(reader.consumed(), Eq(6)); + EXPECT_THAT(reader.remaining(), Eq(0)); CordRep::Unref(tree); } @@ -171,7 +179,7 @@ TEST(CordRepBtreeReaderTest, Read) { chunk = reader.Read(0, chunk.length(), tree); EXPECT_THAT(tree, Eq(nullptr)); EXPECT_THAT(chunk, Eq("abcde")); - EXPECT_THAT(reader.consumed(), Eq(5)); + EXPECT_THAT(reader.remaining(), Eq(10)); EXPECT_THAT(reader.Next(), Eq("fghij")); // Read in full @@ -180,7 +188,7 @@ TEST(CordRepBtreeReaderTest, Read) { EXPECT_THAT(tree, Ne(nullptr)); EXPECT_THAT(CordToString(tree), Eq("abcdefghijklmno")); EXPECT_THAT(chunk, Eq("")); - EXPECT_THAT(reader.consumed(), Eq(15)); + EXPECT_THAT(reader.remaining(), Eq(0)); CordRep::Unref(tree); // Read < chunk bytes @@ -189,7 +197,7 @@ TEST(CordRepBtreeReaderTest, Read) { ASSERT_THAT(tree, Ne(nullptr)); EXPECT_THAT(CordToString(tree), Eq("abc")); EXPECT_THAT(chunk, Eq("de")); - EXPECT_THAT(reader.consumed(), Eq(5)); + EXPECT_THAT(reader.remaining(), Eq(10)); EXPECT_THAT(reader.Next(), Eq("fghij")); CordRep::Unref(tree); @@ -199,7 +207,7 @@ TEST(CordRepBtreeReaderTest, Read) { ASSERT_THAT(tree, Ne(nullptr)); EXPECT_THAT(CordToString(tree), Eq("cd")); EXPECT_THAT(chunk, Eq("e")); - EXPECT_THAT(reader.consumed(), Eq(5)); + EXPECT_THAT(reader.remaining(), Eq(10)); EXPECT_THAT(reader.Next(), Eq("fghij")); CordRep::Unref(tree); @@ -209,7 +217,7 @@ TEST(CordRepBtreeReaderTest, Read) { ASSERT_THAT(tree, Ne(nullptr)); EXPECT_THAT(CordToString(tree), Eq("fgh")); EXPECT_THAT(chunk, Eq("ij")); - EXPECT_THAT(reader.consumed(), Eq(10)); + EXPECT_THAT(reader.remaining(), Eq(5)); EXPECT_THAT(reader.Next(), Eq("klmno")); CordRep::Unref(tree); @@ -219,7 +227,7 @@ TEST(CordRepBtreeReaderTest, Read) { ASSERT_THAT(tree, Ne(nullptr)); EXPECT_THAT(CordToString(tree), Eq("cdefghijklmn")); EXPECT_THAT(chunk, Eq("o")); - EXPECT_THAT(reader.consumed(), Eq(15)); + EXPECT_THAT(reader.remaining(), Eq(0)); CordRep::Unref(tree); // Read across chunks landing on exact edge boundary @@ -228,7 +236,7 @@ TEST(CordRepBtreeReaderTest, Read) { ASSERT_THAT(tree, Ne(nullptr)); EXPECT_THAT(CordToString(tree), Eq("cdefghij")); EXPECT_THAT(chunk, Eq("klmno")); - EXPECT_THAT(reader.consumed(), Eq(15)); + EXPECT_THAT(reader.remaining(), Eq(0)); CordRep::Unref(tree); CordRep::Unref(node); @@ -264,7 +272,7 @@ TEST(CordRepBtreeReaderTest, ReadExhaustive) { consumed += n; remaining -= n; - EXPECT_THAT(reader.consumed(), Eq(consumed + chunk.length())); + EXPECT_THAT(reader.remaining(), Eq(remaining - chunk.length())); if (remaining > 0) { ASSERT_FALSE(chunk.empty()); -- cgit v1.2.3 From f3a42743db4df4c98e1df690045577c775daf20b Mon Sep 17 00:00:00 2001 From: Milad Fa <46688537+miladfarca@users.noreply.github.com> Date: Thu, 23 Sep 2021 16:23:02 -0400 Subject: Initial support for AIX (#1021) * Init support of AIX * make sysinfo change AIX specific * Relocate TBF * Add comments for .csect psudo op. --- absl/base/attributes.h | 8 ++++++++ absl/base/config.h | 10 +++++----- absl/base/internal/sysinfo.cc | 2 ++ absl/base/internal/unscaledcycleclock.cc | 4 ++++ absl/time/clock_test.cc | 2 ++ 5 files changed, 21 insertions(+), 5 deletions(-) (limited to 'absl/base/internal/unscaledcycleclock.cc') diff --git a/absl/base/attributes.h b/absl/base/attributes.h index 2665d8f3..e3907827 100644 --- a/absl/base/attributes.h +++ b/absl/base/attributes.h @@ -318,8 +318,16 @@ // `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. // This functionality is supported by GNU linker. #ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE +#ifdef _AIX +// __attribute__((section(#name))) on AIX is achived by using the `.csect` psudo +// op which includes an additional integer as part of its syntax indcating +// alignment. If data fall under different alignments then you might get a +// compilation error indicating a `Section type conflict`. +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) +#else #define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) #endif +#endif // ABSL_DECLARE_ATTRIBUTE_SECTION_VARS // diff --git a/absl/base/config.h b/absl/base/config.h index c7b2e64d..5d3edcd2 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -408,10 +408,10 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // POSIX.1-2001. #ifdef ABSL_HAVE_MMAP #error ABSL_HAVE_MMAP cannot be directly set -#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \ - defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \ - defined(__ASYLO__) || defined(__myriad2__) +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ + defined(_AIX) || defined(__ros__) || defined(__native_client__) || \ + defined(__asmjs__) || defined(__wasm__) || defined(__Fuchsia__) || \ + defined(__sun) || defined(__ASYLO__) || defined(__myriad2__) #define ABSL_HAVE_MMAP 1 #endif @@ -422,7 +422,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || #ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM #error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__ros__) + defined(_AIX) || defined(__ros__) #define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1 #endif diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc index 08a1e288..a7cfb461 100644 --- a/absl/base/internal/sysinfo.cc +++ b/absl/base/internal/sysinfo.cc @@ -131,6 +131,8 @@ static int GetNumCPUs() { #elif defined(_WIN32) const unsigned hardware_concurrency = Win32NumCPUs(); return hardware_concurrency ? hardware_concurrency : 1; +#elif defined(_AIX) + return sysconf(_SC_NPROCESSORS_ONLN); #else // Other possibilities: // - Read /sys/devices/system/cpu/online and use cpumask_parse() diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc index fc07e300..4d352bd1 100644 --- a/absl/base/internal/unscaledcycleclock.cc +++ b/absl/base/internal/unscaledcycleclock.cc @@ -87,6 +87,10 @@ int64_t UnscaledCycleClock::Now() { double UnscaledCycleClock::Frequency() { #ifdef __GLIBC__ return __ppc_get_timebase_freq(); +#elif defined(_AIX) + // This is the same constant value as returned by + // __ppc_get_timebase_freq(). + return static_cast(512000000); #elif defined(__FreeBSD__) static once_flag init_timebase_frequency_once; static double timebase_frequency = 0.0; diff --git a/absl/time/clock_test.cc b/absl/time/clock_test.cc index 4bcfc6bc..e6f627b3 100644 --- a/absl/time/clock_test.cc +++ b/absl/time/clock_test.cc @@ -18,6 +18,8 @@ #if defined(ABSL_HAVE_ALARM) #include #include +#elif defined(_AIX) +typedef void (*sig_t)(int); #elif defined(__linux__) || defined(__APPLE__) #error all known Linux and Apple targets have alarm #endif -- cgit v1.2.3 From 5ed77665c4d697f657fa1362b5a482450f858cdc Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 14 Mar 2022 08:43:59 -0700 Subject: Export of internal Abseil changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -- d3b99682554d339c42556680f4d65f83226005e2 by Martijn Vels : Inline CycleClock code and remove branch for x86 CycleClockSource function This CL removes the relaxed load for x86 as there is no acquire price to pay on x86. It inlines the UnscaledCycleClock::Now() which is a single RTDSC op for x86, and likewise inlines CycleClock::Now() for x86. The inlining should mostly have secondary benefits such as reducing spills on outlined calls. LTO may eventually hoist these functions inline for the hotspots, but it doesn't hurt to default inline this for all builds and let the compiler decide on the first pass. The perlab benchmark is noisy for the plain BM_Now, but the other benchmarks and the run on my local machine are clear. ------------- Local Benchy Benchmark name old cpu/op new cpu/op delta BM_Now 3.41ns ± 1% 2.30ns ± 2% -32.52% (p=0.000 n=50+50) BM_NowWithRegisterPresure 4.96ns ± 2% 4.19ns ± 2% -15.57% (p=0.000 n=56+55) BM_NowWithCallback 3.30ns ± 2% 1.91ns ± 2% -42.00% (p=0.000 n=47+60) ------------- Perflab Benchy Benchmark name old cpu/op new cpu/op delta BM_Now 8.20ns ±13% 4.32ns ±83% ~ (p=0.413 n=4+5) BM_NowWithRegisterPresure 7.91ns ± 1% 3.68ns ± 2% -53.45% (p=0.029 n=4+4) BM_NowWithCallback 2.66ns ±13% 1.58ns ± 0% -40.51% (p=0.008 n=5+5) PiperOrigin-RevId: 434474766 Change-Id: I991d987ae9233e50f09606c874055cf4c5a56300 -- b38330686a0af176a2679163e4d2fa1b90e2f667 by Laramie Leavitt : Style, comment, and test updates * Remove a redundant assert in uniform_real_distribution. * Update comment in internal/generate_real.h * Style updates to uniform_real_distribution_test mainly replacing TypeParam with real_type, using aliases for some limits, etc. * Add a few more minor tests. PiperOrigin-RevId: 433902174 Change-Id: Id75be8e24be2fb8f6aea05feec13e3ef320a7254 -- ab2da6047ff7f5dae3add3779fcddf73b03feabf by Abseil Team : Remove declaration of method whose definition was previously removed. PiperOrigin-RevId: 433507828 Change-Id: I0130b689813125250f7de2664e767e181f676c89 -- df0c87f4ec2c010691931c1bef9d26470a6e63a2 by Derek Mauro : Internal change PiperOrigin-RevId: 433289136 Change-Id: Iba157dc83ed99dafd17a2223d2504e49f8afbb9e -- 7445fa312f2995772900eda82467325b3401a17d by Martijn Vels : Optimize CordReader logic now that CONCAT is removed This CL cleans up various helper functions and logic remaining from previous complex CONCAT logic that is no longer needed, simplifying the CordReader logic. PiperOrigin-RevId: 433208748 Change-Id: I5f7b1883573c44e7c6f8af12c3cddbd197cb134d GitOrigin-RevId: d3b99682554d339c42556680f4d65f83226005e2 --- absl/base/config.h | 2 +- absl/base/internal/cycleclock.cc | 53 +++-------- absl/base/internal/cycleclock.h | 69 ++++++++++++++- absl/base/internal/unscaledcycleclock.cc | 6 -- absl/base/internal/unscaledcycleclock.h | 10 +++ absl/random/internal/generate_real.h | 4 +- absl/random/uniform_real_distribution.h | 2 +- absl/random/uniform_real_distribution_test.cc | 121 +++++++++++++++++--------- absl/status/status.h | 4 - absl/strings/cord.h | 6 ++ 10 files changed, 176 insertions(+), 101 deletions(-) (limited to 'absl/base/internal/unscaledcycleclock.cc') diff --git a/absl/base/config.h b/absl/base/config.h index cd7781c0..8c100d8e 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -425,7 +425,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || #ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM #error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(_AIX) || defined(__ros__) || defined(__OpenBSD__) || \ + defined(_AIX) || defined(__ros__) || defined(__OpenBSD__) || \ defined(__NetBSD__) #define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1 #endif diff --git a/absl/base/internal/cycleclock.cc b/absl/base/internal/cycleclock.cc index 0e65005b..f6e64242 100644 --- a/absl/base/internal/cycleclock.cc +++ b/absl/base/internal/cycleclock.cc @@ -25,6 +25,7 @@ #include #include // NOLINT(build/c++11) +#include "absl/base/attributes.h" #include "absl/base/internal/unscaledcycleclock.h" namespace absl { @@ -33,44 +34,18 @@ namespace base_internal { #if ABSL_USE_UNSCALED_CYCLECLOCK -namespace { +constexpr int32_t CycleClock::kShift; +constexpr double CycleClock::kFrequencyScale; -#ifdef NDEBUG -#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY -// Not debug mode and the UnscaledCycleClock frequency is the CPU -// frequency. Scale the CycleClock to prevent overflow if someone -// tries to represent the time as cycles since the Unix epoch. -static constexpr int32_t kShift = 1; -#else -// Not debug mode and the UnscaledCycleClock isn't operating at the -// raw CPU frequency. There is no need to do any scaling, so don't -// needlessly sacrifice precision. -static constexpr int32_t kShift = 0; -#endif -#else -// In debug mode use a different shift to discourage depending on a -// particular shift value. -static constexpr int32_t kShift = 2; -#endif - -static constexpr double kFrequencyScale = 1.0 / (1 << kShift); -static std::atomic cycle_clock_source; +ABSL_CONST_INIT std::atomic + CycleClock::cycle_clock_source_{nullptr}; -CycleClockSourceFunc LoadCycleClockSource() { - // Optimize for the common case (no callback) by first doing a relaxed load; - // this is significantly faster on non-x86 platforms. - if (cycle_clock_source.load(std::memory_order_relaxed) == nullptr) { - return nullptr; - } - // This corresponds to the store(std::memory_order_release) in - // CycleClockSource::Register, and makes sure that any updates made prior to - // registering the callback are visible to this thread before the callback is - // invoked. - return cycle_clock_source.load(std::memory_order_acquire); +void CycleClockSource::Register(CycleClockSourceFunc source) { + // Corresponds to the load(std::memory_order_acquire) in LoadCycleClockSource. + CycleClock::cycle_clock_source_.store(source, std::memory_order_release); } -} // namespace - +#ifdef _WIN32 int64_t CycleClock::Now() { auto fn = LoadCycleClockSource(); if (fn == nullptr) { @@ -78,15 +53,7 @@ int64_t CycleClock::Now() { } return fn() >> kShift; } - -double CycleClock::Frequency() { - return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency(); -} - -void CycleClockSource::Register(CycleClockSourceFunc source) { - // Corresponds to the load(std::memory_order_acquire) in LoadCycleClockSource. - cycle_clock_source.store(source, std::memory_order_release); -} +#endif #else diff --git a/absl/base/internal/cycleclock.h b/absl/base/internal/cycleclock.h index a18b5844..9704e388 100644 --- a/absl/base/internal/cycleclock.h +++ b/absl/base/internal/cycleclock.h @@ -42,14 +42,19 @@ #ifndef ABSL_BASE_INTERNAL_CYCLECLOCK_H_ #define ABSL_BASE_INTERNAL_CYCLECLOCK_H_ +#include #include +#include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/base/internal/unscaledcycleclock.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace base_internal { +using CycleClockSourceFunc = int64_t (*)(); + // ----------------------------------------------------------------------------- // CycleClock // ----------------------------------------------------------------------------- @@ -68,12 +73,37 @@ class CycleClock { static double Frequency(); private: +#if ABSL_USE_UNSCALED_CYCLECLOCK + static CycleClockSourceFunc LoadCycleClockSource(); + +#ifdef NDEBUG +#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY + // Not debug mode and the UnscaledCycleClock frequency is the CPU + // frequency. Scale the CycleClock to prevent overflow if someone + // tries to represent the time as cycles since the Unix epoch. + static constexpr int32_t kShift = 1; +#else + // Not debug mode and the UnscaledCycleClock isn't operating at the + // raw CPU frequency. There is no need to do any scaling, so don't + // needlessly sacrifice precision. + static constexpr int32_t kShift = 0; +#endif +#else // NDEBUG + // In debug mode use a different shift to discourage depending on a + // particular shift value. + static constexpr int32_t kShift = 2; +#endif // NDEBUG + + static constexpr double kFrequencyScale = 1.0 / (1 << kShift); + ABSL_CONST_INIT static std::atomic cycle_clock_source_; +#endif // ABSL_USE_UNSCALED_CYCLECLOC + CycleClock() = delete; // no instances CycleClock(const CycleClock&) = delete; CycleClock& operator=(const CycleClock&) = delete; -}; -using CycleClockSourceFunc = int64_t (*)(); + friend class CycleClockSource; +}; class CycleClockSource { private: @@ -87,6 +117,41 @@ class CycleClockSource { static void Register(CycleClockSourceFunc source); }; +#if ABSL_USE_UNSCALED_CYCLECLOCK + +inline CycleClockSourceFunc CycleClock::LoadCycleClockSource() { +#if !defined(__x86_64__) + // Optimize for the common case (no callback) by first doing a relaxed load; + // this is significantly faster on non-x86 platforms. + if (cycle_clock_source_.load(std::memory_order_relaxed) == nullptr) { + return nullptr; + } +#endif // !defined(__x86_64__) + + // This corresponds to the store(std::memory_order_release) in + // CycleClockSource::Register, and makes sure that any updates made prior to + // registering the callback are visible to this thread before the callback + // is invoked. + return cycle_clock_source_.load(std::memory_order_acquire); +} + +// Accessing globals in inlined code in Window DLLs is problematic. +#ifndef _WIN32 +inline int64_t CycleClock::Now() { + auto fn = LoadCycleClockSource(); + if (fn == nullptr) { + return base_internal::UnscaledCycleClock::Now() >> kShift; + } + return fn() >> kShift; +} +#endif + +inline double CycleClock::Frequency() { + return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency(); +} + +#endif // ABSL_USE_UNSCALED_CYCLECLOCK + } // namespace base_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc index 4d352bd1..7b79d19e 100644 --- a/absl/base/internal/unscaledcycleclock.cc +++ b/absl/base/internal/unscaledcycleclock.cc @@ -49,12 +49,6 @@ double UnscaledCycleClock::Frequency() { #elif defined(__x86_64__) -int64_t UnscaledCycleClock::Now() { - uint64_t low, high; - __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); - return (high << 32) | low; -} - double UnscaledCycleClock::Frequency() { return base_internal::NominalCPUFrequency(); } diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h index 681ff8f9..07f867a6 100644 --- a/absl/base/internal/unscaledcycleclock.h +++ b/absl/base/internal/unscaledcycleclock.h @@ -115,6 +115,16 @@ class UnscaledCycleClock { friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency; }; +#if defined(__x86_64__) + +inline int64_t UnscaledCycleClock::Now() { + uint64_t low, high; + __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); + return (high << 32) | low; +} + +#endif + } // namespace base_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/generate_real.h b/absl/random/internal/generate_real.h index d5fbb44c..b569450c 100644 --- a/absl/random/internal/generate_real.h +++ b/absl/random/internal/generate_real.h @@ -50,10 +50,10 @@ struct GenerateSignedTag {}; // inputs, otherwise it never returns 0. // // When a value in U(0,1) is required, use: -// Uniform64ToReal; +// GenerateRealFromBits; // // When a value in U(-1,1) is required, use: -// Uniform64ToReal; +// GenerateRealFromBits; // // This generates more distinct values than the mathematical equivalent // `U(0, 1) * 2.0 - 1.0`. diff --git a/absl/random/uniform_real_distribution.h b/absl/random/uniform_real_distribution.h index 5ba17b23..19683341 100644 --- a/absl/random/uniform_real_distribution.h +++ b/absl/random/uniform_real_distribution.h @@ -73,12 +73,12 @@ class uniform_real_distribution { : lo_(lo), hi_(hi), range_(hi - lo) { // [rand.dist.uni.real] preconditions 2 & 3 assert(lo <= hi); + // NOTE: For integral types, we can promote the range to an unsigned type, // which gives full width of the range. However for real (fp) types, this // is not possible, so value generation cannot use the full range of the // real type. assert(range_ <= (std::numeric_limits::max)()); - assert(std::isfinite(range_)); } result_type a() const { return lo_; } diff --git a/absl/random/uniform_real_distribution_test.cc b/absl/random/uniform_real_distribution_test.cc index 035bd284..07f199d3 100644 --- a/absl/random/uniform_real_distribution_test.cc +++ b/absl/random/uniform_real_distribution_test.cc @@ -78,62 +78,74 @@ TYPED_TEST(UniformRealDistributionTest, ParamSerializeTest) { GTEST_SKIP() << "Skipping the test because we detected x87 floating-point semantics"; #endif + using DistributionType = absl::uniform_real_distribution; + using real_type = TypeParam; + using param_type = typename DistributionType::param_type; - using param_type = - typename absl::uniform_real_distribution::param_type; + constexpr const real_type kMax = std::numeric_limits::max(); + constexpr const real_type kMin = std::numeric_limits::min(); + constexpr const real_type kEpsilon = + std::numeric_limits::epsilon(); + constexpr const real_type kLowest = + std::numeric_limits::lowest(); // -max - constexpr const TypeParam a{1152921504606846976}; + const real_type kDenormMax = std::nextafter(kMin, real_type{0}); + const real_type kOneMinusE = + std::nextafter(real_type{1}, real_type{0}); // 1 - epsilon + + constexpr const real_type kTwo60{1152921504606846976}; // 2^60 constexpr int kCount = 1000; absl::InsecureBitGen gen; for (const auto& param : { param_type(), - param_type(TypeParam(2.0), TypeParam(2.0)), // Same - param_type(TypeParam(-0.1), TypeParam(0.1)), - param_type(TypeParam(0.05), TypeParam(0.12)), - param_type(TypeParam(-0.05), TypeParam(0.13)), - param_type(TypeParam(-0.05), TypeParam(-0.02)), + param_type(real_type{0}, real_type{1}), + param_type(real_type(-0.1), real_type(0.1)), + param_type(real_type(0.05), real_type(0.12)), + param_type(real_type(-0.05), real_type(0.13)), + param_type(real_type(-0.05), real_type(-0.02)), + // range = 0 + param_type(real_type(2.0), real_type(2.0)), // Same // double range = 0 // 2^60 , 2^60 + 2^6 - param_type(a, TypeParam(1152921504606847040)), + param_type(kTwo60, real_type(1152921504606847040)), // 2^60 , 2^60 + 2^7 - param_type(a, TypeParam(1152921504606847104)), + param_type(kTwo60, real_type(1152921504606847104)), // double range = 2^8 // 2^60 , 2^60 + 2^8 - param_type(a, TypeParam(1152921504606847232)), + param_type(kTwo60, real_type(1152921504606847232)), // float range = 0 // 2^60 , 2^60 + 2^36 - param_type(a, TypeParam(1152921573326323712)), + param_type(kTwo60, real_type(1152921573326323712)), // 2^60 , 2^60 + 2^37 - param_type(a, TypeParam(1152921642045800448)), + param_type(kTwo60, real_type(1152921642045800448)), // float range = 2^38 // 2^60 , 2^60 + 2^38 - param_type(a, TypeParam(1152921779484753920)), + param_type(kTwo60, real_type(1152921779484753920)), // Limits - param_type(0, std::numeric_limits::max()), - param_type(std::numeric_limits::lowest(), 0), - param_type(0, std::numeric_limits::epsilon()), - param_type(-std::numeric_limits::epsilon(), - std::numeric_limits::epsilon()), - param_type(std::numeric_limits::epsilon(), - 2 * std::numeric_limits::epsilon()), + param_type(0, kMax), + param_type(kLowest, 0), + param_type(0, kMin), + param_type(0, kEpsilon), + param_type(-kEpsilon, kEpsilon), + param_type(0, kOneMinusE), + param_type(0, kDenormMax), }) { // Validate parameters. const auto a = param.a(); const auto b = param.b(); - absl::uniform_real_distribution before(a, b); + DistributionType before(a, b); EXPECT_EQ(before.a(), param.a()); EXPECT_EQ(before.b(), param.b()); { - absl::uniform_real_distribution via_param(param); + DistributionType via_param(param); EXPECT_EQ(via_param, before); } std::stringstream ss; ss << before; - absl::uniform_real_distribution after(TypeParam(1.0), - TypeParam(3.1)); + DistributionType after(real_type(1.0), real_type(3.1)); EXPECT_NE(before.a(), after.a()); EXPECT_NE(before.b(), after.b()); @@ -168,7 +180,7 @@ TYPED_TEST(UniformRealDistributionTest, ParamSerializeTest) { } } - if (!std::is_same::value) { + if (!std::is_same::value) { // static_cast(long double) can overflow. std::string msg = absl::StrCat("Range: ", static_cast(sample_min), ", ", static_cast(sample_max)); @@ -182,33 +194,52 @@ TYPED_TEST(UniformRealDistributionTest, ParamSerializeTest) { #pragma warning(disable:4756) // Constant arithmetic overflow. #endif TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) { + using DistributionType = absl::uniform_real_distribution; + using real_type = TypeParam; + #if GTEST_HAS_DEATH_TEST // Hi < Lo - EXPECT_DEBUG_DEATH( - { absl::uniform_real_distribution dist(10.0, 1.0); }, ""); + EXPECT_DEBUG_DEATH({ DistributionType dist(10.0, 1.0); }, ""); // Hi - Lo > numeric_limits<>::max() EXPECT_DEBUG_DEATH( { - absl::uniform_real_distribution dist( - std::numeric_limits::lowest(), - std::numeric_limits::max()); + DistributionType dist(std::numeric_limits::lowest(), + std::numeric_limits::max()); + }, + ""); + + // kEpsilon guarantees that max + kEpsilon = inf. + const auto kEpsilon = std::nexttoward( + (std::numeric_limits::max() - + std::nexttoward(std::numeric_limits::max(), 0.0)) / + 2, + std::numeric_limits::max()); + EXPECT_DEBUG_DEATH( + { + DistributionType dist(-kEpsilon, std::numeric_limits::max()); }, ""); + EXPECT_DEBUG_DEATH( + { + DistributionType dist(std::numeric_limits::lowest(), + kEpsilon); + }, + ""); + #endif // GTEST_HAS_DEATH_TEST #if defined(NDEBUG) // opt-mode, for invalid parameters, will generate a garbage value, // but should not enter an infinite loop. absl::InsecureBitGen gen; { - absl::uniform_real_distribution dist(10.0, 1.0); + DistributionType dist(10.0, 1.0); auto x = dist(gen); EXPECT_FALSE(std::isnan(x)) << x; } { - absl::uniform_real_distribution dist( - std::numeric_limits::lowest(), - std::numeric_limits::max()); + DistributionType dist(std::numeric_limits::lowest(), + std::numeric_limits::max()); auto x = dist(gen); // Infinite result. EXPECT_FALSE(std::isfinite(x)) << x; @@ -220,6 +251,8 @@ TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) { #endif TYPED_TEST(UniformRealDistributionTest, TestMoments) { + using DistributionType = absl::uniform_real_distribution; + constexpr int kSize = 1000000; std::vector values(kSize); @@ -228,7 +261,7 @@ TYPED_TEST(UniformRealDistributionTest, TestMoments) { // implementation. absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6}; - absl::uniform_real_distribution dist; + DistributionType dist; for (int i = 0; i < kSize; i++) { values[i] = dist(rng); } @@ -242,9 +275,10 @@ TYPED_TEST(UniformRealDistributionTest, TestMoments) { } TYPED_TEST(UniformRealDistributionTest, ChiSquaredTest50) { + using DistributionType = absl::uniform_real_distribution; + using param_type = typename DistributionType::param_type; + using absl::random_internal::kChiSquared; - using param_type = - typename absl::uniform_real_distribution::param_type; constexpr size_t kTrials = 100000; constexpr int kBuckets = 50; @@ -269,7 +303,7 @@ TYPED_TEST(UniformRealDistributionTest, ChiSquaredTest50) { const double factor = kBuckets / (max_val - min_val); std::vector counts(kBuckets, 0); - absl::uniform_real_distribution dist(param); + DistributionType dist(param); for (size_t i = 0; i < kTrials; i++) { auto x = dist(rng); auto bucket = static_cast((x - min_val) * factor); @@ -297,8 +331,11 @@ TYPED_TEST(UniformRealDistributionTest, ChiSquaredTest50) { } TYPED_TEST(UniformRealDistributionTest, StabilityTest) { + using DistributionType = absl::uniform_real_distribution; + using real_type = TypeParam; + // absl::uniform_real_distribution stability relies only on - // random_internal::RandU64ToDouble and random_internal::RandU64ToFloat. + // random_internal::GenerateRealFromBits. absl::random_internal::sequence_urbg urbg( {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull, 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, @@ -307,9 +344,9 @@ TYPED_TEST(UniformRealDistributionTest, StabilityTest) { std::vector output(12); - absl::uniform_real_distribution dist; + DistributionType dist; std::generate(std::begin(output), std::end(output), [&] { - return static_cast(TypeParam(1000000) * dist(urbg)); + return static_cast(real_type(1000000) * dist(urbg)); }); EXPECT_THAT( diff --git a/absl/status/status.h b/absl/status/status.h index 2d003ce6..193db8d8 100644 --- a/absl/status/status.h +++ b/absl/status/status.h @@ -613,10 +613,6 @@ class Status final { const status_internal::Payloads* GetPayloads() const; status_internal::Payloads* GetPayloads(); - // Takes ownership of payload. - static uintptr_t NewRep( - absl::StatusCode code, absl::string_view msg, - std::unique_ptr payload); static bool EqualsSlow(const absl::Status& a, const absl::Status& b); // MSVC 14.0 limitation requires the const. diff --git a/absl/strings/cord.h b/absl/strings/cord.h index 081b6311..5ad4ea0c 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h @@ -768,6 +768,7 @@ class Cord { // Returns nullptr if holding bytes absl::cord_internal::CordRep* tree() const; absl::cord_internal::CordRep* as_tree() const; + const char* as_chars() const; // Returns non-null iff was holding a pointer absl::cord_internal::CordRep* clear(); // Converts to pointer if necessary. @@ -1094,6 +1095,11 @@ inline const char* Cord::InlineRep::data() const { return is_tree() ? nullptr : data_.as_chars(); } +inline const char* Cord::InlineRep::as_chars() const { + assert(!data_.is_tree()); + return data_.as_chars(); +} + inline absl::cord_internal::CordRep* Cord::InlineRep::as_tree() const { assert(data_.is_tree()); return data_.as_tree(); -- cgit v1.2.3