W3C home > Mailing lists > Public > www-lib@w3.org > October to December 2001

Re: time_t, ms_t, overflow issues

From: Ingo Krabbe <ikrabbe@earthling.net>
Date: Fri, 23 Nov 2001 20:15:41 +0100 (CET)
To: Phil Nitschke <Phil.Nitschke@youramigo.com>
cc: <www-lib@w3.org>
Message-ID: <Pine.slx.4.33.0111232014190.4150-100000@dimwit.burg.de>
> /* ... */
>
> Platform:
>
>     Linux strife 2.4.4 #1 Tue May 22 11:04:41 CST 2001 i686 unknown
>
> Source:
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <time.h>
> #include <sys/time.h>
>
> typedef unsigned long ms_t;
>
> ms_t HTGetTimeInMillis2 (const struct timeval * tp)
> {
>   return(tp->tv_sec * 1000) + (tp->tv_usec / 1000);
> }
>
> void do_tests (struct timeval * tp)
> {
>   ms_t prev_time, new_time;
>
>   prev_time = HTGetTimeInMillis2 (tp);
>   tp->tv_sec += 3;
>
>   for (;;)
>     {
>       tp->tv_sec++;
>       new_time = HTGetTimeInMillis2 (tp);
>
>       if (new_time <= prev_time)
> 	break;
>
>       prev_time = new_time;
>     }
>
>   printf ("Overflow broke at %s Performing comparison of: %lu and %lu !!\n",
> 	  ctime ((time_t *)&tp->tv_sec), new_time, prev_time);
> }
>
> int main (void)
> {
>   int i;
>   struct timeval tp;
>
>   gettimeofday(&tp, NULL);
>
>   for (i = 0; i < 10; i++)
>     do_tests (&tp);
>
>   exit (0);
> }
>

These result are exactly the results I meant to be easily resolved by
scale discussion:

    Overflow broke at Wed Dec 26 08:25:14 2001
     Performing comparison of: 418 and 4294966714 !!
    Overflow broke at Thu Feb 14 01:28:01 2002
     Performing comparison of: 122 and 4294966418 !!
    Overflow broke at Thu Apr  4 17:30:49 2002
     Performing comparison of: 826 and 4294967122 !!
    Overflow broke at Fri May 24 10:33:36 2002
     Performing comparison of: 530 and 4294966826 !!
    Overflow broke at Sat Jul 13 03:36:23 2002
     Performing comparison of: 234 and 4294966530 !!
    Overflow broke at Sat Aug 31 20:39:11 2002
     Performing comparison of: 938 and 4294967234 !!
    Overflow broke at Sun Oct 20 13:41:58 2002
     Performing comparison of: 642 and 4294966938 !!
    Overflow broke at Mon Dec  9 07:44:45 2002
     Performing comparison of: 346 and 4294966642 !!
    Overflow broke at Tue Jan 28 00:47:32 2003
     Performing comparison of: 50 and 4294966346 !!
    Overflow broke at Tue Mar 18 17:50:20 2003
     Performing comparison of: 754 and 4294967050 !!

The second number is always near to

	2^32 = 4294967296

The first number is always near to 0 !

Let's take a milliseconds scale of 3600 seconds = 1 day. If two values are
farer away from each other we DEFINE that we CANNOT express this INTERVAL in
milliseconds but have to take more care for them:

ms_t HTGetTimeInMillis
/*
	...
*/

struct tm	X, Y;	/* long range interval */
ms_t		a, b;	/* interval */
struct timeval	t0, t1;	/* other time coordinates */

X = get_tm_from_timeval( t0 );
a = HTGetTimeInMillis2( t0 );
for ( ;; )
{
	ms_t		distance;
	int		overflow_type = 0;
	t1 = gettimeofday();
	b = HTGetTimeInMillis2( t1 );
	distance = 0;
	if ( a < b )	/* first ok */
	{
		distance = b - a;
		if ( distance > 3600000 )
		{
			distance %= 3600000;
			overflow_type = 1;
		}
	}
	else if ( a > b )
	{
		overflow_type = 2;
		distance = ((ms_t)(-1))-a + b; /* have a forgot 1 ms ? */
		if ( distance > 3600000 )
		{
			distance %= 3600000;
			overflow_type = 3;
		}
	}
	if ( overflow_type & 1 )
	{
		switch ( overflow_type )
		{
			/*
				think about long range distances,
				in most cases we don't need to do
				that, since our problem simply doesn't
				allow such intervals --> we have a real
				error condition
			*/
		}
	}
	else
	{
		/* ok, proceed */
	}
}

Here you can see that on ms_t overflow we simply proceed with
((ms_t)(-1)) - a + b which will fit again in the unsigned type !
We can do this since we know that !!! a IS SMALLER THAN b !!!
Real problems are overflow_type 1 and 3 since they break our previous
definition of one day intervals. Our timeout condition for example is quite
over reached, so we (MAY) need a special handling. If you really want to
calculate an exact time interval you can now proceed with a
struct tm calculation with which you can really can express the age of
Napoleon in years, days and milliseconds :-)

CU INGO
Received on Friday, 23 November 2001 14:15:23 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 23 April 2007 18:18:40 GMT