2009-12-07 14 views
10

Sto scrivendo un programma socket che mantiene le code FIFO per due socket di input. Al momento di decidere quale coda servire, il programma tira il timestamp più recente da ogni coda.Come faccio a confrontare due timestamp in C?

Ho bisogno di un metodo affidabile per confrontare due strutture timeval. Ho provato a utilizzare timercmp(), ma la mia versione di gcc non lo supporta e la documentazione indica che la funzione non è conforme a POSIX.

Cosa devo fare?

risposta

5

googling timeval dare this first result. Da quella pagina:

Spesso è necessario sottrarre due valori di tipo struct timeval o struct timespec. Ecco il modo migliore per farlo. Funziona anche su alcuni sistemi operativi particolari in cui il membro tv_sec ha un tipo senza segno.

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

Grazie per il suggerimento, ma sto già utilizzando il codice. In realtà, ho appena capito qual era il mio problema. Grazie per aver controllato Google, è probabilmente la prima cosa che avrei postato come risposta. =) –

+2

Per chiarire, mi sono reso conto che i tempi erano inizializzati per avere valori di 'tv_sec' e' tv_usec' di 0. L'uso di 'gettimeofday()' per inizializzare correttamente le code ha risolto il problema. Grazie per il supporto. =) –

+0

2Shelly, aggiungerei che IMHO è meglio cambiare la seconda condizione nel seguente modo 'x-> tv_usec - y-> tv_usec> = 1000000' per convertire il tempo come' 5/1000000' in '6/0 '. – Kolyunya

11

timercmp() è solo una macro in 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)) 

Se avete bisogno di 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) 
+0

Richiede la definizione della macro _BSD_SOURCE se la compilazione su Linux. –

0

Questo è leggermente diverso, ma credo che chiaramente illustra la logica coinvolta. Sto lavorando su un codice MSP430 in C, e ho una struttura timestamp molto simile al tempo, ma con nsecs anziché usecs.

Questo codice mantiene tutto positivo, quindi gli interi non firmati funzionerebbero bene ed eviterà overflow (penso). Inoltre, non modifica i timestamp/i messaggi di tempo che vengono inoltrati, ad eccezione ovviamente del risultato.

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

È preferibile utilizzare numero intero '1000000000' (o' 1000 * 1000 * 1000' se si preferisce) piuttosto che '1e9' a virgola mobile, poiché il primo è probabilmente più efficiente. –

Problemi correlati