From fa25646f8092dc6fe38ecf6d1293e9123a2f3fd1 Mon Sep 17 00:00:00 2001
From: Sam Hocevar <sam@hocevar.net>
Date: Sun, 15 Aug 2010 16:56:07 +0000
Subject: [PATCH] Improve the timer accuracy even more.

---
 src/timer.cpp | 38 +++++++++++++++++---------------------
 1 file changed, 17 insertions(+), 21 deletions(-)

diff --git a/src/timer.cpp b/src/timer.cpp
index 4d1c1f82..9037cf54 100644
--- a/src/timer.cpp
+++ b/src/timer.cpp
@@ -48,42 +48,40 @@ private:
 #endif
     }
 
-    float GetSeconds(bool update)
+    float GetOrWait(float seconds)
     {
-        float ret;
+        float ret, delta_time;
 #if defined __linux__
         struct timeval tv;
         gettimeofday(&tv, NULL);
         ret = 1e-6f * (tv.tv_usec - tv0.tv_usec) + (tv.tv_sec - tv0.tv_sec);
-        if (update)
+        delta_time = seconds - ret;
+        if (!seconds)
             tv0 = tv;
+        else if (delta_time > 0.0f)
+            usleep((int)(delta_time * 1e6f));
 #elif defined _WIN32
         LARGE_INTEGER cycles;
         QueryPerformanceCounter(&cycles);
         ret = seconds_per_cycle * (cycles.QuadPart - cycles0.QuadPart);
-        if (update)
+        delta_time = seconds - ret;
+        if (!seconds)
             cycles0 = cycles;
+        else if (delta_time > 5e-4f) // FIXME: use native Win32 stuff
+            SDL_Delay((int)(delta_time * 1e3f + 0.5f));
 #else
+        /* The crappy SDL fallback */
         Uint32 ticks = SDL_GetTicks();
         ret = 1e-3f * (ticks - ticks0);
-        if (update)
+        delta_time = seconds - ret;
+        if (!seconds)
             ticks0 = ticks;
+        else if (delta_time > 5e-4f)
+            SDL_Delay((int)(delta_time * 1e3f + 0.5f));
 #endif
         return ret;
     }
 
-    void WaitSeconds(float seconds)
-    {
-#if defined __linux__
-        usleep((int)(seconds * 1000000.0f));
-#elif defined _WIN32
-        /* FIXME: use native Win32 stuff */
-        SDL_Delay((int)(seconds * 1000.0f + 0.5f));
-#else
-        SDL_Delay((int)(seconds * 1000.0f + 0.5f));
-#endif
-    }
-
 #if defined __linux__
     struct timeval tv0;
 #elif defined _WIN32
@@ -110,13 +108,11 @@ Timer::~Timer()
 
 float Timer::GetSeconds()
 {
-    return data->GetSeconds(true);
+    return data->GetOrWait(0.0f);
 }
 
 void Timer::WaitSeconds(float seconds)
 {
-    float sleep = seconds - data->GetSeconds(false);
-    if (sleep > 1e-4f)
-        data->WaitSeconds(sleep);
+    (void)data->GetOrWait(seconds);
 }