Re: [Boost-users] [Asio] Does stop() cancel handlers post()ed to io_service?

The program below gives different results on Windows (Visual Studio 2008) and Linux. While stop() does cancel the handlers on Linux, the same is not true for Windows. I also tried to destroy the io_service object instead of calling stop, but this does not cancel the handlers on either system, even though the documentation seems to state it should.
It would be more accurate to say "on Windows asio::io_service::stop() does not cancel already queued (!) handlers". See example below. ~~~~~~~~~~~~~~~~~~~~~~~ #if defined(WIN32) #include <tchar.h> #endif #include <cstdlib> #include <cstddef> #include <iostream> #include <boost/ref.hpp> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/thread.hpp> #include <boost/function.hpp> namespace { typedef boost::function<void (boost::asio::io_service&)> work_factory; void run_test(work_factory wf) { { boost::asio::io_service io_service; { wf(io_service); std::cout << "io_service work created" << std::endl; { std::cout << "work thread starting..." << std::endl; boost::thread work_thread(boost::bind( &boost::asio::io_service::run, boost::ref(io_service))); boost::this_thread::sleep(boost::posix_time::millisec(300)); io_service.stop(); std::cout << "io_service signalled to stop" << std::endl; work_thread.join(); std::cout << "work thread stopped" << std::endl; } } std::cout << "destroying io_service..." << std::endl; } std::cout << "io_service destroyed" << std::endl; } void test_function1() { static int counter = 0; std::cout << "handler #" << counter++ << std::endl; boost::this_thread::sleep(boost::posix_time::millisec(100)); } void post_test_function1(boost::asio::io_service& io_service) { for (std::size_t i = 0; i != 10; ++i) { io_service.post(&test_function1); } } void post_test_function2(boost::asio::io_service&); void test_function2(boost::asio::io_service& io_service) { static int counter = 0; std::cout << "handler #" << counter++ << std::endl; boost::this_thread::sleep(boost::posix_time::millisec(100)); post_test_function2(io_service); } void post_test_function2(boost::asio::io_service& io_service) { io_service.post(boost::bind(test_function2, boost::ref(io_service))); } } // anonymous namespace #if defined(WIN32) int _tmain(int /*argc*/, _TCHAR* /*argv*/[]) #else int main(int /*argc*/, char* /*argv*/[]) #endif { std::cout << "Test 1" << std::endl; run_test(post_test_function1); std::cout << std::endl << "Test 2" << std::endl; run_test(post_test_function2); return EXIT_SUCCESS; } ~~~~~~~~~~~~~~~~~~~~~~~ Regards, Marat Abrarov.

Marat Abrarov wrote:
It would be more accurate to say "on Windows asio::io_service::stop() does not cancel already queued (!) handlers". See example below.
Your are right, of course. I should have been more specific. And chaining handlers like this is certainly another way to achieve the desired effect, thanks! However, I'm still interested whether stop() should always cancel the queued handlers, i.e. if this is a bug (on windows). The io_service documentation says this regarding the use of a work object (http://alturl.com/98rvq): "To effect a shutdown, the application will then need to call the io_service object's stop() member function. This will cause the io_service run() call to return as soon as possible, abandoning unfinished operations and without permitting ready handlers to be dispatched. Alternatively, if the application requires that all operations and handlers be allowed to finish normally, the work object may be explicitly destroyed." So am I misreading this or does this say io_service::stop() has to cancel all queued handlers? Regards, Martin
participants (2)
-
Marat Abrarov
-
Martin Gernhard