Merge pull request #705 from yuslepukhin/rate_limiter_fix

Make WinEnv::NowMicros return system time
This commit is contained in:
Siying Dong 2015-09-02 11:35:17 -07:00
commit 0f763db20a
3 changed files with 23 additions and 9 deletions

View File

@ -257,6 +257,8 @@ class Env {
// Returns the number of micro-seconds since some fixed point in time. Only // Returns the number of micro-seconds since some fixed point in time. Only
// useful for computing deltas of time. // 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; virtual uint64_t NowMicros() = 0;
// Returns the number of nano-seconds since some fixed point in time. Only // Returns the number of nano-seconds since some fixed point in time. Only

View File

@ -1816,15 +1816,24 @@ class WinEnv : public Env {
} }
virtual uint64_t NowMicros() override { virtual uint64_t NowMicros() override {
// all std::chrono clocks on windows have the same resolution that is only // all std::chrono clocks on windows proved to return
// On Windows 8 and Windows 2012 Server // values that may repeat that is not good enough for some uses.
// GetSystemTimePreciseAsFileTime(&current_time) can be used 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; LARGE_INTEGER li;
QueryPerformanceCounter(&li); li.LowPart = ftSystemTime.dwLowDateTime;
// Convert to nanoseconds first to avoid loss of precision li.HighPart = ftSystemTime.dwHighDateTime;
// and divide by frequency // Subtract unix epoch start
li.QuadPart *= std::micro::den; li.QuadPart -= c_UnixEpochStartTicks;
li.QuadPart /= perf_counter_frequency_; // Convert to microsecs
li.QuadPart /= c_FtToMicroSec;
return li.QuadPart; return li.QuadPart;
} }

View File

@ -88,13 +88,16 @@ bool CondVar::TimedWait(uint64_t abs_time_us) {
using namespace std::chrono; 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 usAbsTime(abs_time_us);
microseconds usNow( microseconds usNow(
duration_cast<microseconds>(system_clock::now().time_since_epoch())); duration_cast<microseconds>(system_clock::now().time_since_epoch()));
microseconds relTimeUs = microseconds relTimeUs =
(usAbsTime > usNow) ? (usAbsTime - usNow) : microseconds::zero(); (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 #ifndef NDEBUG
mu_->locked_ = true; mu_->locked_ = true;