Reputation: 323
I have a requirement such that my timer must be reset based on 2 conditions, whichever happens earlier.
I am following these steps:
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));
boost::mutex mtx1;
void run_io_service()
{
io.run();
}
void print(const boost::system::error_code& /*e*/)
{
boost::mutex::scoped_lock lock(mtx1);
std::cout << "Hello, world!\n";
t.expires_from_now(boost::posix_time::seconds(1));
t.async_wait(print);
std::cout << "Print executed\n";
}
int main()
{
t.async_wait(print);
boost::thread monitoring_thread = boost::thread(run_io_service);
boost::this_thread::sleep( boost::posix_time::seconds(2));
t.cancel();
std::cout << "Resetting Timer\n";
t.async_wait(print);
boost::this_thread::sleep( boost::posix_time::seconds(2));
t.cancel();
io.stop();
monitoring_thread.join();
return 0;
}
This code works fine till the time timer hasn't been cancelled. Once timer has been cancelled, timer doesn't work in expected way, it doesn't work at all.
What am I doing wrong?
Upvotes: 2
Views: 8700
Reputation: 2995
The first problem is that the handler will still be called if there is an error (such as it being cancelled), you need to check the error code.
void print(const boost::system::error_code& e )
{
if( e ) return; // we were cancelled
// actual error code for cancelled is boost::asio::error::operation_aborted
boost::mutex::scoped_lock lock(mtx1);
std::cout << "Hello, world!\n";
t.expires_from_now(boost::posix_time::seconds(1));
t.async_wait(print);
std::cout << "Print executed\n";
}
Secondly, when you cancel the timer, that leaves the io_service object without any work, which means the run_io_service thread will terminate and leave you without service. To keep the service alive during the whole program, give it a work object at the start of main:
int main() {
boost::asio::io_service::work work(io);
...
And.. as mentioned by sehe, you are not handling the timer safely (or std::cout). You should be locking mtx1 when you print the reset message and reset the timer, otherwise Murphy's law dictates that it may occur at the exact moment the handler is running and mess things up.
Upvotes: 5
Reputation: 393457
You need to set a new expiration.
In fact, you don't have to explicitly cancel in this event, because setting a new experation implicitly cancels any pending async wait.
Keep in mind that the deadline_timer object itself is not thread safe though, so you will need to keep your timer mutations synchronized.
Upvotes: 2