#include "glib.h"
#include "galias.h"
+#define G_NSEC_PER_SEC 1000000000
struct _GTimer
{
#ifdef G_OS_WIN32
guint64 start;
guint64 end;
-#else /* !G_OS_WIN32 */
+#elif HAVE_CLOCK_GETTIME
+ struct timespec start;
+ struct timespec end;
+ gint clock;
+#else /* uses gettimeofday */
struct timeval start;
struct timeval end;
-#endif /* !G_OS_WIN32 */
+#endif
guint active : 1;
};
#ifdef G_OS_WIN32
-# define GETTIME(v) \
+# define GETTIME(v) \
GetSystemTimeAsFileTime ((FILETIME *)&v)
-#else /* !G_OS_WIN32 */
-# define GETTIME(v) \
+#elif HAVE_CLOCK_GETTIME
+# define GETTIME(v) \
+ clock_gettime (posix_clock, &v)
+#else
+# define GETTIME(v) \
gettimeofday (&v, NULL)
-#endif /* !G_OS_WIN32 */
+#endif
+
+#ifdef HAVE_CLOCK_GETTIME
+static gint posix_clock = 0;
+
+static void
+init_posix_clock (void)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized)
+ {
+ initialized = TRUE;
+#if !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK >= 0
+ if (sysconf (_SC_MONOTONIC_CLOCK) >= 0)
+ posix_clock = CLOCK_MONOTONIC;
+ else
+#endif
+ posix_clock = CLOCK_REALTIME;
+ }
+}
+#endif
GTimer*
g_timer_new (void)
timer = g_new (GTimer, 1);
timer->active = TRUE;
+#ifdef HAVE_CLOCK_GETTIME
+ init_posix_clock ();
+#endif
+
GETTIME (timer->start);
return timer;
{
#ifdef G_OS_WIN32
guint64 elapsed;
+#elif HAVE_CLOCK_GETTIME
+ struct timespec elapsed;
#else
struct timeval elapsed;
-#endif /* G_OS_WIN32 */
+#endif
g_return_if_fail (timer != NULL);
g_return_if_fail (timer->active == FALSE);
timer->start -= elapsed;
-#else /* !G_OS_WIN32 */
+#elif HAVE_CLOCK_GETTIME
+
+ if (timer->start.tv_nsec > timer->end.tv_nsec)
+ {
+ timer->end.tv_nsec += G_NSEC_PER_SEC;
+ timer->end.tv_sec--;
+ }
+
+ elapsed.tv_nsec = timer->end.tv_nsec - timer->start.tv_nsec;
+ elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;
+
+ GETTIME (timer->start);
+
+ if (timer->start.tv_nsec < elapsed.tv_nsec)
+ {
+ timer->start.tv_nsec += G_NSEC_PER_SEC;
+ timer->start.tv_sec--;
+ }
+
+ timer->start.tv_nsec -= elapsed.tv_nsec;
+ timer->start.tv_sec -= elapsed.tv_sec;
+
+#else
if (timer->start.tv_usec > timer->end.tv_usec)
{
gdouble total;
#ifdef G_OS_WIN32
gint64 elapsed;
+#elif HAVE_CLOCK_GETTIME
+ struct timespec elapsed;
#else
struct timeval elapsed;
-#endif /* G_OS_WIN32 */
+#endif
g_return_val_if_fail (timer != NULL, 0);
if (microseconds)
*microseconds = (elapsed / 10) % 1000000;
-#else /* !G_OS_WIN32 */
+#elif HAVE_CLOCK_GETTIME
+ if (timer->active)
+ GETTIME (timer->end);
+
+ if (timer->start.tv_nsec > timer->end.tv_nsec)
+ {
+ timer->end.tv_nsec += G_NSEC_PER_SEC;
+ timer->end.tv_sec--;
+ }
+
+ elapsed.tv_nsec = timer->end.tv_nsec - timer->start.tv_nsec;
+ elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;
+
+ total = elapsed.tv_sec + ((gdouble) elapsed.tv_nsec / (gdouble) G_NSEC_PER_SEC);
+ if (total < 0)
+ {
+ total = 0;
+
+ if (microseconds)
+ *microseconds = 0;
+ }
+ else if (microseconds)
+ *microseconds = elapsed.tv_nsec / 1000;
+
+#else
if (timer->active)
- gettimeofday (&timer->end, NULL);
+ GETTIME (timer->end);
if (timer->start.tv_usec > timer->end.tv_usec)
{
elapsed.tv_usec = timer->end.tv_usec - timer->start.tv_usec;
elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;
- total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / 1e6);
+ total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / (gdouble) G_USEC_PER_SEC);
if (total < 0)
{
total = 0;
else if (microseconds)
*microseconds = elapsed.tv_usec;
-#endif /* !G_OS_WIN32 */
+#endif
return total;
}