]> Dogcows Code - chaz/yoink/blobdiff - src/timer.cc
main loop code fixed to decouple updates and draws
[chaz/yoink] / src / timer.cc
index 2c7a1cbc39e05f3957422cc7de6f7d0f71db6b64..d73d94f1bbedb7d11c0d9bc76a558a316d26d05c 100644 (file)
@@ -30,7 +30,9 @@
 #include <ctime>
 #include <cerrno>
 
-#include <SDL/SDL.h>
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
 
 #include "timer.hh"
 
 namespace dc {
 
 
-#if HAVE_LIBRT
+#if HAVE_CLOCK_GETTIME
 
-scalar ticks()
+// Since the monotonic clock will provide us with the timer since the computer
+// started, the number of seconds since that time could easily become so large
+// that it cannot be accurately stored in a float (even with as little two days
+// uptime), therefore we need to start from a more recent reference (when the
+// program starts).  Of course this isn't much of an issue if scalar is a
+// double-precision number.
+
+static time_t setReference()
 {
        struct timespec ts;
 
        if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
        {
-               throw std::runtime_error("cannot access monotonic clock");
+               return 0;
        }
 
-       return scalar(ts.tv_sec) + scalar(ts.tv_nsec) / 1000000000.0;
+       return ts.tv_sec;
 }
 
-void sleep(scalar seconds, bool absolute)
+static const time_t reference = setReference();
+
+
+scalar ticks()
 {
        struct timespec ts;
-       int ret;
-
-       if (!absolute) seconds += ticks();
-       ts.tv_sec = time_t(seconds);
-       ts.tv_nsec = time_t((seconds - scalar(ts.tv_sec)) * 1000000000.0);
 
-       do
+       if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
        {
-               ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, 0);
+               throw std::runtime_error("cannot access monotonic clock");
        }
-       while (ret == -1 && errno == EINTR);
+
+       return scalar(ts.tv_sec - reference) + scalar(ts.tv_nsec) / 1000000000.0;
 }
 
-#else // ! HAVE_LIBRT
 
-// If we don't have librt, we'll have to use different timing methods.
+#else // ! HAVE_CLOCK_GETTIME
+
+
+// If we don't have posix timers, we'll have to use a different timing method.
+// SDL only promises centisecond accuracy, but that's better than a kick in the
+// butt.
+
+#include <SDL/SDL.h>
 
 scalar ticks()
 {
-       unsigned ms = SDL_GetTicks();
+       Uint32 ms = SDL_GetTicks();
        return scalar(ms / 1000) + scalar(ms % 1000) / 1000.0;
 }
 
+
+#endif // HAVE_CLOCK_GETTIME
+
+
 void sleep(scalar seconds, bool absolute)
 {
        struct timespec ts;
@@ -85,7 +103,7 @@ void sleep(scalar seconds, bool absolute)
 
        if (absolute) seconds -= ticks();
        ts.tv_sec = time_t(seconds);
-       ts.tv_nsec = time_t((seconds - scalar(ts.tv_sec)) * 1000000000.0);
+       ts.tv_nsec = long((seconds - scalar(ts.tv_sec)) * 1000000000.0);
 
        do
        {
@@ -94,8 +112,8 @@ void sleep(scalar seconds, bool absolute)
        while (ret == -1 && errno == EINTR);
 }
 
-#endif // HAVE_LIBRT
-
 
 } // namespace dc
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
This page took 0.029958 seconds and 4 git commands to generate.