]> granicus.if.org Git - libevent/commitdiff
Implement a GetTickCount-based monotonic timer for Windows
authorNick Mathewson <nickm@torproject.org>
Tue, 17 Apr 2012 19:16:08 +0000 (15:16 -0400)
committerNick Mathewson <nickm@torproject.org>
Tue, 17 Apr 2012 19:37:12 +0000 (15:37 -0400)
event-internal.h
event.c

index 6910469cad9d6b1e97dc3782ffb746f947cfc072..a2fc8e808b0b9ee2276c4a8e5412e28e67a7d1d7 100644 (file)
@@ -68,6 +68,8 @@ extern "C" {
 #define HAVE_ANY_MONOTONIC 1
 #elif defined(EVENT__HAVE_MACH_ABSOLUTE_TIME)
 #define HAVE_ANY_MONOTONIC 1
+#elif defined(_WIN32)
+#define HAVE_ANY_MONOTONIC 1
 #endif
 
 /** Structure to define the backend of a given event_base. */
@@ -262,8 +264,13 @@ struct event_base {
 #define CLOCK_IS_SELECTED
        int monotonic_clock;
 #endif
+#ifdef _WIN32
+       DWORD last_tick_count;
+       struct timeval adjust_tick_count;
+#endif
 #if defined(HAVE_ANY_MONOTONIC)
        /** 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;
        /** Difference between internal time (maybe from clock_gettime) and
         * gettimeofday. */
diff --git a/event.c b/event.c
index fe55e2169b41d78c9e467bdf57c38782da5bafa5..c1d00eb39592ad5f94d13d55f76bc7eaadc63393 100644 (file)
--- a/event.c
+++ b/event.c
@@ -375,6 +375,8 @@ detect_monotonic(struct event_base *base, const struct event_config *cfg)
                        memcpy(&base->mach_timebase_units, &mi, sizeof(mi));
                }
        }
+#elif defined(_WIN32)
+       base->use_monotonic = 1;
 #endif
 }
 
@@ -418,6 +420,23 @@ gettime(struct event_base *base, struct timeval *tp)
                    / (base->mach_timebase_units.denom);
                tp->tv_sec = 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
 #error "Missing monotonic time implementation."
 #endif