Chromium Code Reviews| Index: base/time/time_win.cc |
| diff --git a/base/time/time_win.cc b/base/time/time_win.cc |
| index 5fa899d1f97f69be69d1df65ba854565d7240b53..86cbde86082911be318ca432f97c05a4dd197969 100644 |
| --- a/base/time/time_win.cc |
| +++ b/base/time/time_win.cc |
| @@ -79,10 +79,22 @@ int64 CurrentWallclockMicroseconds() { |
| // Time between resampling the un-granular clock for this API. 60 seconds. |
| const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; |
| -int64 initial_time = 0; |
| +// The ticks at initialization. |
| TimeTicks initial_ticks; |
| +// The time at initialization. |
| +int64 initial_time = 0; |
| + |
| +// Lock protecting initial_time and initial_ticks. |
| +// Note: this is a global object, and we usually avoid these. However, the time |
| +// code is low-level, and we don't want to use Singletons here (it would be too |
|
Nico
2014/08/15 23:17:38
(fwiw, on linux or mac, "low-level" isn't an excus
willchan no longer on Chromium
2014/08/15 23:20:19
This is very true. But what's the alternative? Do
|
| +// easy to use a Singleton without even knowing it, and that may lead to many |
| +// gotchas). Its impact on startup time should be negligible due to low-level |
| +// nature of time code. |
| +base::Lock initialize_clock_lock; |
| + |
| void InitializeClock() { |
| + base::AutoLock locked(initialize_clock_lock); |
|
M-A Ruel
2014/08/16 00:40:14
Because I'm a nice guy, here's the code you actual
|
| initial_ticks = TimeTicks::Now(); |
| initial_time = CurrentWallclockMicroseconds(); |
| } |
| @@ -119,8 +131,16 @@ Time Time::Now() { |
| while (true) { |
| TimeTicks ticks = TimeTicks::Now(); |
| + int64 start_time = 0; |
| + TimeTicks start_ticks; |
| + { |
| + base::AutoLock locked(initialize_clock_lock); |
| + start_time = initial_time; |
| + start_ticks = initial_ticks; |
| + } |
| + |
| // Calculate the time elapsed since we started our timer |
| - TimeDelta elapsed = ticks - initial_ticks; |
| + TimeDelta elapsed = ticks - start_ticks; |
| // Check if enough time has elapsed that we need to resync the clock. |
| if (elapsed.InMilliseconds() > kMaxMillisecondsToAvoidDrift) { |
| @@ -128,7 +148,7 @@ Time Time::Now() { |
| continue; |
| } |
| - return Time(elapsed + Time(initial_time)); |
| + return Time(elapsed + Time(start_time)); |
| } |
| } |
| @@ -359,21 +379,24 @@ bool IsBuggyAthlon(const base::CPU& cpu) { |
| class HighResNowSingleton { |
| public: |
| HighResNowSingleton() |
| - : ticks_per_second_(0), |
| - skew_(0) { |
| - InitializeClock(); |
| + : ticks_per_second_(0), |
| + skew_(0) { |
| base::CPU cpu; |
| if (IsBuggyAthlon(cpu)) |
| - DisableHighResClock(); |
| - } |
| + return; |
| - bool IsUsingHighResClock() { |
| - return ticks_per_second_ != 0.0; |
| + // Synchronize the QPC clock with GetSystemTimeAsFileTime. |
| + LARGE_INTEGER ticks_per_sec = {0}; |
| + if (!QueryPerformanceFrequency(&ticks_per_sec)) |
| + return; // QPC is not available. |
| + ticks_per_second_ = ticks_per_sec.QuadPart; |
| + |
| + skew_ = UnreliableNow() - ReliableNow(); |
| } |
| - void DisableHighResClock() { |
| - ticks_per_second_ = 0.0; |
| + bool IsUsingHighResClock() { |
| + return ticks_per_second_ != 0; |
| } |
| TimeDelta Now() { |
| @@ -408,16 +431,6 @@ class HighResNowSingleton { |
| } |
| private: |
| - // Synchronize the QPC clock with GetSystemTimeAsFileTime. |
| - void InitializeClock() { |
| - LARGE_INTEGER ticks_per_sec = {0}; |
| - if (!QueryPerformanceFrequency(&ticks_per_sec)) |
| - return; // Broken, we don't guarantee this function works. |
| - ticks_per_second_ = ticks_per_sec.QuadPart; |
| - |
| - skew_ = UnreliableNow() - ReliableNow(); |
| - } |
| - |
| // Get the number of microseconds since boot in an unreliable fashion. |
| int64 UnreliableNow() { |
| LARGE_INTEGER now; |
| @@ -480,6 +493,7 @@ bool TimeTicks::SetNowIsHighResNowIfSupported() { |
| } |
| now_function = HighResNowWrapper; |
| + InitializeClock(); |
| return true; |
| } |