X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftimer.cc;h=d73d94f1bbedb7d11c0d9bc76a558a316d26d05c;hb=87bc17e55b0c1dc73ecc66df856d3f08fd7a7724;hp=2c7a1cbc39e05f3957422cc7de6f7d0f71db6b64;hpb=79b5f738f2e38acb60cda7e09f54802933a17105;p=chaz%2Fyoink diff --git a/src/timer.cc b/src/timer.cc index 2c7a1cb..d73d94f 100644 --- a/src/timer.cc +++ b/src/timer.cc @@ -30,7 +30,9 @@ #include #include -#include +#if HAVE_CONFIG_H +#include "config.h" +#endif #include "timer.hh" @@ -38,46 +40,62 @@ 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 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: *************************************************/ +