Index: gtimer.h
===================================================================
RCS file: /cvs/gnome/glib/glib/gtimer.h,v
retrieving revision 1.3
diff -u -p -r1.3 gtimer.h
--- gtimer.h	2001/06/26 16:01:14	1.3
+++ gtimer.h	2002/07/22 07:36:01
@@ -45,7 +45,10 @@ void	g_timer_start	(GTimer	  *timer);
 void	g_timer_stop	(GTimer	  *timer);
 void	g_timer_reset	(GTimer	  *timer);
 gdouble g_timer_elapsed (GTimer	  *timer,
-			 gulong	  *microseconds);
+                         gulong	  *microseconds);
+gdouble g_timer_total_elapsed (GTimer *timer,
+                               gulong	  *microseconds);
+gboolean g_timer_is_active (GTimer *timer);
 
 void    g_usleep        (gulong    microseconds);
 
Index: gtimer.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gtimer.c,v
retrieving revision 1.16
diff -u -p -r1.16 gtimer.c
--- gtimer.c	2001/09/19 18:08:19	1.16
+++ gtimer.c	2002/07/22 07:37:04
@@ -51,9 +51,11 @@ struct _GTimer
 #ifdef G_OS_WIN32
   DWORD start;
   DWORD end;
+  DWORD elapsed;
 #else /* !G_OS_WIN32 */
   struct timeval start;
   struct timeval end;
+  struct timeval elapsed;
 #endif /* !G_OS_WIN32 */
 
   guint active : 1;
@@ -67,6 +69,15 @@ struct _GTimer
      gettimeofday (&v, NULL)
 #endif /* !G_OS_WIN32 */
 
+
+/**
+ *  g_timer_new:
+ *
+ *  @returns: a new #GTimer
+ *
+ *  Creates a new #GTimer, and starts timing (ie. a g_timer_start()
+ *  is implicitly called for you).
+ **/
 GTimer*
 g_timer_new (void)
 {
@@ -77,9 +88,23 @@ g_timer_new (void)
 
   GETTIME (timer->start);
 
+#ifdef G_OS_WIN32
+  timer->elapsed = 0;
+#else
+  timer->elapsed.tv_usec = 0;
+  timer->elapsed.tv_sec = 0;
+#endif /* G_OS_WIN32 */
+
   return timer;
 }
 
+/**
+ *  g_timer_destroy:
+ *
+ *  @timer: the timer instance to destroy
+ *
+ *  Destroys the timer, freeing any associated resources.
+ **/
 void
 g_timer_destroy (GTimer *timer)
 {
@@ -88,6 +113,15 @@ g_timer_destroy (GTimer *timer)
   g_free (timer);
 }
 
+/**
+ *  g_timer_start:
+ *
+ *  @timer: the timer to start
+ *
+ *  Marks a start time, so that future calls to g_timer_elapsed()
+ *  will report the time since this was called.  The timer is made
+ *  active, and the total elapsed time is preserved.
+ **/
 void
 g_timer_start (GTimer *timer)
 {
@@ -98,6 +132,15 @@ g_timer_start (GTimer *timer)
   GETTIME (timer->start);
 }
 
+/**
+ *  g_timer_stop:
+ *
+ *  @timer: the timer to stop.
+ *
+ *  Marks an end time, so calls to #g_timer_elapsed() will return the
+ *  difference between the start time and this end time.  The timer is
+ *  made inactive, and  the total elapsed time is accumulated.
+ **/
 void
 g_timer_stop (GTimer *timer)
 {
@@ -106,16 +149,96 @@ g_timer_stop (GTimer *timer)
   timer->active = FALSE;
 
   GETTIME(timer->end);
+
+    /* Calculate the time elapsed since the last start */
+
+#ifdef G_OS_WIN32
+
+    /* Check for wraparound, which happens every 49.7 days. */
+    if (timer->end < timer->start)
+        timer->elapsed += (UINT_MAX - (timer->start - timer->end)) / 1000.0;
+    else
+        timer->elapsed += (timer->end - timer->start) / 1000.0;
+
+#else /* !G_OS_WIN32 */
+
+    if (timer->start.tv_usec > timer->end.tv_usec)
+    {
+        timer->end.tv_usec += G_USEC_PER_SEC;
+        timer->end.tv_sec--;
+    }
+
+    timer->elapsed.tv_usec += timer->end.tv_usec - timer->start.tv_usec;
+    timer->elapsed.tv_sec  += timer->end.tv_sec - timer->start.tv_sec;
+
+    /* Normalise elapsed time */
+    while (timer->elapsed.tv_usec > G_USEC_PER_SEC)
+    {
+        timer->elapsed.tv_usec -= G_USEC_PER_SEC;
+        timer->elapsed.tv_sec++;
+    }
+
+#endif
 }
 
