1// Copyright (c) 2010 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/stats_counters.h"
6
7namespace base {
8
9StatsCounter::StatsCounter(const std::string& name)
10    : counter_id_(-1) {
11  // We prepend the name with 'c:' to indicate that it is a counter.
12  if (StatsTable::current()) {
13    // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
14    // static.
15    name_ = "c:";
16    name_.append(name);
17  }
18}
19
20StatsCounter::~StatsCounter() {
21}
22
23void StatsCounter::Set(int value) {
24  int* loc = GetPtr();
25  if (loc)
26    *loc = value;
27}
28
29void StatsCounter::Add(int value) {
30  int* loc = GetPtr();
31  if (loc)
32    (*loc) += value;
33}
34
35StatsCounter::StatsCounter()
36    : counter_id_(-1) {
37}
38
39int* StatsCounter::GetPtr() {
40  StatsTable* table = StatsTable::current();
41  if (!table)
42    return NULL;
43
44  // If counter_id_ is -1, then we haven't looked it up yet.
45  if (counter_id_ == -1) {
46    counter_id_ = table->FindCounter(name_);
47    if (table->GetSlot() == 0) {
48      if (!table->RegisterThread(std::string())) {
49        // There is no room for this thread.  This thread
50        // cannot use counters.
51        counter_id_ = 0;
52        return NULL;
53      }
54    }
55  }
56
57  // If counter_id_ is > 0, then we have a valid counter.
58  if (counter_id_ > 0)
59    return table->GetLocation(counter_id_, table->GetSlot());
60
61  // counter_id_ was zero, which means the table is full.
62  return NULL;
63}
64
65
66StatsCounterTimer::StatsCounterTimer(const std::string& name) {
67  // we prepend the name with 't:' to indicate that it is a timer.
68  if (StatsTable::current()) {
69    // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
70    // static.
71    name_ = "t:";
72    name_.append(name);
73  }
74}
75
76StatsCounterTimer::~StatsCounterTimer() {
77}
78
79void StatsCounterTimer::Start() {
80  if (!Enabled())
81    return;
82  start_time_ = TimeTicks::Now();
83  stop_time_ = TimeTicks();
84}
85
86// Stop the timer and record the results.
87void StatsCounterTimer::Stop() {
88  if (!Enabled() || !Running())
89    return;
90  stop_time_ = TimeTicks::Now();
91  Record();
92}
93
94// Returns true if the timer is running.
95bool StatsCounterTimer::Running() {
96  return Enabled() && !start_time_.is_null() && stop_time_.is_null();
97}
98
99// Accept a TimeDelta to increment.
100void StatsCounterTimer::AddTime(TimeDelta time) {
101  Add(static_cast<int>(time.InMilliseconds()));
102}
103
104void StatsCounterTimer::Record() {
105  AddTime(stop_time_ - start_time_);
106}
107
108
109StatsRate::StatsRate(const std::string& name)
110    : StatsCounterTimer(name),
111      counter_(name),
112      largest_add_(std::string(" ").append(name).append("MAX")) {
113}
114
115StatsRate::~StatsRate() {
116}
117
118void StatsRate::Add(int value) {
119  counter_.Increment();
120  StatsCounterTimer::Add(value);
121  if (value > largest_add_.value())
122    largest_add_.Set(value);
123}
124
125}  // namespace base
126