Как сравнить две метки времени в C?

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

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

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

Ответ 1

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

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

 /* 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;
 }

Ответ 2

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)

Ответ 3

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

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

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;
}