+/**
+ *  g_timer_is_active:
+ *
+ *  @timer:     the timer instance
+ *  @returns:   true if the timer is running
+ *
+ *  Returns whether or not the timer is currently running.
+ **/
+gboolean
+g_timer_is_active (GTimer *timer)
+{
+    g_return_val_if_fail (timer != NULL, FALSE);
+
+    return timer->active;
+}
+
+/**
+ *  g_timer_reset:
+ *
+ *  @timer: the timer instance to reset
+ *
+ *  Stops the timer and zeroes the start time and the total elapsed
+ *  time.
+ *
+ **/
 void
 g_timer_reset (GTimer *timer)
 {
   g_return_if_fail (timer != NULL);
 
+  timer->active = FALSE;
+
   GETTIME (timer->start);
+
+#ifdef G_OS_WIN32
+  timer->elapsed = 0;
+#else
+  timer->elapsed.tv_usec = 0;
+  timer->elapsed.tv_sec = 0;
+#endif /* G_OS_WIN32 */
 }
 
+/**
+ *  g_timer_elapsed:
+ *
+ *  @timer:         The timer instance to query
+ *  @microseconds:  The number of microseconds since the last second,
+ *                  or NULL if this is not required.
+ *  @returns:       The elapsed time as a fractional number of seconds.
+ *
+ *  If @timer has been started but not stopped, returns the time since
+ *  the timer was started.  If @timer has been stopped, obtains the
+ *  elapsed time between the time it was last started and the time it
+ *  was stopped.
+ *
+ *  To get the total elapsed time since the timer was created or last
+ *  reset, use g_timer_total_elapsed().
+ **/
 gdouble
 g_timer_elapsed (GTimer *timer,
 		 gulong *microseconds)
@@ -175,6 +298,100 @@ g_timer_elapsed (GTimer *timer,
   return total;
 }
 
+/**
+ *  g_timer_total_elapsed:
+ *
+ *  @timer:         The timer instance to query
+ *  @microseconds:  The number of microseconds since the last second,
+ *                  or NULL if this is not required.
+ *  @returns:       The total elapsed time as a fractional number of seconds.
+ *
+ *  Returns the total time, in fractional seconds, elapsed for this
+ *  timer.  Elapsed time is defined as the total time between
+ *  successive start-stop calls.  If inactive, returns the total
+ *  elapsed time.  If active, returns the total elapsed time,
+ *  including the time since the last start call.  Time will accumulate
+ *  until g_timer_reset() is called.
+ **/
+gdouble
+g_timer_total_elapsed (GTimer *timer,
+                       gulong *microseconds)
+{
+  gdouble total;
+#ifdef G_OS_WIN32
+  DWORD end;
+#else
+  struct timeval end;
+#endif /* G_OS_WIN32 */
+
+  g_return_val_if_fail (timer != NULL, 0);
+
+  if (timer->active)
+      GETTIME(end);
+  else
+      end = timer->start;
+
+#ifdef G_OS_WIN32
+
+  /* Check for wraparound, which happens every 49.7 days. */
+  if (end < timer->start)
+    total = (UINT_MAX - (timer->start - end)) / 1000.0;
+  else
+    total = (end - timer->start) / 1000.0;
+
+  if (microseconds)
+    {
+      if (end < timer->start)
+	*microseconds =
+	  ((UINT_MAX - (timer->start - end)) % 1000) * 1000;
+      else
+	*microseconds =
+	  ((timer->end - timer->start) % 1000) * 1000;
+    }
+
+#else /* !G_OS_WIN32 */
+
+  if (timer->start.tv_usec > end.tv_usec)
+    {
+      end.tv_usec += G_USEC_PER_SEC;
+      end.tv_sec--;
+    }
+
+  timer->elapsed.tv_usec += end.tv_usec - timer->start.tv_usec;
+  timer->elapsed.tv_sec  += end.tv_sec - timer->start.tv_sec;
+
+  /* Normalise elapsed time */
+  while (timer->elapsed.tv_usec > G_USEC_PER_SEC)
+  {
+      timer->elapsed.tv_usec -= G_USEC_PER_SEC;
+      timer->elapsed.tv_sec++;
+  }
+
+  total = timer->elapsed.tv_sec + ((gdouble) timer->elapsed.tv_usec / 1e6);
+  if (total < 0)
+    {
+      total = 0;
+
+      if (microseconds)
+          *microseconds = 0;
+    }
+  else if (microseconds)
+      *microseconds = timer->elapsed.tv_usec;
+
+#endif /* !G_OS_WIN32 */
+
+  return total;
+}
+
+/**
+ *  g_usleep:
+ *
+ *  @microseconds:  Number of microseconds to sleep for
+ *
+ *  Puts the current thread to sleep for the given number of microseconds.
+ *  This call is blocking, and the sleep time is a minimum value; depending
+ *  on system load and scheduling, it may sleep longer.
+ **/
 void
 g_usleep (gulong microseconds)
 {
