Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(536)

Side by Side Diff: base/metrics/statistics_recorder.cc

Issue 1779503002: Fix StatisticsRecorder to handle re-entry during tests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: always do global UninitializeForTesting when uninitializing Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/metrics/statistics_recorder.h ('k') | base/metrics/statistics_recorder_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/metrics/statistics_recorder.h" 5 #include "base/metrics/statistics_recorder.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/at_exit.h" 9 #include "base/at_exit.h"
10 #include "base/debug/leak_annotations.h" 10 #include "base/debug/leak_annotations.h"
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 } 67 }
68 68
69 return *this; 69 return *this;
70 } 70 }
71 71
72 StatisticsRecorder::~StatisticsRecorder() { 72 StatisticsRecorder::~StatisticsRecorder() {
73 DCHECK(lock_); 73 DCHECK(lock_);
74 DCHECK(histograms_); 74 DCHECK(histograms_);
75 DCHECK(ranges_); 75 DCHECK(ranges_);
76 76
77 // Global clean up. 77 // Clean out what this object created and then restore what existed before.
78 Reset(); 78 Reset();
79 base::AutoLock auto_lock(*lock_);
80 histograms_ = existing_histograms_.release();
81 callbacks_ = existing_callbacks_.release();
82 ranges_ = existing_ranges_.release();
79 } 83 }
80 84
81 // static 85 // static
82 void StatisticsRecorder::Initialize() { 86 void StatisticsRecorder::Initialize() {
83 // Ensure that an instance of the StatisticsRecorder object is created. 87 // Ensure that an instance of the StatisticsRecorder object is created.
84 g_statistics_recorder_.Get(); 88 g_statistics_recorder_.Get();
85 } 89 }
86 90
87 // static 91 // static
88 bool StatisticsRecorder::IsActive() { 92 bool StatisticsRecorder::IsActive() {
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 if (!lock_) 390 if (!lock_)
387 return 0; 391 return 0;
388 392
389 base::AutoLock auto_lock(*lock_); 393 base::AutoLock auto_lock(*lock_);
390 if (!histograms_) 394 if (!histograms_)
391 return 0; 395 return 0;
392 return histograms_->size(); 396 return histograms_->size();
393 } 397 }
394 398
395 // static 399 // static
396 void StatisticsRecorder::ResetForTesting() {
397 // Just call the private version that is used also by the destructor.
398 Reset();
399 }
400
401 // static
402 void StatisticsRecorder::ForgetHistogramForTesting(base::StringPiece name) { 400 void StatisticsRecorder::ForgetHistogramForTesting(base::StringPiece name) {
403 if (histograms_) 401 if (histograms_)
404 histograms_->erase(name); 402 histograms_->erase(name);
405 } 403 }
406 404
405 // static
406 void StatisticsRecorder::UninitializeForTesting() {
407 // Stop now if it's never been initialized.
408 if (lock_ == NULL || histograms_ == NULL)
409 return;
410
411 // Get the global instance and destruct it. It's held in static memory so
412 // can't "delete" it; call the destructor explicitly.
413 DCHECK(g_statistics_recorder_.private_instance_);
414 g_statistics_recorder_.Get().~StatisticsRecorder();
415
416 // Now the ugly part. There's no official way to release a LazyInstance once
417 // created so it's necessary to clear out an internal variable which
418 // shouldn't be publicly visible but is for initialization reasons.
419 g_statistics_recorder_.private_instance_ = 0;
420 }
421
407 // This singleton instance should be started during the single threaded portion 422 // This singleton instance should be started during the single threaded portion
408 // of main(), and hence it is not thread safe. It initializes globals to 423 // of main(), and hence it is not thread safe. It initializes globals to
409 // provide support for all future calls. 424 // provide support for all future calls.
410 StatisticsRecorder::StatisticsRecorder() { 425 StatisticsRecorder::StatisticsRecorder() {
411 DCHECK(!histograms_);
412 if (lock_ == NULL) { 426 if (lock_ == NULL) {
413 // This will leak on purpose. It's the only way to make sure we won't race 427 // This will leak on purpose. It's the only way to make sure we won't race
414 // against the static uninitialization of the module while one of our 428 // against the static uninitialization of the module while one of our
415 // static methods relying on the lock get called at an inappropriate time 429 // static methods relying on the lock get called at an inappropriate time
416 // during the termination phase. Since it's a static data member, we will 430 // during the termination phase. Since it's a static data member, we will
417 // leak one per process, which would be similar to the instance allocated 431 // leak one per process, which would be similar to the instance allocated
418 // during static initialization and released only on process termination. 432 // during static initialization and released only on process termination.
419 lock_ = new base::Lock; 433 lock_ = new base::Lock;
420 } 434 }
435
421 base::AutoLock auto_lock(*lock_); 436 base::AutoLock auto_lock(*lock_);
437
438 existing_histograms_.reset(histograms_);
439 existing_callbacks_.reset(callbacks_);
440 existing_ranges_.reset(ranges_);
441
422 histograms_ = new HistogramMap; 442 histograms_ = new HistogramMap;
423 callbacks_ = new CallbackMap; 443 callbacks_ = new CallbackMap;
424 ranges_ = new RangesMap; 444 ranges_ = new RangesMap;
425 445
426 if (VLOG_IS_ON(1)) 446 if (VLOG_IS_ON(1))
427 AtExitManager::RegisterCallback(&DumpHistogramsToVlog, this); 447 AtExitManager::RegisterCallback(&DumpHistogramsToVlog, this);
428 } 448 }
429 449
430 // static 450 // static
431 void StatisticsRecorder::Reset() { 451 void StatisticsRecorder::Reset() {
(...skipping 29 matching lines...) Expand all
461 // static 481 // static
462 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; 482 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
463 // static 483 // static
464 StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL; 484 StatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL;
465 // static 485 // static
466 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; 486 StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL;
467 // static 487 // static
468 base::Lock* StatisticsRecorder::lock_ = NULL; 488 base::Lock* StatisticsRecorder::lock_ = NULL;
469 489
470 } // namespace base 490 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/statistics_recorder.h ('k') | base/metrics/statistics_recorder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698