Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2004:
[Freeciv-Dev] Re: (PR#8073) win32: unit moves aren't smooth
Home

[Freeciv-Dev] Re: (PR#8073) win32: unit moves aren't smooth

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: use_less@xxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#8073) win32: unit moves aren't smooth
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 15 Mar 2004 13:05:17 -0800
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8073 >

Jason Short wrote:
> <URL: http://rt.freeciv.org/Ticket/Display.html?id=8073 >
> 
> Jason Short wrote:
> 
>><URL: http://rt.freeciv.org/Ticket/Display.html?id=8073 >
>>
>>James Canete wrote:
>>
>>
>>
>>>After a little research, I find that mingw has no support for
>>>gettimeofday(), which is required for millisecond resolution for freeciv
>>>timers.
>>
>>
>>Ouch.  If you can figure out what replacement functions to use instead 
>>(there must be one!) we can add an appropriate configure check and 
>>change timer.c.
> 
> 
> I believe ftime() should work.

And the patch.  Please test it (remember to rerun autogen.sh first).


The patch is fine so far as it goes.  However the timing code does have 
problems.

- When we have to fall back to using time(), the semantics completely 
change.  Now usleep_since_timer_start(usec) will just sleep usec 
seconds.  So this code

   timer = renew_timer_start(timer, ...);
   usleep_since_timer_start(timer, 20000);

will work but

   timer = renew_timer_start(timer, ...);
   for (i = 0; i < 10; i++) {
     usleep_since_timer_start(timer, i * 20000);
   }

will not.  I still believe the time() method should be dropped and we 
should just fail if this happens.  (If this happen someone will report 
it and we can fix it.  All platforms should have a working timer function!)

- The code is way longer than it needs to be.  It would be much better 
if we just tracked everything in seconds using a double.  Then the 
t->usec value would go away and t->start would be replaced with a 
double.  Half of the code in the file could be removed.  The only 
drawback is a possible reduction in accuracy (which seems unlikely to 
affect anything, but could be fixed by using an even more accurate type).

One final issue is with broken implementations.  gettimeofday() has a 
special check to make sure that the function returns sane values 
(apparently some glibc's are broken).  ftime has no such check; 
configure just checks to see if it exists.  So if ftime exists but is 
broken there will be problems (since ftime is likely a wrapper for 
gettimeofday this is actually an issue).  On the other hand the 
alternative is to fall back to using time() which is far worse even than 
a slightly broken ftime.  An additional alternative is to check for and 
use clock_gettime().

jason

Index: configure.ac
===================================================================
RCS file: /home/freeciv/CVS/freeciv/configure.ac,v
retrieving revision 1.55
diff -u -r1.55 configure.ac
--- configure.ac        26 Feb 2004 13:32:20 -0000      1.55
+++ configure.ac        15 Mar 2004 20:50:43 -0000
@@ -541,9 +541,9 @@
 AC_FUNC_VPRINTF
 AC_FUNC_VSNPRINTF
 
-AC_CHECK_FUNCS(fileno gethostname getpwuid inet_aton \
-               select snooze strerror strcasecmp strncasecmp \
-               strlcat strlcpy strstr usleep vsnprintf uname flock)
+AC_CHECK_FUNCS([fileno ftime gethostname getpwuid inet_aton \
+               select snooze strerror strcasecmp strncasecmp \
+               strlcat strlcpy strstr usleep vsnprintf uname flock])
 
 AC_MSG_CHECKING(for working gettimeofday)
   FC_CHECK_GETTIMEOFDAY_RUNTIME(,AC_DEFINE(HAVE_GETTIMEOFDAY, 1,
Index: configure.in
===================================================================
RCS file: /home/freeciv/CVS/freeciv/configure.in,v
retrieving revision 1.230
diff -u -r1.230 configure.in
--- configure.in        10 Mar 2004 22:14:27 -0000      1.230
+++ configure.in        15 Mar 2004 20:50:43 -0000
@@ -525,9 +525,9 @@
 AC_FUNC_VPRINTF
 AC_FUNC_VSNPRINTF
 
-AC_CHECK_FUNCS(fileno gethostname getpwuid inet_aton \
-               select snooze strerror strcasecmp strncasecmp \
-               strlcat strlcpy strstr usleep vsnprintf uname flock)
+AC_CHECK_FUNCS([fileno ftime gethostname getpwuid inet_aton \
+               select snooze strerror strcasecmp strncasecmp \
+               strlcat strlcpy strstr usleep vsnprintf uname flock\)
 AC_MSG_CHECKING(for working gettimeofday)
   FC_CHECK_GETTIMEOFDAY_RUNTIME(,AC_DEFINE(HAVE_GETTIMEOFDAY),)
 
Index: common/timing.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/timing.c,v
retrieving revision 1.11
diff -u -r1.11 timing.c
--- common/timing.c     4 Apr 2003 15:47:49 -0000       1.11
+++ common/timing.c     15 Mar 2004 20:50:43 -0000
@@ -52,6 +52,10 @@
 #include <unistd.h>
 #endif
 
+#ifdef HAVE_FTIME
+# include <sys/timeb.h>
+#endif
+
 #include "log.h"
 #include "mem.h"
 #include "shared.h"            /* TRUE, FALSE */
@@ -90,6 +94,8 @@
     clock_t c;
 #ifdef HAVE_GETTIMEOFDAY
     struct timeval tv;
+#elif HAVE_FTIME
+    struct timeb tp;
 #else
     time_t t;
 #endif
@@ -126,7 +132,7 @@
   }
   t->use = TIMER_IGNORE;
 }
-#else
+#elsif !defined HAVE_FTIME
 /********************************************************************** 
   Report if time() returns -1, but only the first time.
   Ignore this timer from now on.
@@ -260,6 +266,11 @@
       report_gettimeofday_failed(t);
       return;
     }
+#elif defined HAVE_FTIME
+    if (ftime(&t->start.tp) != 0) {
+      /* Should never happen. */
+      assert(0);
+    }
 #else
     t->start.t = time(NULL);
     if (t->start.t == (time_t) -1) {
@@ -324,6 +335,24 @@
       t->usec -= sec * N_USEC_PER_SEC;
     }
     t->start.tv = now;
+#elif defined HAVE_FTIME
+    struct timeb now;
+
+    if (ftime(&now) != 0) {
+      /* Should never happen. */
+      assert(0);
+    }
+    t->usec += 1000 * ((long)now.millitm - (long)t->start.tp.millitm);
+    t->sec += now.time - t->start.tp.time;
+    if (t->usec < 0) {
+      t->usec += N_USEC_PER_SEC;
+      t->sec -= 1.0;
+    } else if (t->usec >= N_USEC_PER_SEC) {
+      long sec = t->usec / N_USEC_PER_SEC;
+      t->sec += sec;
+      t->usec -= sec * N_USEC_PER_SEC;
+    }
+    t->start.tp = now;
 #else
     time_t now = time(NULL);
     if (now == (time_t) -1) {
@@ -407,6 +436,22 @@
 
   if (wait_usec > 0)
     myusleep(wait_usec);
+#elif HAVE_FTIME
+  struct timeb now;
+  long elapsed_usec, wait_usec;
+
+  if (ftime(&now) != 0) {
+    /* Should never happen. */
+    assert(0);
+  }
+
+  elapsed_usec = (now.time - t->start.tp.time) * N_USEC_PER_SEC
+    + (now.millitm - t->start.tp.millitm);
+  wait_usec = usec - elapsed_usec;
+
+  if (wait_usec > 0) {
+    myusleep(wait_usec);
+  }
 #else
   myusleep(usec);
 #endif

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