1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/metrics/histogram_samples.h" 6 7 #include "base/compiler_specific.h" 8 #include "base/pickle.h" 9 10 namespace base { 11 12 namespace { 13 14 class SampleCountPickleIterator : public SampleCountIterator { 15 public: 16 explicit SampleCountPickleIterator(PickleIterator* iter); 17 18 bool Done() const override; 19 void Next() override; 20 void Get(HistogramBase::Sample* min, 21 HistogramBase::Sample* max, 22 HistogramBase::Count* count) const override; 23 24 private: 25 PickleIterator* const iter_; 26 27 HistogramBase::Sample min_; 28 HistogramBase::Sample max_; 29 HistogramBase::Count count_; 30 bool is_done_; 31 }; 32 33 SampleCountPickleIterator::SampleCountPickleIterator(PickleIterator* iter) 34 : iter_(iter), 35 is_done_(false) { 36 Next(); 37 } 38 39 bool SampleCountPickleIterator::Done() const { 40 return is_done_; 41 } 42 43 void SampleCountPickleIterator::Next() { 44 DCHECK(!Done()); 45 if (!iter_->ReadInt(&min_) || 46 !iter_->ReadInt(&max_) || 47 !iter_->ReadInt(&count_)) 48 is_done_ = true; 49 } 50 51 void SampleCountPickleIterator::Get(HistogramBase::Sample* min, 52 HistogramBase::Sample* max, 53 HistogramBase::Count* count) const { 54 DCHECK(!Done()); 55 *min = min_; 56 *max = max_; 57 *count = count_; 58 } 59 60 } // namespace 61 62 // Don't try to delegate behavior to the constructor below that accepts a 63 // Matadata pointer by passing &local_meta_. Such cannot be reliably passed 64 // because it has not yet been constructed -- no member variables have; the 65 // class itself is in the middle of being constructed. Using it to 66 // initialize meta_ is okay because the object now exists and local_meta_ 67 // is before meta_ in the construction order. 68 HistogramSamples::HistogramSamples(uint64_t id) 69 : meta_(&local_meta_) { 70 meta_->id = id; 71 } 72 73 HistogramSamples::HistogramSamples(uint64_t id, Metadata* meta) 74 : meta_(meta) { 75 DCHECK(meta_->id == 0 || meta_->id == id); 76 77 // It's possible that |meta| is contained in initialized, read-only memory 78 // so it's essential that no write be done in that case. 79 if (!meta_->id) 80 meta_->id = id; 81 } 82 83 HistogramSamples::~HistogramSamples() {} 84 85 void HistogramSamples::Add(const HistogramSamples& other) { 86 IncreaseSum(other.sum()); 87 subtle::NoBarrier_AtomicIncrement(&meta_->redundant_count, 88 other.redundant_count()); 89 bool success = AddSubtractImpl(other.Iterator().get(), ADD); 90 DCHECK(success); 91 } 92 93 bool HistogramSamples::AddFromPickle(PickleIterator* iter) { 94 int64_t sum; 95 HistogramBase::Count redundant_count; 96 97 if (!iter->ReadInt64(&sum) || !iter->ReadInt(&redundant_count)) 98 return false; 99 100 IncreaseSum(sum); 101 subtle::NoBarrier_AtomicIncrement(&meta_->redundant_count, 102 redundant_count); 103 104 SampleCountPickleIterator pickle_iter(iter); 105 return AddSubtractImpl(&pickle_iter, ADD); 106 } 107 108 void HistogramSamples::Subtract(const HistogramSamples& other) { 109 IncreaseSum(-other.sum()); 110 subtle::NoBarrier_AtomicIncrement(&meta_->redundant_count, 111 -other.redundant_count()); 112 bool success = AddSubtractImpl(other.Iterator().get(), SUBTRACT); 113 DCHECK(success); 114 } 115 116 bool HistogramSamples::Serialize(Pickle* pickle) const { 117 if (!pickle->WriteInt64(sum())) 118 return false; 119 if (!pickle->WriteInt(redundant_count())) 120 return false; 121 122 HistogramBase::Sample min; 123 HistogramBase::Sample max; 124 HistogramBase::Count count; 125 for (std::unique_ptr<SampleCountIterator> it = Iterator(); !it->Done(); 126 it->Next()) { 127 it->Get(&min, &max, &count); 128 if (!pickle->WriteInt(min) || 129 !pickle->WriteInt(max) || 130 !pickle->WriteInt(count)) 131 return false; 132 } 133 return true; 134 } 135 136 void HistogramSamples::IncreaseSum(int64_t diff) { 137 #ifdef ARCH_CPU_64_BITS 138 subtle::NoBarrier_AtomicIncrement(&meta_->sum, diff); 139 #else 140 meta_->sum += diff; 141 #endif 142 } 143 144 void HistogramSamples::IncreaseRedundantCount(HistogramBase::Count diff) { 145 subtle::NoBarrier_AtomicIncrement(&meta_->redundant_count, diff); 146 } 147 148 SampleCountIterator::~SampleCountIterator() {} 149 150 bool SampleCountIterator::GetBucketIndex(size_t* /*index*/) const { 151 DCHECK(!Done()); 152 return false; 153 } 154 155 } // namespace base 156