#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;
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: *************************************************/
+