Atomically cancel asio asynchronous timer from another thread

I have a deadline_timer boost that runs periodically (as in the example http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/tutorial/tuttimer3/src.html ):

#include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/date_time/posix_time/posix_time.hpp> void print(const boost::system::error_code& /*e*/, boost::asio::deadline_timer* t) { t->expires_at(t->expires_at() + boost::posix_time::seconds(1)); t->async_wait(boost::bind(print, boost::asio::placeholders::error, t, count)); } int main() { boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(1)); t.async_wait(boost::bind(print, boost::asio::placeholders::error, &t)); io.run(); return 0; } 

Now I need to cancel it from another thread. But what if a cancel call appears only while the print function is running, but before expires_at expires? Then the timer will continue to work.

One way to handle this is to run something like

 while (timer.cancel() == 0) { } 

in this separate stream function.

But maybe someone knows a more elegant way that this problem can be solved?

0
source share
1 answer

In fact, both approaches are not entirely safe, simply because deadline_timer not thread safe .

IMO, the easiest and safest way is post cancellation:

 //... timer.get_io_service().post([&]{timer.cancel();}) //... 

NOTE: in real code, you need to make sure that the timer survives the functor (lambda).

UPDATE: as mentioned above, this solution may not work, because the cancel handler may appear in the io_service queue immediately before print , when the timer no longer waits.

+2
source

Source: https://habr.com/ru/post/1266230/


All Articles