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