简体   繁体   中英

How to stop std thread safely?

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.

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).

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM