[Freeciv-Dev] (PR#12219) fix bugs with real_timer_callback
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12219 >
This patch fixes some bugs and makes real_timer_callback a lot more useful.
Currently there are several bugs here.
1. real_time_callback decreases the seconds_to_turndone on every 2
callbacks. Each callback is 500 ms. Great. Except that the callbacks
can lag, and when they do there is no attempt to catch up. This _may_
be why when I play on pubserver the turn often ends when the timer says
there's still plenty of time left.
2. When switching focus units, we should restart the blink timer. I
think. At least it should be possible for the focus unit code to run
its own timer separate from the 1s-timer used by the timeout code.
This patch solves the problem in a fairly elegant and modular way.
1. real_timer_callback isn't called at a fixed interval. Rather each
call to it returns the time until the next call. The clients thus have
to re-queue the timer (this is implemented for gtk2, xaw, and ftwl clients).
2. The seconds until turn done value is hidden inside civclient.c.
Users now access it via set_seconds_until_turndone() and
get_seconds_until_turndone(). We keep a separate timer of
time-passed-since-the-server-last-told-us-how-long-we-have so now the
timer won't become inaccurate as time goes by.
3. The blink-focus-unit code also keeps its own timer. This timer is
restarted when the focus unit changes and each time a blink is done (so
unlike the timeout timer, this one is allowed to lag).
See also PR#12215.
-jason
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.212
diff -u -r1.212 civclient.c
--- client/civclient.c 22 Jan 2005 19:45:38 -0000 1.212
+++ client/civclient.c 11 Feb 2005 20:02:54 -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 @@
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;
@@ -612,16 +612,60 @@
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 &&
@@ -643,18 +687,26 @@
}
}
- 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.38
diff -u -r1.38 civclient.h
--- client/civclient.h 12 Dec 2004 03:44:47 -0000 1.38
+++ client/civclient.h 11 Feb 2005 20:02:54 -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 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(const struct player *pplayer);
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.155
diff -u -r1.155 control.c
--- client/control.c 9 Feb 2005 16:23:12 -0000 1.155
+++ client/control.c 11 Feb 2005 20:02:54 -0000
@@ -21,6 +21,7 @@
#include "log.h"
#include "map.h"
#include "mem.h"
+#include "timing.h"
#include "audio.h"
#include "chatline_g.h"
@@ -394,26 +395,45 @@
}
/**************************************************************************
-...
+ Blink the active unit (if necessary). Return the time until the next
+ blink (in seconds).
**************************************************************************/
-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;
- if ((punit = punit_focus)) {
+ struct unit *punit = punit_focus;
+ bool need_update = FALSE;
+
+ 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_unit_mapcanvas(punit, punit->tile, TRUE);
}
- set_focus_unit_hidden_state(!is_shown);
- refresh_unit_mapcanvas(punit, 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.48
diff -u -r1.48 control.h
--- client/control.h 9 Feb 2005 16:23:12 -0000 1.48
+++ client/control.h 11 Feb 2005 20:02:54 -0000
@@ -112,7 +112,7 @@
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.468
diff -u -r1.468 packhand.c
--- client/packhand.c 9 Feb 2005 17:15:17 -0000 1.468
+++ client/packhand.c 11 Feb 2005 20:02:55 -0000
@@ -766,7 +766,7 @@
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
@@ -1362,11 +1362,9 @@
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.24
diff -u -r1.24 text.c
--- client/text.c 8 Feb 2005 21:36:49 -0000 1.24
+++ client/text.c 11 Feb 2005 20:02:55 -0000
@@ -639,7 +639,7 @@
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.9
diff -u -r1.9 gui_main.c
--- client/gui-ftwl/gui_main.c 22 Jan 2005 19:45:39 -0000 1.9
+++ client/gui-ftwl/gui_main.c 11 Feb 2005 20:02:55 -0000
@@ -68,9 +68,9 @@
**************************************************************************/
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/gui_main.c,v
retrieving revision 1.161
diff -u -r1.161 gui_main.c
--- client/gui-gtk/gui_main.c 11 Feb 2005 16:57:59 -0000 1.161
+++ client/gui-gtk/gui_main.c 11 Feb 2005 20:02:55 -0000
@@ -1090,6 +1090,7 @@
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.109
diff -u -r1.109 gui_main.c
--- client/gui-gtk-2.0/gui_main.c 11 Feb 2005 16:57:59 -0000 1.109
+++ client/gui-gtk-2.0/gui_main.c 11 Feb 2005 20:02:56 -0000
@@ -1387,8 +1387,11 @@
**************************************************************************/
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.90
diff -u -r1.90 gui_main.c
--- client/gui-mui/gui_main.c 11 Feb 2005 16:57:59 -0000 1.90
+++ client/gui-mui/gui_main.c 11 Feb 2005 20:02:56 -0000
@@ -144,6 +144,7 @@
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.40
diff -u -r1.40 gui_main.c
--- client/gui-win32/gui_main.c 11 Feb 2005 16:58:00 -0000 1.40
+++ client/gui-win32/gui_main.c 11 Feb 2005 20:02:56 -0000
@@ -516,6 +516,7 @@
}
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.101
diff -u -r1.101 gui_main.c
--- client/gui-xaw/gui_main.c 11 Feb 2005 16:58:00 -0000 1.101
+++ client/gui-xaw/gui_main.c 11 Feb 2005 20:02:56 -0000
@@ -851,9 +851,10 @@
**************************************************************************/
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] |
- [Freeciv-Dev] (PR#12219) fix bugs with real_timer_callback,
Jason Short <=
|
|