| Index: base/metrics/histogram.cc
|
| ===================================================================
|
| --- base/metrics/histogram.cc (revision 69955)
|
| +++ base/metrics/histogram.cc (working copy)
|
| @@ -904,12 +904,21 @@
|
| // provide support for all future calls.
|
| StatisticsRecorder::StatisticsRecorder() {
|
| DCHECK(!histograms_);
|
| - lock_ = new Lock;
|
| + if (lock_ == NULL) {
|
| + // This will leak on purpose. It's the only way to make sure we won't race
|
| + // against the static uninitialization of the module while one of our
|
| + // static methods relying on the lock get called at an inappropriate time
|
| + // during the termination phase. Since it's a static data member, we will
|
| + // leak one per process, which would be similar to the instance allocated
|
| + // during static initialization and released only on process termination.
|
| + lock_ = new Lock;
|
| + }
|
| + AutoLock auto_lock(*lock_);
|
| histograms_ = new HistogramMap;
|
| }
|
|
|
| StatisticsRecorder::~StatisticsRecorder() {
|
| - DCHECK(histograms_);
|
| + DCHECK(histograms_ && lock_);
|
|
|
| if (dump_on_exit_) {
|
| std::string output;
|
| @@ -917,14 +926,22 @@
|
| LOG(INFO) << output;
|
| }
|
| // Clean up.
|
| - delete histograms_;
|
| - histograms_ = NULL;
|
| - delete lock_;
|
| - lock_ = NULL;
|
| + HistogramMap* histograms = NULL;
|
| + {
|
| + AutoLock auto_lock(*lock_);
|
| + histograms = histograms_;
|
| + histograms_ = NULL;
|
| + }
|
| + delete histograms;
|
| + // We don't delete lock_ on purpose to avoid having to properly protect
|
| + // against it going away after we checked for NULL in the static methods.
|
| }
|
|
|
| // static
|
| -bool StatisticsRecorder::WasStarted() {
|
| +bool StatisticsRecorder::IsActive() {
|
| + if (lock_ == NULL)
|
| + return false;
|
| + AutoLock auto_lock(*lock_);
|
| return NULL != histograms_;
|
| }
|
|
|
| @@ -935,10 +952,12 @@
|
| // destroyed before assignment (when value was returned by new).
|
| // static
|
| void StatisticsRecorder::Register(Histogram* histogram) {
|
| + if (lock_ == NULL)
|
| + return;
|
| + AutoLock auto_lock(*lock_);
|
| if (!histograms_)
|
| return;
|
| const std::string name = histogram->histogram_name();
|
| - AutoLock auto_lock(*lock_);
|
| // Avoid overwriting a previous registration.
|
| if (histograms_->end() == histograms_->find(name))
|
| (*histograms_)[name] = histogram;
|
| @@ -947,7 +966,7 @@
|
| // static
|
| void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
|
| std::string* output) {
|
| - if (!histograms_)
|
| + if (!IsActive())
|
| return;
|
| output->append("<html><head><title>About Histograms");
|
| if (!query.empty())
|
| @@ -971,7 +990,7 @@
|
| // static
|
| void StatisticsRecorder::WriteGraph(const std::string& query,
|
| std::string* output) {
|
| - if (!histograms_)
|
| + if (!IsActive())
|
| return;
|
| if (query.length())
|
| StringAppendF(output, "Collections of histograms for %s\n", query.c_str());
|
| @@ -990,9 +1009,11 @@
|
|
|
| // static
|
| void StatisticsRecorder::GetHistograms(Histograms* output) {
|
| + if (lock_ == NULL)
|
| + return;
|
| + AutoLock auto_lock(*lock_);
|
| if (!histograms_)
|
| return;
|
| - AutoLock auto_lock(*lock_);
|
| for (HistogramMap::iterator it = histograms_->begin();
|
| histograms_->end() != it;
|
| ++it) {
|
| @@ -1003,9 +1024,11 @@
|
|
|
| bool StatisticsRecorder::FindHistogram(const std::string& name,
|
| scoped_refptr<Histogram>* histogram) {
|
| + if (lock_ == NULL)
|
| + return false;
|
| + AutoLock auto_lock(*lock_);
|
| if (!histograms_)
|
| return false;
|
| - AutoLock auto_lock(*lock_);
|
| HistogramMap::iterator it = histograms_->find(name);
|
| if (histograms_->end() == it)
|
| return false;
|
| @@ -1016,7 +1039,11 @@
|
| // private static
|
| void StatisticsRecorder::GetSnapshot(const std::string& query,
|
| Histograms* snapshot) {
|
| + if (lock_ == NULL)
|
| + return;
|
| AutoLock auto_lock(*lock_);
|
| + if (!histograms_)
|
| + return;
|
| for (HistogramMap::iterator it = histograms_->begin();
|
| histograms_->end() != it;
|
| ++it) {
|
|
|