Index: base/metrics/histogram.cc |
=================================================================== |
--- base/metrics/histogram.cc (revision 80382) |
+++ base/metrics/histogram.cc (working copy) |
@@ -73,9 +73,12 @@ |
// static |
const size_t Histogram::kBucketCount_MAX = 16384u; |
-scoped_refptr<Histogram> Histogram::FactoryGet(const std::string& name, |
- Sample minimum, Sample maximum, size_t bucket_count, Flags flags) { |
- scoped_refptr<Histogram> histogram(NULL); |
+Histogram* Histogram::FactoryGet(const std::string& name, |
+ Sample minimum, |
+ Sample maximum, |
+ size_t bucket_count, |
+ Flags flags) { |
+ Histogram* histogram(NULL); |
// Defensive code. |
if (minimum < 1) |
@@ -84,10 +87,16 @@ |
maximum = kSampleType_MAX - 1; |
if (!StatisticsRecorder::FindHistogram(name, &histogram)) { |
- histogram = new Histogram(name, minimum, maximum, bucket_count); |
- histogram->InitializeBucketRange(); |
- histogram->SetFlags(flags); |
- StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); |
+ // Extra variable is not needed... but this keeps this section basically |
+ // identical to other derived classes in this file (and compiler will |
+ // optimize away the extra variable. |
+ // To avoid racy destruction at shutdown, the following will be leaked. |
+ Histogram* tentative_histogram = |
+ new Histogram(name, minimum, maximum, bucket_count); |
+ tentative_histogram->InitializeBucketRange(); |
+ tentative_histogram->SetFlags(flags); |
+ histogram = |
+ StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
} |
DCHECK_EQ(HISTOGRAM, histogram->histogram_type()); |
@@ -95,11 +104,11 @@ |
return histogram; |
} |
-scoped_refptr<Histogram> Histogram::FactoryTimeGet(const std::string& name, |
- TimeDelta minimum, |
- TimeDelta maximum, |
- size_t bucket_count, |
- Flags flags) { |
+Histogram* Histogram::FactoryTimeGet(const std::string& name, |
+ TimeDelta minimum, |
+ TimeDelta maximum, |
+ size_t bucket_count, |
+ Flags flags) { |
return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), |
bucket_count, flags); |
} |
@@ -259,7 +268,7 @@ |
DCHECK_NE(NOT_VALID_IN_RENDERER, histogram_type); |
- scoped_refptr<Histogram> render_histogram(NULL); |
+ Histogram* render_histogram(NULL); |
if (histogram_type == HISTOGRAM) { |
render_histogram = Histogram::FactoryGet( |
@@ -761,12 +770,12 @@ |
LinearHistogram::~LinearHistogram() { |
} |
-scoped_refptr<Histogram> LinearHistogram::FactoryGet(const std::string& name, |
- Sample minimum, |
- Sample maximum, |
- size_t bucket_count, |
- Flags flags) { |
- scoped_refptr<Histogram> histogram(NULL); |
+Histogram* LinearHistogram::FactoryGet(const std::string& name, |
+ Sample minimum, |
+ Sample maximum, |
+ size_t bucket_count, |
+ Flags flags) { |
+ Histogram* histogram(NULL); |
if (minimum < 1) |
minimum = 1; |
@@ -774,12 +783,13 @@ |
maximum = kSampleType_MAX - 1; |
if (!StatisticsRecorder::FindHistogram(name, &histogram)) { |
- LinearHistogram* linear_histogram = |
+ // To avoid racy destruction at shutdown, the following will be leaked. |
+ LinearHistogram* tentative_histogram = |
new LinearHistogram(name, minimum, maximum, bucket_count); |
- linear_histogram->InitializeBucketRange(); |
- histogram = linear_histogram; |
- histogram->SetFlags(flags); |
- StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); |
+ tentative_histogram->InitializeBucketRange(); |
+ tentative_histogram->SetFlags(flags); |
+ histogram = |
+ StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
} |
DCHECK_EQ(LINEAR_HISTOGRAM, histogram->histogram_type()); |
@@ -787,12 +797,11 @@ |
return histogram; |
} |
-scoped_refptr<Histogram> LinearHistogram::FactoryTimeGet( |
- const std::string& name, |
- TimeDelta minimum, |
- TimeDelta maximum, |
- size_t bucket_count, |
- Flags flags) { |
+Histogram* LinearHistogram::FactoryTimeGet(const std::string& name, |
+ TimeDelta minimum, |
+ TimeDelta maximum, |
+ size_t bucket_count, |
+ Flags flags) { |
return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), |
bucket_count, flags); |
} |
@@ -862,16 +871,16 @@ |
// This section provides implementation for BooleanHistogram. |
//------------------------------------------------------------------------------ |
-scoped_refptr<Histogram> BooleanHistogram::FactoryGet(const std::string& name, |
- Flags flags) { |
- scoped_refptr<Histogram> histogram(NULL); |
+Histogram* BooleanHistogram::FactoryGet(const std::string& name, Flags flags) { |
+ Histogram* histogram(NULL); |
if (!StatisticsRecorder::FindHistogram(name, &histogram)) { |
- BooleanHistogram* boolean_histogram = new BooleanHistogram(name); |
- boolean_histogram->InitializeBucketRange(); |
- histogram = boolean_histogram; |
- histogram->SetFlags(flags); |
- StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); |
+ // To avoid racy destruction at shutdown, the following will be leaked. |
+ BooleanHistogram* tentative_histogram = new BooleanHistogram(name); |
+ tentative_histogram->InitializeBucketRange(); |
+ tentative_histogram->SetFlags(flags); |
+ histogram = |
+ StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
} |
DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->histogram_type()); |
@@ -894,11 +903,10 @@ |
// CustomHistogram: |
//------------------------------------------------------------------------------ |
-scoped_refptr<Histogram> CustomHistogram::FactoryGet( |
- const std::string& name, |
- const std::vector<Sample>& custom_ranges, |
- Flags flags) { |
- scoped_refptr<Histogram> histogram(NULL); |
+Histogram* CustomHistogram::FactoryGet(const std::string& name, |
+ const std::vector<Sample>& custom_ranges, |
+ Flags flags) { |
+ Histogram* histogram(NULL); |
// Remove the duplicates in the custom ranges array. |
std::vector<int> ranges = custom_ranges; |
@@ -914,11 +922,12 @@ |
DCHECK_LT(ranges.back(), kSampleType_MAX); |
if (!StatisticsRecorder::FindHistogram(name, &histogram)) { |
- CustomHistogram* custom_histogram = new CustomHistogram(name, ranges); |
- custom_histogram->InitializedCustomBucketRange(ranges); |
- histogram = custom_histogram; |
- histogram->SetFlags(flags); |
- StatisticsRecorder::RegisterOrDiscardDuplicate(&histogram); |
+ // To avoid racy destruction at shutdown, the following will be leaked. |
+ CustomHistogram* tentative_histogram = new CustomHistogram(name, ranges); |
+ tentative_histogram->InitializedCustomBucketRange(ranges); |
+ tentative_histogram->SetFlags(flags); |
+ histogram = |
+ StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
} |
DCHECK_EQ(histogram->histogram_type(), CUSTOM_HISTOGRAM); |
@@ -1004,27 +1013,23 @@ |
return NULL != histograms_; |
} |
-// Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a |
-// reference, and we are called while in the Histogram constructor. In that |
-// scenario, a ref_ptr would have incremented the ref count when the histogram |
-// was passed to us, decremented it when we returned, and the instance would be |
-// destroyed before assignment (when value was returned by new). |
-// static |
-void StatisticsRecorder::RegisterOrDiscardDuplicate( |
- scoped_refptr<Histogram>* histogram) { |
- DCHECK((*histogram)->HasValidRangeChecksum()); |
+Histogram* StatisticsRecorder::RegisterOrDeleteDuplicate(Histogram* histogram) { |
+ DCHECK(histogram->HasValidRangeChecksum()); |
if (lock_ == NULL) |
- return; |
+ return histogram; |
base::AutoLock auto_lock(*lock_); |
if (!histograms_) |
- return; |
- const std::string name = (*histogram)->histogram_name(); |
+ return histogram; |
+ const std::string name = histogram->histogram_name(); |
HistogramMap::iterator it = histograms_->find(name); |
// Avoid overwriting a previous registration. |
- if (histograms_->end() == it) |
- (*histograms_)[name] = *histogram; |
- else |
- *histogram = it->second; |
+ if (histograms_->end() == it) { |
+ (*histograms_)[name] = histogram; |
+ } else { |
+ delete histogram; // We already have one by this name. |
+ histogram = it->second; |
+ } |
+ return histogram; |
} |
// static |
@@ -1087,7 +1092,7 @@ |
} |
bool StatisticsRecorder::FindHistogram(const std::string& name, |
- scoped_refptr<Histogram>* histogram) { |
+ Histogram** histogram) { |
if (lock_ == NULL) |
return false; |
base::AutoLock auto_lock(*lock_); |