steady_clock example c++ c++11 chrono

example - date c++



C++ ¿Cómo convierto un std:: chrono:: time_point a largo y viceversa (4)

También señalaría que hay dos formas de obtener el número de ms en el punto de tiempo. No estoy seguro de cuál es mejor, los he comparado y ambos tienen el mismo rendimiento, así que supongo que es una cuestión de preferencia. Quizás Howard podría intervenir:

auto now = system_clock::now(); //Cast the time point to ms, then get its duration, then get the duration''s count. auto ms = time_point_cast<milliseconds>(now).time_since_epoch().count(); //Get the time point''s duration, then cast to ms, then get its count. auto ms = duration_cast<milliseconds>(tpBid.time_since_epoch()).count();

El primero lee más claramente en mi mente yendo de izquierda a derecha.

Necesito convertir std::chrono::time_point desde un tipo long (entero de 64 bits). Estoy empezando a trabajar con std::chrono ...

Aquí está mi código:

int main () { std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); auto epoch = now.time_since_epoch(); auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch); long duration = value.count(); std::chrono::duration<long> dur(duration); std::chrono::time_point<std::chrono::system_clock> dt(dur); if (dt != now) std::cout << "Failure." << std::endl; else std::cout << "Success." << std::endl; }

Este código se compila, pero no muestra el éxito.

¿Por qué es dt diferente de now al final?

¿Qué falta en ese código?


como una sola línea:

long value_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch()).count();


time_point objetos de punto de tiempo solo admiten aritmética con otros objetos de punto de duration o duration .

Tendrá que convertir su unidad long a una duration de unidades específicas, luego su código debería funcionar correctamente.


std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();

Este es un gran lugar para auto :

auto now = std::chrono::system_clock::now();

Dado que desea traficar con una precisión de millisecond , sería bueno seguir adelante y encubrirlo en el time_point :

auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);

now_ms es un time_point , basado en system_clock , pero con la precisión de milliseconds lugar de la precisión que tenga su system_clock .

auto epoch = now_ms.time_since_epoch();

epoch ahora tiene el tipo std::chrono::milliseconds . Y esta siguiente declaración se convierte esencialmente en un no-op (simplemente hace una copia y no hace una conversión):

auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);

Aquí:

long duration = value.count();

Tanto en su código como en mi, la duration contiene el número de milliseconds desde la época de system_clock .

Esta:

std::chrono::duration<long> dur(duration);

Crea una duration representada con un long y una precisión de seconds . Esto reinterpret_cast efectivamente los milliseconds en value en seconds . Es un error lógico. El código correcto se vería así:

std::chrono::milliseconds dur(duration);

Esta línea:

std::chrono::time_point<std::chrono::system_clock> dt(dur);

crea un time_point basado en system_clock , con la capacidad de mantener una precisión a la precisión nativa de system_clock (generalmente más fina que milisegundos). Sin embargo, el valor de tiempo de ejecución reflejará correctamente que se mantiene un número integral de milisegundos (suponiendo mi corrección en el tipo de dur ).

Sin embargo, incluso con la corrección, esta prueba fallará (casi siempre):

if (dt != now)

Porque dt tiene un número integral de milliseconds , pero now tiene un número integral de tics más fino que un millisecond (por ejemplo, microseconds o nanoseconds ). Por lo tanto, solo en la rara posibilidad de que system_clock::now() devuelva un número integral de milliseconds pasaría la prueba.

Pero en su lugar puedes:

if (dt != now_ms)

Y ahora obtendrá el resultado esperado de manera confiable.

Poniendolo todo junto:

int main () { auto now = std::chrono::system_clock::now(); auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now); auto value = now_ms.time_since_epoch(); long duration = value.count(); std::chrono::milliseconds dur(duration); std::chrono::time_point<std::chrono::system_clock> dt(dur); if (dt != now_ms) std::cout << "Failure." << std::endl; else std::cout << "Success." << std::endl; }

Personalmente, encuentro todo el std::chrono demasiado detallado y lo codifico como:

int main () { using namespace std::chrono; auto now = system_clock::now(); auto now_ms = time_point_cast<milliseconds>(now); auto value = now_ms.time_since_epoch(); long duration = value.count(); milliseconds dur(duration); time_point<system_clock> dt(dur); if (dt != now_ms) std::cout << "Failure." << std::endl; else std::cout << "Success." << std::endl; }

Lo que generará de manera confiable:

Success.

Finalmente, recomiendo eliminar los temporales para reducir al mínimo la conversión del código entre time_point y el tipo integral. Estas conversiones son peligrosas, por lo que cuanto menos código escriba al manipular el tipo integral simple, mejor:

int main () { using namespace std::chrono; // Get current time with precision of milliseconds auto now = time_point_cast<milliseconds>(system_clock::now()); // sys_milliseconds is type time_point<system_clock, milliseconds> using sys_milliseconds = decltype(now); // Convert time_point to signed integral type auto integral_duration = now.time_since_epoch().count(); // Convert signed integral type to time_point sys_milliseconds dt{milliseconds{integral_duration}}; // test if (dt != now) std::cout << "Failure." << std::endl; else std::cout << "Success." << std::endl; }

El principal peligro anterior no es interpretar la time_point integral_duration como milliseconds en el camino de regreso a un time_point . Una posible forma de mitigar ese riesgo es escribir:

sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};

Esto reduce el riesgo a solo asegurarse de usar sys_milliseconds al salir y en los dos lugares al regresar.

Y un ejemplo más: supongamos que desea convertir ay desde una integral que representa la duración que admite system_clock (microsegundos, décimo de microsegundos o nanosegundos). Entonces no tiene que preocuparse por especificar milisegundos como se indicó anteriormente. El código se simplifica a:

int main () { using namespace std::chrono; // Get current time with native precision auto now = system_clock::now(); // Convert time_point to signed integral type auto integral_duration = now.time_since_epoch().count(); // Convert signed integral type to time_point system_clock::time_point dt{system_clock::duration{integral_duration}}; // test if (dt != now) std::cout << "Failure." << std::endl; else std::cout << "Success." << std::endl; }

Esto funciona, pero si ejecuta la mitad de la conversión (en integral) en una plataforma y la otra mitad (en integral) en otra plataforma, corre el riesgo de que system_clock::duration tenga diferentes precisiones para las dos conversiones.