I'm developing a chat server and I have a question.
How to stop std::thread
safely?
it is very easy problem, like this.
thread t(&func);
t.join();
but, if func is has infinite loop, join is not working.
this is my source.
void CServerSocket::AcceptRun(boost::asio::io_service &iosrv)
{
while (true)
{
auto sock = std::make_shared<boost::asio::ip::tcp::socket>(iosrv);
m_Acceptor->accept(*sock);
m_SocketList.push_back(std::make_shared<CConnectionSocket>(this, sock));
}
}
and
CServerSocket::~CServerSocket()
{
CLogManager::WriteLog("Stopping Server...");
m_Acceptor->close();
m_Acceptor.reset();
// m_AcceptThread.detach(); This is right?
CLogManager::WriteLog("Server Stoped!");
}
I'm very wondering. Please help me. thank you.
You can pass a suitable context to your thread(s) which can contain a flag indicating whether it is time to stop. The flag could be a std::atomic<bool>
. Obviously, you' d also need to set up communication to not wait indefinitely for data so you have the chance to check the flag once in a while.
I'm fairly sure that accept
will exit cleanly, throwing an exception, when you close the acceptor. You should catch the exception so that the thread exits normally:
void CServerSocket::AcceptRun(boost::asio::io_service &iosrv)
try {
// your loop here, unchanged
} catch (std::exception const & ex) {
// perhaps log the message, ex.what()
}
and then join the thread after closing the acceptor, but before destroying it:
CServerSocket::~CServerSocket()
{
CLogManager::WriteLog("Stopping Server...");
m_Acceptor->close();
m_AcceptThread.join();
CLogManager::WriteLog("Server Stopped!");
// No need to do anything else with m_Acceptor, assuming it's a smart pointer
}
Personally, I'd use asynchronous operations unless there were a compelling reason to use multiple threads. A single thread is much easier to deal with.
How to stop std::thread safely?
Stopping the thread safely means that you tell the thread function to stop processing (through a mechanism that is outside std::thread
), then wait for the thread to stop.
The response from @DietmarKuhl tells you how to do this. Regarding the acccept being blocking, you must set an option on the socket/acceptor to expire on a timeout. When the accept call returns, you either break the loop (if your loop condition is false) or you call accept
again, with a new timeout.
Your timeout value will be a compromise: a small timeout will be more computationally intensive (keep the CPU busy) while giving you a very responsive thread function (one that doesn't block much when you stop the thread).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With