c++boost-asiobusy-waiting

avoiding busy wait with boost::asio poll


I'm writing a service on linux that uses boost::asio::io_service with io_service::poll in a while loop. This is a busy wait loop, e.g. it wastes CPU cycles.

void Application::run()
{
    try
    {
        std::cout << "TcpServer starting..\n";
        _TcpServer.reset( new TcpServer(_io_service, boost::ref(_spState)) );

        // _io_service.run();

        while( ! _spState->QuitSignalled() )
        {
            _io_service.poll(); 
        }

        std::cerr << "quit signalled, TcpServer stopping.. :/" << std::endl;
    }
    catch(std::exception & e)
    {
        std::cout << e.what() << "\n";
    }
}

I use poll instead of run to check if another thread in the service has signalled service shutdown.

Is there a way of achieving this without using poll in a busy wait loop ?

The service uses async io on a single thread, and other threads do data processing.

I've added a sleep between iterations of the loop which seems to reduce the waste of cpu time, but I was hoping there might be a more efficient way?

void Application::run()
{
    using boost::this_thread::sleep_for;

    static const boost::chrono::milliseconds napMsecs( 50 );

    try
    {
        std::cout << "TcpServer starting..\n";
        _TcpServer.reset( new TcpServer(_io_service, boost::ref(_spState)) );

        // _io_service.run();

        while( ! _spState->QuitSignalled() )
        {
            _io_service.poll();
            boost::this_thread::sleep_for( napMsecs );
        }

        std::cerr << "quit signalled, TcpServer stopping.. :/" << std::endl;
    }
    catch(std::exception & e)
    {
        std::cout << e.what() << "\n";
    }
}

Solution

  • I'd say, simply take advantage of the fact that boost::asio::io_service is fully threadsafe by default, and do

    iosvc.run();
    

    And signal service shutdown on "another thread in the service" like you would:

    iosvc.stop();
    

    Remember to iosvc.reset() before you call {run,poll}[_one] again, as per the documentation.

    Of course you can also use other means to signal the actual logical workers to end, but then that's completely independent unrelated to Boost Asio