summaryrefslogtreecommitdiff
path: root/libs/backends/portaudio
diff options
context:
space:
mode:
authorTim Mayberry <mojofunk@gmail.com>2015-09-11 21:48:26 +1000
committerTim Mayberry <mojofunk@gmail.com>2015-09-16 11:22:16 +1000
commita974659504b5d0797e62d2d115812be17a1ea5a0 (patch)
treeadce339cbc80edaf52bd628866a607a12728d172 /libs/backends/portaudio
parentc510d8a49da0555bc94d4564fa76a67cd2909380 (diff)
Check return value of windows timer functions and handle errors
Change return type of utils::get_microseconds to signed int and return -1 when failing to read timer
Diffstat (limited to 'libs/backends/portaudio')
-rw-r--r--libs/backends/portaudio/win_utils.cc39
-rw-r--r--libs/backends/portaudio/win_utils.h10
2 files changed, 40 insertions, 9 deletions
diff --git a/libs/backends/portaudio/win_utils.cc b/libs/backends/portaudio/win_utils.cc
index 3b985820b7..dc0f8d5270 100644
--- a/libs/backends/portaudio/win_utils.cc
+++ b/libs/backends/portaudio/win_utils.cc
@@ -27,15 +27,27 @@
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
diff --git a/libs/backends/portaudio/win_utils.h b/libs/backends/portaudio/win_utils.h
index 1b85eb04fd..072ce1f0b0 100644
--- a/libs/backends/portaudio/win_utils.h
+++ b/libs/backends/portaudio/win_utils.h
@@ -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 ();
}