Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2005:
[Freeciv-Dev] (PR#13645) Timer drift
Home

[Freeciv-Dev] (PR#13645) Timer drift

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: chrisk@xxxxxxxxx
Subject: [Freeciv-Dev] (PR#13645) Timer drift
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 10 Aug 2005 18:54:43 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13645 >

(Oops, sent that to the wrong ticket.  This is the right one.)

This is an update of the PR#12219 patch that probably fixes the problem
for 2.0. I haven't tested it and don't plan to commit it unless it gets
some extensive testing.

-jason
? timer-2.0.diff
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.197.2.9
diff -p -u -r1.197.2.9 civclient.c
--- client/civclient.c  22 Feb 2005 00:00:32 -0000      1.197.2.9
+++ client/civclient.c  11 Aug 2005 01:52:43 -0000
@@ -20,6 +20,7 @@
 #endif
 
 #include <assert.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
@@ -38,6 +39,7 @@
 #include "packets.h"
 #include "rand.h"
 #include "support.h"
+#include "timing.h"
 #include "version.h"
 
 #include "agents.h"
@@ -87,8 +89,6 @@ bool auto_connect = FALSE; /* TRUE = ski
 
 static enum client_states client_state = CLIENT_BOOT_STATE;
 
-int seconds_to_turndone;
-
 /* TRUE if an end turn request is blocked by busy agents */
 bool waiting_for_end_turn = FALSE;
 
@@ -604,16 +604,60 @@ bool client_is_observer(void)
   return aconnection.established && aconnection.observer;
 }
 
+/* Seconds_to_turndone is the number of seconds the server has told us
+ * are left.  The timer tells exactly how much time has passed since the
+ * server gave us that data. */
+static double seconds_to_turndone = 0.0;
+static struct timer *turndone_timer;
+
+/* This value shows what value the timeout label is currently showing for
+ * the seconds-to-turndone. */
+static int seconds_shown_to_turndone;
+
+/**************************************************************************
+  Reset the number of seconds to turndone from an "authentic" source.
+
+  The seconds are taken as a double even though most callers will just
+  know an integer value.
+**************************************************************************/
+void set_seconds_to_turndone(double seconds)
+{
+  if (game.timeout > 0) {
+    seconds_to_turndone = seconds;
+    turndone_timer = renew_timer_start(turndone_timer, TIMER_USER,
+                                      TIMER_ACTIVE);
+
+    /* Maybe we should do an update_timeout_label here, but it doesn't
+     * seem to be necessary. */
+    seconds_shown_to_turndone = ceil(seconds) + 0.1;
+  }
+}
+
+/**************************************************************************
+  Return the number of seconds until turn-done.  Don't call this unless
+  game.timeout != 0.
+**************************************************************************/
+int get_seconds_to_turndone(void)
+{
+  if (game.timeout > 0) {
+    return seconds_shown_to_turndone;
+  } else {
+    /* This shouldn't happen. */
+    return FC_INFINITY;
+  }
+}
+
 /**************************************************************************
- This function should be called every 500ms. It lets the unit blink
- and update the timeout.
+  This function should be called at least once per second.  It does various
+  updates (idle animations and timeout updates).  It returns the number of
+  seconds until it should be called again.
 **************************************************************************/
-void real_timer_callback(void)
+double real_timer_callback(void)
 {
-  static bool flip = FALSE;
+  double time_until_next_call = 1.0;
 
   if (get_client_state() != CLIENT_GAME_RUNNING_STATE) {
-    return;
+    return time_until_next_call;
   }
 
   if (game.player_ptr->is_connected && game.player_ptr->is_alive &&
@@ -635,18 +679,26 @@ void real_timer_callback(void)
     }
   }
 
-  blink_active_unit();
+  if (get_unit_in_focus()) {
+    double blink_time = blink_active_unit();
 
-  if (flip) {
-    update_timeout_label();
-    if (seconds_to_turndone > 0) {
-      seconds_to_turndone--;
-    } else {
-      seconds_to_turndone = 0;
+    time_until_next_call = MIN(time_until_next_call, blink_time);
+  }
+
+  if (game.timeout > 0) {
+    double seconds = seconds_to_turndone - read_timer_seconds(turndone_timer);
+    int iseconds = ceil(seconds) + 0.1; /* Turn should end right on 0. */
+
+    if (iseconds < seconds_shown_to_turndone) {
+      seconds_shown_to_turndone = iseconds;
+      update_timeout_label();
     }
+
+    time_until_next_call = MIN(time_until_next_call,
+                              seconds - floor(seconds) + 0.001);
   }
 
-  flip = !flip;
+  return MAX(time_until_next_call, 0.0);
 }
 
 /**************************************************************************
Index: client/civclient.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.h,v
retrieving revision 1.35
diff -p -u -r1.35 civclient.h
--- client/civclient.h  29 Sep 2004 02:24:19 -0000      1.35
+++ client/civclient.h  11 Aug 2005 01:52:43 -0000
@@ -22,7 +22,7 @@
  * called. TIMER_INTERVAL has to stay 500 because real_timer_callback
  * also updates the timeout info.
  */
-#define TIMER_INTERVAL 500
+#define TIMER_INTERVAL (int)(real_timer_callback() * 1000)
 
 void handle_packet_input(void *packet, int type);
 
@@ -52,11 +52,11 @@ extern bool auto_connect;
 extern bool waiting_for_end_turn;
 extern bool turn_done_sent;
 
-extern int seconds_to_turndone;
-
 void wait_till_request_got_processed(int request_id);
 bool client_is_observer(void);
-void real_timer_callback(void);
+void set_seconds_to_turndone(double seconds);
+int get_seconds_to_turndone(void);
+double real_timer_callback(void);
 bool can_client_issue_orders(void);
 bool can_client_change_view(void);
 bool can_meet_with_player(struct player *pplayer);
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.143.2.13
diff -p -u -r1.143.2.13 control.c
--- client/control.c    26 May 2005 04:55:19 -0000      1.143.2.13
+++ client/control.c    11 Aug 2005 01:52:44 -0000
@@ -21,6 +21,7 @@
 #include "log.h"
 #include "map.h"
 #include "mem.h"
+#include "timing.h"
 
 #include "audio.h"
 #include "chatline_g.h"
@@ -372,24 +373,41 @@ struct unit *find_visible_unit(struct ti
 /**************************************************************************
 ...
 **************************************************************************/
-void blink_active_unit(void)
+double blink_active_unit(void)
 {
   static bool is_shown;
   static struct unit *pblinking_unit;
-  struct unit *punit;
+  static struct timer *blink_timer = NULL;
+  const double blink_time = 0.5;
+
+  struct unit *punit = punit_focus;
+  bool need_update = FALSE;
 
-  if ((punit = punit_focus)) {
+  if (punit) {
     if (punit != pblinking_unit) {
       /* When the focus unit changes, we reset the is_shown flag. */
       pblinking_unit = punit;
       is_shown = TRUE;
+      need_update = TRUE;
     } else {
-      /* Reverse the shown status. */
-      is_shown = !is_shown;
+      if (read_timer_seconds(blink_timer) > blink_time) {
+       /* Reverse the shown status. */
+       is_shown = !is_shown;
+       need_update = TRUE;
+      }
+    }
+    if (need_update) {
+      /* If we lag, we don't try to catch up.  Instead we just start a
+       * new blink_time on every update. */
+      blink_timer = renew_timer_start(blink_timer, TIMER_USER, TIMER_ACTIVE);
+      set_focus_unit_hidden_state(!is_shown);
+      refresh_tile_mapcanvas(punit->tile, TRUE);
     }
-    set_focus_unit_hidden_state(!is_shown);
-    refresh_tile_mapcanvas(punit->tile, TRUE);
+
+    return blink_time - read_timer_seconds(blink_timer);
   }
+
+  return blink_time;
 }
 
 /**************************************************************************
Index: client/control.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.h,v
retrieving revision 1.45
diff -p -u -r1.45 control.h
--- client/control.h    29 Sep 2004 02:24:19 -0000      1.45
+++ client/control.h    11 Aug 2005 01:52:44 -0000
@@ -106,7 +106,7 @@ void set_unit_focus_and_select(struct un
 void update_unit_focus(void);
 struct unit *find_visible_unit(struct tile *ptile);
 void set_units_in_combat(struct unit *pattacker, struct unit *pdefender);
-void blink_active_unit(void);
+double blink_active_unit(void);
 void update_unit_pix_label(struct unit *punit);
 
 void process_caravan_arrival(struct unit *punit);
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.408.2.27
diff -p -u -r1.408.2.27 packhand.c
--- client/packhand.c   21 Jul 2005 19:32:03 -0000      1.408.2.27
+++ client/packhand.c   11 Aug 2005 01:52:46 -0000
@@ -827,7 +827,7 @@ void handle_new_year(int year, int turn)
   update_unit_info_label(get_unit_in_focus());
   update_menus();
 
-  seconds_to_turndone=game.timeout;
+  set_seconds_to_turndone(game.timeout);
 
 #if 0
   /* This information shouldn't be needed, but if it is this is the only
@@ -1461,11 +1461,9 @@ void handle_game_info(struct packet_game
   boot_help = (can_client_change_view()
               && game.spacerace != pinfo->spacerace);
   game.spacerace=pinfo->spacerace;
-  if (game.timeout != 0) {
-    if (pinfo->seconds_to_turndone != 0)
-      seconds_to_turndone = pinfo->seconds_to_turndone;
-  } else
-    seconds_to_turndone = 0;
+  if (game.timeout != 0 && pinfo->seconds_to_turndone != 0) {
+    set_seconds_to_turndone(pinfo->seconds_to_turndone);
+  }
   if (boot_help) {
     boot_help_texts();         /* reboot, after setting game.spacerace */
   }
Index: client/text.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/text.c,v
retrieving revision 1.11.2.7
diff -p -u -r1.11.2.7 text.c
--- client/text.c       29 Dec 2004 17:25:00 -0000      1.11.2.7
+++ client/text.c       11 Aug 2005 01:52:46 -0000
@@ -639,7 +639,7 @@ const char *get_timeout_label_text(void)
   if (game.timeout <= 0) {
     add("%s", Q_("?timeout:off"));
   } else {
-    add("%s", format_duration(seconds_to_turndone));
+    add("%s", format_duration(get_seconds_to_turndone()));
   }
 
   RETURN;
Index: client/gui-ftwl/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-ftwl/gui_main.c,v
retrieving revision 1.3.2.2
diff -p -u -r1.3.2.2 gui_main.c
--- client/gui-ftwl/gui_main.c  1 Dec 2004 22:14:52 -0000       1.3.2.2
+++ client/gui-ftwl/gui_main.c  11 Aug 2005 01:52:46 -0000
@@ -65,9 +65,9 @@ void ui_init(void)
 **************************************************************************/
 static void timer_callback(void *data)
 {
-  real_timer_callback();
-  //sw_add_timeout(TIMER_INTERVAL, timer_callback, NULL);
-  sw_add_timeout(1000, timer_callback, NULL);
+  double msec = real_timer_callback() * 1000;
+  //sw_add_timeout(1000, timer_callback, NULL);
+  sw_add_timeout(msec, timer_callback, NULL);
 }
 
 /**************************************************************************
Index: client/gui-gtk/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/Attic/gui_main.c,v
retrieving revision 1.152.2.3
diff -p -u -r1.152.2.3 gui_main.c
--- client/gui-gtk/gui_main.c   16 Dec 2004 21:25:09 -0000      1.152.2.3
+++ client/gui-gtk/gui_main.c   11 Aug 2005 01:52:46 -0000
@@ -1063,6 +1063,7 @@ static void select_unit_pixmap_callback(
 static gint timer_callback(gpointer data)
 {
   real_timer_callback();
+  freelog(LOG_ERROR, "FIXME: Need to update timer.");
   return TRUE;
 }
 
Index: client/gui-gtk-2.0/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/gui_main.c,v
retrieving revision 1.81.2.17
diff -p -u -r1.81.2.17 gui_main.c
--- client/gui-gtk-2.0/gui_main.c       4 Aug 2005 16:57:35 -0000       
1.81.2.17
+++ client/gui-gtk-2.0/gui_main.c       11 Aug 2005 01:52:47 -0000
@@ -1352,8 +1352,11 @@ static gboolean select_unit_pixmap_callb
 **************************************************************************/
 static gint timer_callback(gpointer data)
 {
-  real_timer_callback();
-  return TRUE;
+  double seconds = real_timer_callback();
+
+  timer_id = gtk_timeout_add(seconds * 1000, timer_callback, NULL);
+
+  return FALSE;
 }
 
 /**************************************************************************
Index: client/gui-mui/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/gui_main.c,v
retrieving revision 1.86.2.2
diff -p -u -r1.86.2.2 gui_main.c
--- client/gui-mui/gui_main.c   22 Nov 2004 07:55:17 -0000      1.86.2.2
+++ client/gui-mui/gui_main.c   11 Aug 2005 01:52:47 -0000
@@ -133,6 +133,7 @@ static void parse_options(int argc, char
 static void handle_timer(void)
 {
   real_timer_callback();
+  freelog(LOG_ERROR, "FIXME: Need to update timer.");
 }
 
 static BOOL connected;         /* TRUE, if connected to the server */
Index: client/gui-win32/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/gui_main.c,v
retrieving revision 1.30.2.8
diff -p -u -r1.30.2.8 gui_main.c
--- client/gui-win32/gui_main.c 23 Mar 2005 04:04:43 -0000      1.30.2.8
+++ client/gui-win32/gui_main.c 11 Aug 2005 01:52:47 -0000
@@ -488,6 +488,7 @@ static VOID CALLBACK blink_timer(HWND hw
   }
 
   real_timer_callback();
+  freelog(LOG_ERROR, "FIXME: Need to update timer.");
 }
 
 /**************************************************************************
Index: client/gui-xaw/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/gui_main.c,v
retrieving revision 1.95.2.4
diff -p -u -r1.95.2.4 gui_main.c
--- client/gui-xaw/gui_main.c   24 Jan 2005 21:15:10 -0000      1.95.2.4
+++ client/gui-xaw/gui_main.c   11 Aug 2005 01:52:47 -0000
@@ -831,9 +831,10 @@ void end_turn_callback(Widget w, XtPoint
 **************************************************************************/
 void timer_callback(XtPointer client_data, XtIntervalId * id)
 {
-  x_interval_id = XtAppAddTimeOut(app_context, TIMER_INTERVAL,
+  int msec = real_timer_callback() * 1000;
+
+  x_interval_id = XtAppAddTimeOut(app_context, msec,
                                  timer_callback, NULL);
-  real_timer_callback();
 }
 
 /**************************************************************************

[Prev in Thread] Current Thread [Next in Thread]