Tiempo en milisegundos en unix

other
20 de Noviembre del 2003
Estoy realizando un programa multihebra. Además este programa recibe órdenes desde los sockets y las ejecuta. Antes de ejecutarlas debe comprobar que ha pasado suficiente tiempo (300 milisegundos) desde la ultima vez que la ejecutó.
Para resolver esto he intentado varias soluciones:
-----Utilizar la función clock()
La idea era guardar el clock() de la última vez que se ejecutó la acción y compararlo con el clock() en el momento de volver a intentarlo. El problema es que la función clock() no funciona correctamente en programas multihebra, ya que cuenta el tiempo en base al número de clocks que lleva ejecutándose el proceso actual, y cada hebra es para linux un proceso diferente.

-----Utilizar la funcion time()
Tampoco es válido, por que la estructura en la que time almacena sus datos (time_t) tiene como medida más pequeña los segundos (int) y yo necesito trabajar con tiempos del orden de milisegundos.

----Activar una variable "preparado" y que una hebra auxiliar espere con la funcion usleep y luego cambie el valor de preparado.
Es la única alternativa que se me ocurre. No la he probado, aún así que no se si dará algún problema.

Me gustaría saber si conocen alguna forma de medir el tiempo transcurrido entre dos instantes con c++ en unix en milisegundos y utilizando hebras.
Gracias.

ivan
20 de Noviembre del 2003
El problema al que te refiere es de "planificación de procesos" una actividad que usualmente es reservada a los sistemas operativos. Como tal, UNIX o Linux te proporcionan una vía diferente para hacer lo que quieres...

Veras, si haces que el hilo que hace su trabajo "rechaze" ejecutarse hasta tanto transcurran los 300 milisegundos, ¿que podria pensar el sistema operativo de él? La idea es que implementar esto de esa forma es solo una forma de hacer un blucle de espera, un algoritmo no demaciado optimo.

La solución es utilizar un sistema de alarma, donde sea el sistema operativo el que se encargue de llamarte cada vez que transcurran 300 milisegundos. En una palabra: "confianza", confia en el sistema operativo...

La solución con usleep() es una primera aproximación bastante buena. Por todo lo dicho hasta aquí, sería el sistema operativo quien esperaria el tiempo apropiado.

En el fondo, usleep() utiliza la siguiente tecnica: programa una señal y luego se bloquea, a la espera de la señal en sí.

POSIX incluye funciones para programar señales "de tiempo real" que te pueden proporcionar la resolución apropiada para implementar tu programa.

Finalmente, las señales y sus manejadores, van por hilo. O en otras palabras, cada hilo podra establecer su propia serie de llamadas, señales, y manejadores.

Solo recuerda un ultimo dato: "deriva". La deriva es que el sistema de alarma te llame, no cada 300 milisegundos, sino cada 300 milisegundos despues de la ultima llamada... que es sutilmente diferente a lo que necesitas.

Cada vez que resivas la señal de la alarma, debes programar la siguiente, pero no diciendo que dentro de 300 milisegundos, sino calculando el momento a partir de tu serie original. De esta forma, el proceso sera activado cada 300 milisegundos, independientemente del tiempo que tarde en ejecutarse... tendras deriva, pero minima.

pther
20 de Noviembre del 2003
Muchas gracias por la respuesta, aunque no he llegado a comprenderla del todo.
El problema es que yo no puedo detener el proceso. Yo tengo que hacer una comprobación del tipo (hora_actual>hora_proxima acción) y según el resultado hacer una u otra cosa (decir al cliente que no puede realizar la acción y intentar recibir otra o decir al cliente el resultado de la acción)
Al final lo he resuelto del siguiente modo:
He creado una hebra especifica desde el programa principal que consiste en un ciclo infinito como este:
while (true)
{
tiempo+=15;
usleep(15);
}

Tiempo es una variable global que en un principio vale 0. De este modo desde cualquier lugar o hebra del programa puedo acceder a tiempo, que me dirá el número de milisegundos transcurridos desde que se inició el programa. Es posible que esto no sea exacto, por que si el Sist. Operativo no tiene tiempo de proceso para la hebra que se encarga de mantener tiempo, es posible que tarde algunos milisegundos más en permitirle sumar 15 a tiempo, pero no necesitaba precisión hasta esos extremos, y con esto funciona a la perfección.
Por cierto, se trata de un juego que estamos desarrollando en un grupo de programación (www.hewop.com).
Son batallitas de robots, en las que el robot no puede realizar un disparo si disparó hace menso de X milisegundos.
Lo verdaderamente curioso de este juego es que no se juega interactivamente, los jugadores programan un cliente que juege con ellos, y así vemos quien hace mejores algoritmos...
Muchas gracias por todo!