#include <ctime>
#include <cerrno>
-#include <SDL/SDL.h>
-
#include "timer.hh"
#if HAVE_LIBRT
-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
+// update), 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-precious 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.
+
+// If we don't have librt, we'll have to use a different timing method. SDL
+// only promises centisecond accuracy, but it may be better than nothing.
+
+#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_LIBRT
+
+
void sleep(scalar seconds, bool absolute)
{
struct timespec ts;
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
{
while (ret == -1 && errno == EINTR);
}
-#endif // HAVE_LIBRT
-
} // namespace dc
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+