Implement a GetTickCount-based monotonic timer for Windows

This commit is contained in:
Nick Mathewson 2012-04-17 15:16:08 -04:00
parent 55780a70e2
commit d5e1d5ad99
2 changed files with 26 additions and 0 deletions

View File

@ -68,6 +68,8 @@ extern "C" {
#define HAVE_ANY_MONOTONIC 1 #define HAVE_ANY_MONOTONIC 1
#elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME) #elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
#define HAVE_ANY_MONOTONIC 1 #define HAVE_ANY_MONOTONIC 1
#elif defined(_WIN32)
#define HAVE_ANY_MONOTONIC 1
#endif #endif
/** Structure to define the backend of a given event_base. */ /** Structure to define the backend of a given event_base. */
@ -262,8 +264,13 @@ struct event_base {
#define CLOCK_IS_SELECTED #define CLOCK_IS_SELECTED
int monotonic_clock; int monotonic_clock;
#endif #endif
#ifdef _WIN32
DWORD last_tick_count;
struct timeval adjust_tick_count;
#endif
#if defined(HAVE_ANY_MONOTONIC) #if defined(HAVE_ANY_MONOTONIC)
/** True iff we should use our system's monotonic time implementation */ /** True iff we should use our system's monotonic time implementation */
/* TODO: Support systems where we don't need to detct monotonic time */
int use_monotonic; int use_monotonic;
/** Difference between internal time (maybe from clock_gettime) and /** Difference between internal time (maybe from clock_gettime) and
* gettimeofday. */ * gettimeofday. */

19
event.c
View File

@ -375,6 +375,8 @@ detect_monotonic(struct event_base *base, const struct event_config *cfg)
memcpy(&base->mach_timebase_units, &mi, sizeof(mi)); memcpy(&base->mach_timebase_units, &mi, sizeof(mi));
} }
} }
#elif defined(_WIN32)
base->use_monotonic = 1;
#endif #endif
} }
@ -418,6 +420,23 @@ gettime(struct event_base *base, struct timeval *tp)
/ (base->mach_timebase_units.denom); / (base->mach_timebase_units.denom);
tp->tv_sec = usec / 1000000; tp->tv_sec = usec / 1000000;
tp->tv_usec = usec % 1000000; tp->tv_usec = usec % 1000000;
#elif defined(_WIN32)
/* TODO: Support GetTickCount64. */
/* TODO: Support alternate timer backends if the user asked
* for a high-precision timer. QueryPerformanceCounter is
* possibly a good idea, but it is also supposed to have
* reliability issues under various circumstances. */
DWORD ticks = GetTickCount();
if (ticks < base->last_tick_count) {
/* The 32-bit timer rolled over. Let's assume it only
* happened once. Add 2**32 msec to adjust_tick_count. */
const struct timeval tv_rollover = { 4294967, 296000 };
evutil_timeradd(&tv_rollover, &base->adjust_tick_count, &base->adjust_tick_count);
}
base->last_tick_count = ticks;
tp->tv_sec = ticks / 1000;
tp->tv_usec = (ticks % 1000) * 1000;
evutil_timeradd(tp, &base->adjust_tick_count, tp);
#else #else
#error "Missing monotonic time implementation." #error "Missing monotonic time implementation."
#endif #endif