Make WinEnv::NowMicros return system time
Previous change for the function
555ca3e7b7 (diff-bdc04e0404c2db4fd3ac5118a63eaa4a)
made use of the QueryPerformanceCounter to return microseconds values that do not repeat
as std::chrono::system_clock returned values that made auto_roll_logger_test fail.
The interface documentation does not state that we need to return
system time describing the return value as a number of microsecs since some
moment in time. However, because on Linux it is implemented using gettimeofday
various pieces of code (such as GenericRateLimiter) took advantage of that
and make use of NowMicros() as a system timestamp. Thus the previous change
broke rate_limiter_test on Windows.
In addition, the interface name NowMicros() suggests that it is actually
a timestamp so people use it as such.
This change makes use of the new system call on Windows that returns
system time with required precision. This change preserves the fix
for auto_roll_logger_test and fixes rate_limiter_test.
Note that DBTest.RateLimitingTest still fails due to a separately reported issue.
This commit is contained in:
parent
b722007778
commit
f14c3363e1
@ -257,6 +257,8 @@ class Env {
|
||||
|
||||
// Returns the number of micro-seconds since some fixed point in time. Only
|
||||
// useful for computing deltas of time.
|
||||
// However, it is often used as system time such as in GenericRateLimiter
|
||||
// and other places so a port needs to return system time in order to work.
|
||||
virtual uint64_t NowMicros() = 0;
|
||||
|
||||
// Returns the number of nano-seconds since some fixed point in time. Only
|
||||
|
@ -1816,15 +1816,24 @@ class WinEnv : public Env {
|
||||
}
|
||||
|
||||
virtual uint64_t NowMicros() override {
|
||||
// all std::chrono clocks on windows have the same resolution that is only
|
||||
// On Windows 8 and Windows 2012 Server
|
||||
// GetSystemTimePreciseAsFileTime(¤t_time) can be used
|
||||
// all std::chrono clocks on windows proved to return
|
||||
// values that may repeat that is not good enough for some uses.
|
||||
const int64_t c_UnixEpochStartTicks = 116444736000000000i64;
|
||||
const int64_t c_FtToMicroSec = 10;
|
||||
|
||||
// This interface needs to return system time and not
|
||||
// just any microseconds because it is often used as an argument
|
||||
// to TimedWait() on condition variable
|
||||
FILETIME ftSystemTime;
|
||||
GetSystemTimePreciseAsFileTime(&ftSystemTime);
|
||||
|
||||
LARGE_INTEGER li;
|
||||
QueryPerformanceCounter(&li);
|
||||
// Convert to nanoseconds first to avoid loss of precision
|
||||
// and divide by frequency
|
||||
li.QuadPart *= std::micro::den;
|
||||
li.QuadPart /= perf_counter_frequency_;
|
||||
li.LowPart = ftSystemTime.dwLowDateTime;
|
||||
li.HighPart = ftSystemTime.dwHighDateTime;
|
||||
// Subtract unix epoch start
|
||||
li.QuadPart -= c_UnixEpochStartTicks;
|
||||
// Convert to microsecs
|
||||
li.QuadPart /= c_FtToMicroSec;
|
||||
return li.QuadPart;
|
||||
}
|
||||
|
||||
|
@ -88,13 +88,16 @@ bool CondVar::TimedWait(uint64_t abs_time_us) {
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
// MSVC++ library implements wait_until in terms of wait_for so
|
||||
// there is not an absolute wait anyway.
|
||||
microseconds usAbsTime(abs_time_us);
|
||||
|
||||
microseconds usNow(
|
||||
duration_cast<microseconds>(system_clock::now().time_since_epoch()));
|
||||
microseconds relTimeUs =
|
||||
(usAbsTime > usNow) ? (usAbsTime - usNow) : microseconds::zero();
|
||||
|
||||
std::_Cv_status cvStatus = cv_.wait_for(mu_->getLock(), relTimeUs);
|
||||
std::cv_status cvStatus = cv_.wait_for(mu_->getLock(), relTimeUs);
|
||||
|
||||
#ifndef NDEBUG
|
||||
mu_->locked_ = true;
|
||||
|
Loading…
Reference in New Issue
Block a user