OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |