Tengo una función que utiliza difftime para detectar el tiempo en segundos desde que se detuvo el latido del corazón de la comunicación. Esta función podría ejecutarse tan rápido como cada 50 milisegundos. La función parece funcionar, excepto que de vez en cuando devuelve 65535. Puedo reducir la ejecución a una vez por segundo, ya que el retorno de difftime es solo en segundos. Pero no sé si va a solucionar el problema. ¿Es el problema porque no estoy lanzando correctamente el retorno de difftime a uint16_t desde el doble?
Este progtwig se ejecuta en una máquina de ubuntu 64bit.
Por favor ayuda. Gracias.
uint16_t commlost(uint16_t heartbeat_read_cur) { time_t current_time; static time_t previous_time; static uint16_t commlost_secs_cur = 0; static uint16_t commlost_secs_prev = 0; static uint16_t heartbeat_read_prev = 0; static bool first_time = TRUE; if (first_time) { previous_time = time(NULL); first_time = FALSE; } time(¤t_time); commlost_secs_prev = commlost_secs_cur; if(heartbeat_read_prev == heartbeat_read_cur) { commlost_secs_cur += difftime(current_time, previous_time); } else { heartbeat_read_prev = heartbeat_read_cur; commlost_secs_cur = 0; } previous_time = current_time; return (commlost_secs_cur); }
difftime()
se usa en sistemas donde time_t
admite el tiempo a una resolución más alta que los segundos integrales. Aunque permitido, nunca he encontrado un sistema así, no creo que exista uno. Específicamente en los sistemas POSIX, time_t
se mide en segundos integrales, y difftime()
es equivalente a la resta aritmética de sus argumentos, por lo que en realidad es mejor utilizar simplemente:
commlost_secs_cur += current_time - previous_time ;
Dicho esto, su implementación es algo demasiado compleja, en lugar de acumular tiempo desde la llamada anterior, que puede ser más pequeña que la resolución del reloj, simplemente puede marcar el último latido del corazón observado y devolver el tiempo desde entonces:
int commlost(uint16_t heartbeat_read_cur) { time_t current_time = time(0) ; static time_t heartbeat_timestamp = 0 ; static uint16_t heartbeat_read_prev ; // If first time, or heartbeat changed... if( heartbeat_timestamp == 0 || heartbeat_read_prev != heartbeat_read_cur) { // ... timestamp heartbeat heartbeat_timestamp = time(0) ; // ... keep last heartbeat heartbeat_read_prev = heartbeat_read_cur ; } // Return seconds since last heartbeat timestamp return current_time - heartbeat_timestamp ; }
No estoy seguro de por qué usaría uint16_t
para esto; hay poca o ninguna ventaja a menos que sea por compatibilidad con algún protocolo o formato de archivo específico.
Antes de consultar la hora, lea la página del manual de time (7) (y léala de nuevo).
Sugiero que use clock_gettime (2) con, por ejemplo, CLOCK_MONOTONIC
o CLOCK_REALTIME
, y preferiblemente use el double
para los cálculos de tiempo (ya que una struct timespec
es generalmente más grande que cualquier tipo integral).
No use uint16_t
para tales cálculos de tiempo.
Intenta usar
inline double double_gettime (clockid_t cid) { struct timespec ts = {0,0}; clock_gettime(cid, &ts); return (double)ts.tv_sec + 1.0e-9*ts.tv_nsec; }
¡Es posible que desee hacer esa función más sofisticada, probando si clock_gettime
está fallando y dando NAN
cuando falla! Esto se deja como un ejercicio para el lector. También puede, para CLOCK_REALTIME
, etc., medir la diferencia entre algún momento al inicio del proceso y el tiempo actual (es decir, calcular una struct timespec
de las diferencias de tiempo y convertir esa diferencia a un double
)
Entonces cosas como
double tstart = double_gettime(CLOCK_REALTIME); some_long_computation(); double tend = double_gettime(CLOCK_REALTIME); printf ("needed %f seconds to compute\n", tend-tstart);
Ver también reloj (3).