[glib/glib-2-28] Go back to the old logic in set_expiration



commit b0ec12ef7692ee95923e97451614e1049af3f0e1
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Mar 6 22:37:01 2011 -0500

    Go back to the old logic in set_expiration
    
    It was more complicated, but also more correct...
    Also add a test to ensure that our rounding works as expected.
    https://bugzilla.gnome.org/show_bug.cgi?id=643795

 glib/gmain.c         |   10 +++++++---
 glib/tests/timeout.c |   41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 3 deletions(-)
---
diff --git a/glib/gmain.c b/glib/gmain.c
index 1af9a5c..3a480f3 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -3801,6 +3801,7 @@ g_timeout_set_expiration (GTimeoutSource *timeout_source,
 
   if (timeout_source->seconds)
     {
+      gint64 remainder;
       static gint timer_perturb = -1;
 
       if (timer_perturb == -1)
@@ -3825,11 +3826,14 @@ g_timeout_set_expiration (GTimeoutSource *timeout_source,
        * always only *increase* the expiration time by adding a full
        * second in the case that the microsecond portion decreases.
        */
-      if (timer_perturb < timeout_source->expiration % 1000000)
+      timeout_source->expiration -= timer_perturb;
+
+      remainder = timeout_source->expiration % 1000000;
+      if (remainder >= 1000000/4)
         timeout_source->expiration += 1000000;
 
-      timeout_source->expiration =
-        ((timeout_source->expiration / 1000000) * 1000000) + timer_perturb;
+      timeout_source->expiration -= remainder;
+      timeout_source->expiration += timer_perturb;
     }
 }
 
diff --git a/glib/tests/timeout.c b/glib/tests/timeout.c
index ff33aa6..9354cd7 100644
--- a/glib/tests/timeout.c
+++ b/glib/tests/timeout.c
@@ -1,4 +1,5 @@
 #include <glib.h>
+#include <unistd.h>
 
 static GMainLoop *loop;
 
@@ -42,12 +43,52 @@ test_seconds (void)
   g_main_loop_run (loop);
 }
 
+static gint64 last_time;
+static gint count;
+
+static gboolean
+test_func (gpointer data)
+{
+  gint64 current_time;
+
+  current_time = g_get_monotonic_time ();
+
+  g_assert (current_time / 1000000 - last_time / 1000000 == 1);
+
+  last_time = current_time;
+  count++;
+
+  /* Make the timeout take up to 0.1 seconds.
+   * We should still get scheduled for the next second.
+   */
+  usleep (count * 10000);
+
+  if (count < 10)
+    return TRUE;
+
+  g_main_loop_quit (loop);
+
+  return FALSE;
+}
+
+static void
+test_rounding (void)
+{
+  loop = g_main_loop_new (NULL, FALSE);
+
+  last_time = g_get_monotonic_time ();
+  g_timeout_add_seconds (1, test_func, NULL);
+
+  g_main_loop_run (loop);
+}
+
 int
 main (int argc, char *argv[])
 {
   g_test_init (&argc, &argv, NULL);
 
   g_test_add_func ("/timeout/seconds", test_seconds);
+  g_test_add_func ("/timeout/rounding", test_rounding);
 
   return g_test_run ();
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]