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
10namespace base {
11
12namespace {
13
14class SampleCountPickleIterator : public SampleCountIterator {
15 public:
16  explicit SampleCountPickleIterator(PickleIterator* iter);
17
18  virtual bool Done() const OVERRIDE;
19  virtual void Next() OVERRIDE;
20  virtual void Get(HistogramBase::Sample* min,
21                   HistogramBase::Sample* max,
22                   HistogramBase::Count* count) const OVERRIDE;
23 private:
24  PickleIterator* const iter_;
25
26  HistogramBase::Sample min_;
27  HistogramBase::Sample max_;
28  HistogramBase::Count count_;
29  bool is_done_;
30};
31
32SampleCountPickleIterator::SampleCountPickleIterator(PickleIterator* iter)
33    : iter_(iter),
34      is_done_(false) {
35  Next();
36}
37
38bool SampleCountPickleIterator::Done() const {
39  return is_done_;
40}
41
42void SampleCountPickleIterator::Next() {
43  DCHECK(!Done());
44  if (!iter_->ReadInt(&min_) ||
45      !iter_->ReadInt(&max_) ||
46      !iter_->ReadInt(&count_))
47    is_done_ = true;
48}
49
50void SampleCountPickleIterator::Get(HistogramBase::Sample* min,
51                                    HistogramBase::Sample* max,
52                                    HistogramBase::Count* count) const {
53  DCHECK(!Done());
54  *min = min_;
55  *max = max_;
56  *count = count_;
57}
58
59}  // namespace
60
61HistogramSamples::HistogramSamples() : sum_(0), redundant_count_(0) {}
62
63HistogramSamples::~HistogramSamples() {}
64
65void HistogramSamples::Add(const HistogramSamples& other) {
66  sum_ += other.sum();
67  HistogramBase::Count old_redundant_count =
68      subtle::NoBarrier_Load(&redundant_count_);
69  subtle::NoBarrier_Store(&redundant_count_,
70      old_redundant_count + other.redundant_count());
71  bool success = AddSubtractImpl(other.Iterator().get(), ADD);
72  DCHECK(success);
73}
74
75bool HistogramSamples::AddFromPickle(PickleIterator* iter) {
76  int64 sum;
77  HistogramBase::Count redundant_count;
78
79  if (!iter->ReadInt64(&sum) || !iter->ReadInt(&redundant_count))
80    return false;
81  sum_ += sum;
82  HistogramBase::Count old_redundant_count =
83      subtle::NoBarrier_Load(&redundant_count_);
84  subtle::NoBarrier_Store(&redundant_count_,
85                          old_redundant_count + redundant_count);
86
87  SampleCountPickleIterator pickle_iter(iter);
88  return AddSubtractImpl(&pickle_iter, ADD);
89}
90
91void HistogramSamples::Subtract(const HistogramSamples& other) {
92  sum_ -= other.sum();
93  HistogramBase::Count old_redundant_count =
94      subtle::NoBarrier_Load(&redundant_count_);
95  subtle::NoBarrier_Store(&redundant_count_,
96                          old_redundant_count - other.redundant_count());
97  bool success = AddSubtractImpl(other.Iterator().get(), SUBTRACT);
98  DCHECK(success);
99}
100
101bool HistogramSamples::Serialize(Pickle* pickle) const {
102  if (!pickle->WriteInt64(sum_) ||
103      !pickle->WriteInt(subtle::NoBarrier_Load(&redundant_count_)))
104    return false;
105
106  HistogramBase::Sample min;
107  HistogramBase::Sample max;
108  HistogramBase::Count count;
109  for (scoped_ptr<SampleCountIterator> it = Iterator();
110       !it->Done();
111       it->Next()) {
112    it->Get(&min, &max, &count);
113    if (!pickle->WriteInt(min) ||
114        !pickle->WriteInt(max) ||
115        !pickle->WriteInt(count))
116      return false;
117  }
118  return true;
119}
120
121void HistogramSamples::IncreaseSum(int64 diff) {
122  sum_ += diff;
123}
124
125void HistogramSamples::IncreaseRedundantCount(HistogramBase::Count diff) {
126  subtle::NoBarrier_Store(&redundant_count_,
127      subtle::NoBarrier_Load(&redundant_count_) + diff);
128}
129
130SampleCountIterator::~SampleCountIterator() {}
131
132bool SampleCountIterator::GetBucketIndex(size_t* index) const {
133  DCHECK(!Done());
134  return false;
135}
136
137}  // namespace base
138