Как сравнить две метки времени в C? - PullRequest
11 голосов
/ 07 декабря 2009

Я пишу программу для сокетов, которая поддерживает очереди FIFO для двух входных сокетов. При принятии решения, какую очередь обслуживать, программа извлекает самую последнюю отметку времени из каждой очереди.

Мне нужен надежный метод для сравнения двух timeval структур. Я попытался использовать timercmp(), но моя версия gcc не поддерживает его, и в документации говорится, что функция не совместима с POSIX.

Что мне делать?

Ответы [ 3 ]

12 голосов
/ 07 декабря 2009

timercmp() - это просто макрос в libc (sys / time.h):

# define timercmp(a, b, CMP)                                                  \
  (((a)->tv_sec == (b)->tv_sec) ?                                             \
   ((a)->tv_usec CMP (b)->tv_usec) :                                          \
   ((a)->tv_sec CMP (b)->tv_sec))

Если вам нужно timersub():

# define timersub(a, b, result)                                               \
  do {                                                                        \
    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
    if ((result)->tv_usec < 0) {                                              \
      --(result)->tv_sec;                                                     \
      (result)->tv_usec += 1000000;                                           \
    }                                                                         \
  } while (0)
6 голосов
/ 07 декабря 2009

поиск в Google timeval дает этот первый результат . С этой страницы:

Часто необходимо вычесть два значения типа struct timeval или struct timespec. Вот лучший способ сделать это. Он работает даже в некоторых специфических операционных системах, где член tv_sec имеет тип unsigned.

 /* Subtract the `struct timeval' values X and Y,
    storing the result in RESULT.
    Return 1 if the difference is negative, otherwise 0.  */

 int
 timeval_subtract (result, x, y)
      struct timeval *result, *x, *y;
 {
   /* Perform the carry for the later subtraction by updating y. */
   if (x->tv_usec < y->tv_usec) {
     int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
     y->tv_usec -= 1000000 * nsec;
     y->tv_sec += nsec;
   }
   if (x->tv_usec - y->tv_usec > 1000000) {
     int nsec = (x->tv_usec - y->tv_usec) / 1000000;
     y->tv_usec += 1000000 * nsec;
     y->tv_sec -= nsec;
   }

   /* Compute the time remaining to wait.
      tv_usec is certainly positive. */
   result->tv_sec = x->tv_sec - y->tv_sec;
   result->tv_usec = x->tv_usec - y->tv_usec;

   /* Return 1 if result is negative. */
   return x->tv_sec < y->tv_sec;
 }
0 голосов
/ 07 мая 2012

Это немного отличается, но я думаю, что ясно иллюстрирует вовлеченную логику. Я работаю над некоторым кодом MSP430 на C, и у меня есть структура меток времени, очень похожая на timeval, но с nsecs вместо usecs.

Этот код сохраняет все положительные значения, поэтому беззнаковые целочисленные значения будут работать нормально и избегать переполнений (я думаю). Он также не изменяет передаваемые временные метки / временные интервалы, кроме результата, конечно.

typedef struct timestamp {
    int32_t secs;
    int32_t nsecs;
} timestamp_t;

int timestamp_sub(timestamp_t * x, timestamp_t * y, timestamp_t * result){
    // returns 1 if difference is negative, 0 otherwise
    // result is the absolute value of the difference between x and y
    negative = 0;
    if( x->secs > y->secs ){
        if( x->nsecs > y->nsecs ){
            result->secs = x->secs - y->secs;
            result->nsecs = x->nsecs - y->nsecs;
        }else{
            result->secs = x->secs - y->secs - 1;
            result->nsecs = (1000*1000*1000) - y->nsecs + x->nsecs;
        }
    }else{
        if( x->secs == y->secs ){
            result->secs = 0;
            if( x->nsecs > y->nsecs ){
                result->nsecs = x->nsecs - y->nsecs;
            }else{
                negative = 1;
                result->nsecs = y->nsecs - x->nsecs;
            }
        }else{
            negative = 1;
            if( x->nsecs > y->nsecs ){
                result->secs = y->secs - x->secs - 1;
                result->nsecs = (1000*1000*1000) - x->nsecs + y->nsecs;
            }else{
                result->secs = y->secs - x->secs;
                result->nsecs = y->nsecs - x->nsecs;
            }
        }
    }
    return negative;
}
...