[Asio] Erratic results with io_service + deadline_timer
Today I tried using Boost.Asio to make a function get called at a particular time of day. My work included some tests, which usually passed but sometimes failed. I've boiled it down below. I'm using gcc 4.0.3 and Boost 1.35 on Linux 2.6.22 (Ubuntu Dapper 32-bit i686, quad-core CPU). I compiled the following code with g++ -lboost_thread -lboost_date_time -lboost_system : #include <boost/system/error_code.hpp> #include <boost/thread/thread.hpp> #include <boost/asio/io_service.hpp> #include <boost/asio/deadline_timer.hpp> #include <boost/date_time/posix_time/posix_time.hpp> using namespace boost; using namespace boost::asio; using namespace boost::posix_time; bool g_called = false; io_service g_svc; void func(boost::system::error_code ec) { g_called = true; } void work() { for(;;) { g_svc.run(); } } int main() { thread thr(work); #ifdef FAIL // if defined, causes program to always assert this_thread::sleep(milliseconds(1)); #endif deadline_timer tmr(g_svc, second_clock::local_time() + seconds(1)); tmr.async_wait(&func); // expected to wait 1 second then call func this_thread::sleep(milliseconds(1500)); assert(g_called); } I think my first issue was that I didn't recognize the need to call io_service::run in a loop. The docs<http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/reference/io_service/run.html>don't make this clear at all, stating that it will "Run the ... event processing loop," but I figured from reading the source that the loop in my own code was needed. Anyway, that didn't fix it. What I'm expecting here is that my callback function will be invoked about a second after registration, and it will set the flag which is then checked half a second later. When compiled as-is, this (usually) works. However, when compiled with -DFAIL, which just adds a tiny sleep in a place I'd think it would not matter, it fails always. Surely I'm doing something wrong. Or is the combination of this (new) library and my system just not working correctly (something I rather doubt given my past experience with Boost)?
for(;;) { g_svc.run(); }
You don't have to call run() in a loop. Instead, you have to give io_service some work *before* you call run() - it will exit when there's no more work to do. Anyway, if for some reason you have to call run() again, you're expected to call reset() prior to run(). Please, refer to the manual: http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/reference/io_servic...
participants (2)
-
Igor R
-
John Zwinck