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

Side by Side Diff: base/time/time_win.cc

Issue 302903004: Make HighResNowSingleton a leaky LazyInstance (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix build Created 6 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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 5
6 // Windows Timer Primer 6 // Windows Timer Primer
7 // 7 //
8 // A good article: http://www.ddj.com/windows/184416651 8 // A good article: http://www.ddj.com/windows/184416651
9 // A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258 9 // A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258
10 // 10 //
(...skipping 24 matching lines...) Expand all
35 // there is nothing else to waken the Wait. 35 // there is nothing else to waken the Wait.
36 36
37 #include "base/time/time.h" 37 #include "base/time/time.h"
38 38
39 #pragma comment(lib, "winmm.lib") 39 #pragma comment(lib, "winmm.lib")
40 #include <windows.h> 40 #include <windows.h>
41 #include <mmsystem.h> 41 #include <mmsystem.h>
42 42
43 #include "base/basictypes.h" 43 #include "base/basictypes.h"
44 #include "base/cpu.h" 44 #include "base/cpu.h"
45 #include "base/lazy_instance.h"
45 #include "base/logging.h" 46 #include "base/logging.h"
46 #include "base/memory/singleton.h"
47 #include "base/synchronization/lock.h" 47 #include "base/synchronization/lock.h"
48 48
49 using base::Time; 49 using base::Time;
50 using base::TimeDelta; 50 using base::TimeDelta;
51 using base::TimeTicks; 51 using base::TimeTicks;
52 52
53 namespace { 53 namespace {
54 54
55 // From MSDN, FILETIME "Contains a 64-bit value representing the number of 55 // From MSDN, FILETIME "Contains a 64-bit value representing the number of
56 // 100-nanosecond intervals since January 1, 1601 (UTC)." 56 // 100-nanosecond intervals since January 1, 1601 (UTC)."
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 // give consistent result on a multiprocessor computer, but it is unreliable in 351 // give consistent result on a multiprocessor computer, but it is unreliable in
352 // reality due to bugs in BIOS or HAL on some, especially old computers. 352 // reality due to bugs in BIOS or HAL on some, especially old computers.
353 // With recent updates on HAL and newer BIOS, QPC is getting more reliable but 353 // With recent updates on HAL and newer BIOS, QPC is getting more reliable but
354 // it should be used with caution. 354 // it should be used with caution.
355 // 355 //
356 // (3) System time. The system time provides a low-resolution (typically 10ms 356 // (3) System time. The system time provides a low-resolution (typically 10ms
357 // to 55 milliseconds) time stamp but is comparatively less expensive to 357 // to 55 milliseconds) time stamp but is comparatively less expensive to
358 // retrieve and more reliable. 358 // retrieve and more reliable.
359 class HighResNowSingleton { 359 class HighResNowSingleton {
360 public: 360 public:
361 static HighResNowSingleton* GetInstance() { 361 HighResNowSingleton()
362 return Singleton<HighResNowSingleton>::get(); 362 : ticks_per_second_(0),
363 skew_(0) {
364 InitializeClock();
365
366 base::CPU cpu;
367 if (IsBuggyAthlon(cpu))
368 DisableHighResClock();
363 } 369 }
364 370
365 bool IsUsingHighResClock() { 371 bool IsUsingHighResClock() {
366 return ticks_per_second_ != 0.0; 372 return ticks_per_second_ != 0.0;
367 } 373 }
368 374
369 void DisableHighResClock() { 375 void DisableHighResClock() {
370 ticks_per_second_ = 0.0; 376 ticks_per_second_ = 0.0;
371 } 377 }
372 378
(...skipping 19 matching lines...) Expand all
392 // overflow and precision issues. Think twice before simplifying! 398 // overflow and precision issues. Think twice before simplifying!
393 int64 whole_seconds = qpc_value / ticks_per_second_; 399 int64 whole_seconds = qpc_value / ticks_per_second_;
394 int64 leftover_ticks = qpc_value % ticks_per_second_; 400 int64 leftover_ticks = qpc_value % ticks_per_second_;
395 int64 microseconds = (whole_seconds * Time::kMicrosecondsPerSecond) + 401 int64 microseconds = (whole_seconds * Time::kMicrosecondsPerSecond) +
396 ((leftover_ticks * Time::kMicrosecondsPerSecond) / 402 ((leftover_ticks * Time::kMicrosecondsPerSecond) /
397 ticks_per_second_); 403 ticks_per_second_);
398 return microseconds; 404 return microseconds;
399 } 405 }
400 406
401 private: 407 private:
402 HighResNowSingleton()
403 : ticks_per_second_(0),
404 skew_(0) {
405 InitializeClock();
406
407 base::CPU cpu;
408 if (IsBuggyAthlon(cpu))
409 DisableHighResClock();
410 }
411
412 // Synchronize the QPC clock with GetSystemTimeAsFileTime. 408 // Synchronize the QPC clock with GetSystemTimeAsFileTime.
413 void InitializeClock() { 409 void InitializeClock() {
414 LARGE_INTEGER ticks_per_sec = {0}; 410 LARGE_INTEGER ticks_per_sec = {0};
415 if (!QueryPerformanceFrequency(&ticks_per_sec)) 411 if (!QueryPerformanceFrequency(&ticks_per_sec))
416 return; // Broken, we don't guarantee this function works. 412 return; // Broken, we don't guarantee this function works.
417 ticks_per_second_ = ticks_per_sec.QuadPart; 413 ticks_per_second_ = ticks_per_sec.QuadPart;
418 414
419 skew_ = UnreliableNow() - ReliableNow(); 415 skew_ = UnreliableNow() - ReliableNow();
420 } 416 }
421 417
422 // Get the number of microseconds since boot in an unreliable fashion. 418 // Get the number of microseconds since boot in an unreliable fashion.
423 int64 UnreliableNow() { 419 int64 UnreliableNow() {
424 LARGE_INTEGER now; 420 LARGE_INTEGER now;
425 QueryPerformanceCounter(&now); 421 QueryPerformanceCounter(&now);
426 return QPCValueToMicroseconds(now.QuadPart); 422 return QPCValueToMicroseconds(now.QuadPart);
427 } 423 }
428 424
429 // Get the number of microseconds since boot in a reliable fashion. 425 // Get the number of microseconds since boot in a reliable fashion.
430 int64 ReliableNow() { 426 int64 ReliableNow() {
431 return RolloverProtectedNow().InMicroseconds(); 427 return RolloverProtectedNow().InMicroseconds();
432 } 428 }
433 429
434 int64 ticks_per_second_; // 0 indicates QPF failed and we're broken. 430 int64 ticks_per_second_; // 0 indicates QPF failed and we're broken.
435 int64 skew_; // Skew between lo-res and hi-res clocks (for debugging). 431 int64 skew_; // Skew between lo-res and hi-res clocks (for debugging).
436
437 friend struct DefaultSingletonTraits<HighResNowSingleton>;
438 }; 432 };
439 433
434 static base::LazyInstance<HighResNowSingleton>::Leaky
435 leaky_high_res_now_singleton = LAZY_INSTANCE_INITIALIZER;
436
437 HighResNowSingleton* GetHighResNowSingleton() {
438 return leaky_high_res_now_singleton.Pointer();
439 }
440
440 TimeDelta HighResNowWrapper() { 441 TimeDelta HighResNowWrapper() {
441 return HighResNowSingleton::GetInstance()->Now(); 442 return GetHighResNowSingleton()->Now();
442 } 443 }
443 444
444 typedef TimeDelta (*NowFunction)(void); 445 typedef TimeDelta (*NowFunction)(void);
445 NowFunction now_function = RolloverProtectedNow; 446 NowFunction now_function = RolloverProtectedNow;
446 447
447 bool CPUReliablySupportsHighResTime() { 448 bool CPUReliablySupportsHighResTime() {
448 base::CPU cpu; 449 base::CPU cpu;
449 if (!cpu.has_non_stop_time_stamp_counter()) 450 if (!cpu.has_non_stop_time_stamp_counter())
450 return false; 451 return false;
451 452
(...skipping 26 matching lines...) Expand all
478 return true; 479 return true;
479 } 480 }
480 481
481 // static 482 // static
482 TimeTicks TimeTicks::Now() { 483 TimeTicks TimeTicks::Now() {
483 return TimeTicks() + now_function(); 484 return TimeTicks() + now_function();
484 } 485 }
485 486
486 // static 487 // static
487 TimeTicks TimeTicks::HighResNow() { 488 TimeTicks TimeTicks::HighResNow() {
488 return TimeTicks() + HighResNowSingleton::GetInstance()->Now(); 489 return TimeTicks() + HighResNowWrapper();
489 } 490 }
490 491
491 // static 492 // static
492 bool TimeTicks::IsHighResNowFastAndReliable() { 493 bool TimeTicks::IsHighResNowFastAndReliable() {
493 return CPUReliablySupportsHighResTime(); 494 return CPUReliablySupportsHighResTime();
494 } 495 }
495 496
496 // static 497 // static
497 TimeTicks TimeTicks::ThreadNow() { 498 TimeTicks TimeTicks::ThreadNow() {
498 NOTREACHED(); 499 NOTREACHED();
499 return TimeTicks(); 500 return TimeTicks();
500 } 501 }
501 502
502 // static 503 // static
503 TimeTicks TimeTicks::NowFromSystemTraceTime() { 504 TimeTicks TimeTicks::NowFromSystemTraceTime() {
504 return HighResNow(); 505 return HighResNow();
505 } 506 }
506 507
507 // static 508 // static
508 int64 TimeTicks::GetQPCDriftMicroseconds() { 509 int64 TimeTicks::GetQPCDriftMicroseconds() {
509 return HighResNowSingleton::GetInstance()->GetQPCDriftMicroseconds(); 510 return GetHighResNowSingleton()->GetQPCDriftMicroseconds();
510 } 511 }
511 512
512 // static 513 // static
513 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { 514 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
514 return TimeTicks( 515 return TimeTicks(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value));
515 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value));
516 } 516 }
517 517
518 // static 518 // static
519 bool TimeTicks::IsHighResClockWorking() { 519 bool TimeTicks::IsHighResClockWorking() {
520 return HighResNowSingleton::GetInstance()->IsUsingHighResClock(); 520 return GetHighResNowSingleton()->IsUsingHighResClock();
521 } 521 }
522 522
523 TimeTicks TimeTicks::UnprotectedNow() { 523 TimeTicks TimeTicks::UnprotectedNow() {
524 if (now_function == HighResNowWrapper) { 524 if (now_function == HighResNowWrapper) {
525 return Now(); 525 return Now();
526 } else { 526 } else {
527 return TimeTicks() + TimeDelta::FromMilliseconds(timeGetTime()); 527 return TimeTicks() + TimeDelta::FromMilliseconds(timeGetTime());
528 } 528 }
529 } 529 }
530 530
531 // TimeDelta ------------------------------------------------------------------ 531 // TimeDelta ------------------------------------------------------------------
532 532
533 // static 533 // static
534 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { 534 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
535 return TimeDelta( 535 return TimeDelta(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value));
536 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value));
537 } 536 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698