1
votes

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";
    }
}
1

1 Answers

2
votes

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