| Index: base/metrics/sample_vector.h
|
| diff --git a/base/metrics/sample_vector.h b/base/metrics/sample_vector.h
|
| index ee26c52101912df69856d107ebc330390269b0cf..84cdbc9fad2469dbf71079e3f306789918856b75 100644
|
| --- a/base/metrics/sample_vector.h
|
| +++ b/base/metrics/sample_vector.h
|
| @@ -14,28 +14,27 @@
|
| #include <memory>
|
| #include <vector>
|
|
|
| +#include "base/atomicops.h"
|
| #include "base/compiler_specific.h"
|
| #include "base/gtest_prod_util.h"
|
| #include "base/macros.h"
|
| #include "base/metrics/histogram_base.h"
|
| #include "base/metrics/histogram_samples.h"
|
| +#include "base/metrics/persistent_memory_allocator.h"
|
|
|
| namespace base {
|
|
|
| class BucketRanges;
|
|
|
| -class BASE_EXPORT SampleVector : public HistogramSamples {
|
| +class BASE_EXPORT SampleVectorBase : public HistogramSamples {
|
| public:
|
| - explicit SampleVector(const BucketRanges* bucket_ranges);
|
| - SampleVector(uint64_t id, const BucketRanges* bucket_ranges);
|
| - SampleVector(uint64_t id,
|
| - HistogramBase::AtomicCount* counts,
|
| - size_t counts_size,
|
| - Metadata* meta,
|
| - const BucketRanges* bucket_ranges);
|
| - ~SampleVector() override;
|
| + SampleVectorBase(uint64_t id, const BucketRanges* bucket_ranges);
|
| + SampleVectorBase(uint64_t id,
|
| + Metadata* meta,
|
| + const BucketRanges* bucket_ranges);
|
| + ~SampleVectorBase() override;
|
|
|
| - // HistogramSamples implementation:
|
| + // HistogramSamples:
|
| void Accumulate(HistogramBase::Sample value,
|
| HistogramBase::Count count) override;
|
| HistogramBase::Count GetCount(HistogramBase::Sample value) const override;
|
| @@ -52,25 +51,93 @@ class BASE_EXPORT SampleVector : public HistogramSamples {
|
|
|
| virtual size_t GetBucketIndex(HistogramBase::Sample value) const;
|
|
|
| + void MoveSingleSampleToCounts();
|
| +
|
| + void MountCountsStorage();
|
| + virtual bool MountExistingCountsStorage() const = 0;
|
| + virtual HistogramBase::Count* CreateCountsStorageWhileLocked() = 0;
|
| +
|
| + HistogramBase::AtomicCount* counts() {
|
| + return reinterpret_cast<HistogramBase::AtomicCount*>(
|
| + subtle::NoBarrier_Load(&counts_));
|
| + }
|
| +
|
| + const HistogramBase::AtomicCount* counts() const {
|
| + return reinterpret_cast<HistogramBase::AtomicCount*>(
|
| + subtle::NoBarrier_Load(&counts_));
|
| + }
|
| +
|
| + void set_counts(HistogramBase::AtomicCount* counts) const {
|
| + subtle::NoBarrier_Store(&counts_, reinterpret_cast<uintptr_t>(counts));
|
| + }
|
| +
|
| + size_t counts_size() const { return counts_size_; }
|
| +
|
| private:
|
| + friend class SampleVectorTest;
|
| FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts);
|
| FRIEND_TEST_ALL_PREFIXES(SharedHistogramTest, CorruptSampleCounts);
|
|
|
| - // In the case where this class manages the memory, here it is.
|
| - std::vector<HistogramBase::AtomicCount> local_counts_;
|
| -
|
| - // These are raw pointers rather than objects for flexibility. The actual
|
| - // memory is either managed by local_counts_ above or by an external object
|
| - // and passed in directly.
|
| - HistogramBase::AtomicCount* counts_;
|
| - size_t counts_size_;
|
| + // |counts_| is actually a pointer to a HistogramBase::AtomicCount array but
|
| + // is held as an AtomicWord for concurrency reasons. When combined with the
|
| + // single_sample held in the metadata, there are four possible states:
|
| + // 1) single_sample == zero, counts_ == null
|
| + // 2) single_sample != zero, counts_ == null
|
| + // 3) single_sample != zero, counts_ != null BUT IS EMPTY
|
| + // 4) single_sample == zero, counts_ != null and may have data
|
| + // Once |counts_| is set, it can never revert and any existing single-sample
|
| + // must be moved to this storage. It is mutable because changing it doesn't
|
| + // change the (const) data but must adapt if a non-const object causes the
|
| + // storage to be allocated and updated.
|
| + mutable subtle::AtomicWord counts_ = 0;
|
| + const size_t counts_size_;
|
|
|
| // Shares the same BucketRanges with Histogram object.
|
| const BucketRanges* const bucket_ranges_;
|
|
|
| + DISALLOW_COPY_AND_ASSIGN(SampleVectorBase);
|
| +};
|
| +
|
| +// A sample vector that uses local memory for the counts array.
|
| +class BASE_EXPORT SampleVector : public SampleVectorBase {
|
| + public:
|
| + explicit SampleVector(const BucketRanges* bucket_ranges);
|
| + SampleVector(uint64_t id, const BucketRanges* bucket_ranges);
|
| + ~SampleVector() override;
|
| +
|
| + private:
|
| + // SampleVectorBase:
|
| + bool MountExistingCountsStorage() const override;
|
| + HistogramBase::Count* CreateCountsStorageWhileLocked() override;
|
| +
|
| + // Simple local storage for counts.
|
| + mutable std::vector<HistogramBase::AtomicCount> local_counts_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(SampleVector);
|
| };
|
|
|
| +// A sample vector that uses persistent memory for the counts array.
|
| +class BASE_EXPORT PersistentSampleVector : public SampleVectorBase {
|
| + public:
|
| + PersistentSampleVector(uint64_t id,
|
| + const BucketRanges* bucket_ranges,
|
| + Metadata* meta,
|
| + const DelayedPersistentAllocation& counts);
|
| + ~PersistentSampleVector() override;
|
| +
|
| + private:
|
| + // SampleVectorBase:
|
| + bool MountExistingCountsStorage() const override;
|
| + HistogramBase::Count* CreateCountsStorageWhileLocked() override;
|
| +
|
| + // Persistent storage for counts.
|
| + DelayedPersistentAllocation persistent_counts_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(PersistentSampleVector);
|
| +};
|
| +
|
| +// An iterator for sample vectors. This could be defined privately in the .cc
|
| +// file but is here for easy testing.
|
| class BASE_EXPORT SampleVectorIterator : public SampleCountIterator {
|
| public:
|
| SampleVectorIterator(const std::vector<HistogramBase::AtomicCount>* counts,
|
|
|