Check return value of windows timer functions and handle errors
authorTim Mayberry <mojofunk@gmail.com>
Fri, 11 Sep 2015 11:48:26 +0000 (21:48 +1000)
committerTim Mayberry <mojofunk@gmail.com>
Wed, 16 Sep 2015 01:22:16 +0000 (11:22 +1000)
Change return type of utils::get_microseconds to signed int and return -1 when
failing to read timer

libs/backends/portaudio/win_utils.cc
libs/backends/portaudio/win_utils.h

index 3b985820b74bcc6ee81e3ceab5dbd9b608a7f562..dc0f8d527017c7a1e5543828de14d1b0632e8715 100644 (file)
 
 namespace {
 
+bool&
+qpc_frequency_success ()
+{
+       static bool success = false;
+       return success;
+}
+
 LARGE_INTEGER
-get_frequency ()
+qpc_frequency ()
 {
        LARGE_INTEGER freq;
-       QueryPerformanceFrequency(&freq);
+       if (QueryPerformanceFrequency(&freq) == 0) {
+               DEBUG_TIMING ("Failed to determine frequency of QPC\n");
+               qpc_frequency_success() = false;
+       } else {
+               qpc_frequency_success() = true;
+       }
+
        return freq;
 }
 
-
 UINT&
 old_timer_resolution ()
 {
@@ -86,15 +98,26 @@ reset_timer_resolution ()
        return true;
 }
 
-uint64_t get_microseconds ()
+int64_t
+get_microseconds ()
 {
-       static LARGE_INTEGER frequency = get_frequency ();
+       static LARGE_INTEGER frequency = qpc_frequency ();
        LARGE_INTEGER current_val;
 
-       QueryPerformanceCounter (&current_val);
+       if (qpc_frequency_success()) {
 
-       return (uint64_t)(((double)current_val.QuadPart) /
-                         ((double)frequency.QuadPart) * 1000000.0);
+               // MS docs say this will always succeed for systems >= XP but it may
+               // not return a monotonic value with non-invariant TSC's etc
+               if (QueryPerformanceCounter(&current_val) != 0) {
+                       return (int64_t)(((double)current_val.QuadPart) /
+                                        ((double)frequency.QuadPart) * 1000000.0);
+               } else {
+                       DEBUG_TIMING ("Could not get QPC timer\n");
+               }
+               return -1;
+       }
+       // For XP systems that don't support a high-res performance counter
+       return g_get_monotonic_time ();
 }
 
 } // namespace utils
index 1b85eb04fdfd4dbb69ea345e40b58ca457edb848..072ce1f0b0147d37b5be4559911384831cfc0542 100644 (file)
@@ -27,7 +27,15 @@ bool set_min_timer_resolution ();
 
 bool reset_timer_resolution ();
 
-uint64_t get_microseconds ();
+/** The highest resolution timer source provided by the system. On Vista and
+ * above this is the value returned by QueryPerformanceCounter(QPC). On XP,
+ * this will QPC if supported or otherwise g_get_monotonic_time will be used.
+ *
+ * @return A timer value in microseconds or -1 in the event that the reading
+ * the timer source fails, but the MS docs say that this won't occur for
+ * systems >= XP
+ */
+int64_t get_microseconds ();
 
 }