Boost Deadline_Timer no esperando
-
28-10-2019 - |
Pregunta
Intenté usar Boost Deadline_Timer en esta aplicación de prueba simple, pero tuve algunos problemas. El objetivo es que el temporizador active cada 45 milisegundos utilizando el expires_at()
Función miembro del deadline_timer
. (Necesito un tiempo absoluto, así que no estoy considerando expires_from_now()
. Tampoco estoy preocupado por la deriva en este momento). Cuando ejecuto el programa, wait()
¡No espera 45 ms! Sin embargo, no se informan errores. ¿Estoy usando la biblioteca de alguna manera de alguna manera?
Programa de muestra:
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using namespace std;
int main()
{
boost::asio::io_service Service;
boost::shared_ptr<boost::thread> Thread;
boost::asio::io_service::work RunForever(Service);
Thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &Service)));
boost::shared_ptr<boost::asio::deadline_timer> Timer(new boost::asio::deadline_timer(Service));
while(1)
{
boost::posix_time::time_duration Duration;
Duration = boost::posix_time::microseconds(45000);
boost::posix_time::ptime Start = boost::posix_time::microsec_clock::local_time();
boost::posix_time::ptime Deadline = Start + Duration;
boost::system::error_code Error;
size_t Result = Timer->expires_at(Deadline, Error);
cout << Result << ' ' << Error << ' ';
Timer->wait(Error);
cout << Error << ' ';
boost::posix_time::ptime End = boost::posix_time::microsec_clock::local_time();
(cout << "Duration = " << (End - Start).total_milliseconds() << " milliseconds" << endl).flush();
}
return 0;
}
Solución
Estás mezclando la hora local con el tiempo del sistema. El momento en que ASIO compara su hora local es muy probable que sea un número de horas después del tiempo que desea que su fecha límite establezca, por lo que espera devoluciones de inmediato (dependiendo de dónde viva; este mismo código también podría esperar durante varias horas). Para evitar este punto de confusión, los tiempos absolutos deben derivarse de ASIO :: Time_Traits.
#include <boost/asio.hpp>
#include <boost/asio/time_traits.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using namespace std;
typedef boost::asio::time_traits<boost::posix_time::ptime> time_traits_t;
int main() {
boost::asio::io_service Service;
boost::shared_ptr<boost::thread> Thread;
boost::asio::io_service::work RunForever(Service);
Thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &Service)));
boost::shared_ptr<boost::asio::deadline_timer> Timer(new boost::asio::deadline_timer(Service));
while(1)
{
boost::posix_time::time_duration Duration;
Duration = boost::posix_time::microseconds(45000);
boost::posix_time::ptime Start = time_traits_t::now();
boost::posix_time::ptime Deadline = Start + Duration;
boost::system::error_code Error;
size_t Result = Timer->expires_at(Deadline, Error);
cout << Result << ' ' << Error << ' ';
Timer->wait(Error);
cout << Error << ' ';
boost::posix_time::ptime End = boost::posix_time::microsec_clock::local_time();
(cout << "Duration = " << (End - Start).total_milliseconds() << " milliseconds" << endl).flush();
}
return 0;
}
Eso debería funcionar para usted en este caso.
Otros consejos
Estás mezclando métodos asíncronos io_service::run
con métodos sincrónicos deadline_timer::wait
. Esto no funcionará. Ya sea deadline_timer::async_wait
con io_service::run
, o omita el io_service::run
Y solo usa deadline_timer::wait
. Tampoco necesitas un hilo para invocar io_service:run
Si sigue la ruta asíncrona, un hilo funcionará bien. Ambos conceptos se explican en detalle en el Habilidades básicas Sección de la Tutorial ASIO.
void print(const boost::system::error_code& /*e*/)
{
std::cout << "Hello, world!\n";
}
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
t.async_wait(print);
io.run();
return 0;
}
Nota que deberá dar un trabajo para su io_service
al servicio antes de invocar run()
. En este ejemplo, async_wait
es ese trabajo.
Potencialmente no relacionado: 45ms es un delta bastante pequeño. En mi experiencia, el momento más pequeño para que cualquier manejador atraviese la cola de reactores ASIO Epoll sea de alrededor de 30 ms, esto puede ser considerablemente más largo con cargas más altas. Aunque todo depende en gran medida de su aplicación.