In contrast to std::thread the joinable thread std::jthread has the following properties:
- Automatically joining
The destructor of std::jthread automatically joins the connected thread (a not explicitly joined std::thread will terminate the program within its destructor) - Cooperative interruption
The thread function of a std::jthread can have a stop_token as parameter, thus allowing to stop the execution via jthread::request_stop(). For a successful stop the thread function has to check for a pending stop request and cancel its execution.
Example:
#include <chrono>
#include <thread>
void TestJThread()
{
// Start thread function which optionally can get a stop_token
std::jthread myThread([](std::stop_token stoken) {
for (int i = 0; i < 10; ++i)
{
if (stoken.stop_requested()) return; // cancel execution
std::this_thread::sleep_for(0.5s);
std::cout << "myThread: i=" << i << "\n";
}
});
std::cout << "main: thread started" << "\n";
std::this_thread::sleep_for(2s);
myThread.request_stop();
// myThread destructor automatically joins thread and waits for end of execution!
}
Output:
main: thread started
myThread: i=0
myThread: i=1
myThread: i=2
myThread: i=3
Ask whether stop is possible
It is possible to ask whether a thread currently can be stopped or not via jthread::get_stop_token().stop_possible().
By temporarily exchanging a regular stop_token with a default constructed stop_token the thread function can signal that a stop is currently not possible (and a call of jthread::request_stop() will be ignored):
std::jthread myThread([](std::stop_token stoken) {
...
std::stop_token stopNotPossible;
std::swap(stoken, stopNotPossible);
// do something not interruptable
// here a call of jthread::get_stop_token().stop_possible() will return false
...
std::swap(stoken, stopNotPossible);
// Changed back to interruptable state, stop_possible() will return true
...
});
Stop waiting on condition variables
A condition variable can be used to wait until a thread has prepared some data. When this thread is stopped, the data will never be prepared. To avoid endless waiting on the condition variable there is the possibility to return from waiting when the thread is stopped by using special overloads of the wait functions:
std::mutex myMutex;
std::condition_variable_any myCondVar;
bool myDataReady;
std::jthread myThread([](std::stop_token stoken) {
...
// wait for data availability or a stop signal
std::unique_lock<std::mutex> lock(myMutex);
bool ret = myCondVar.wait(lock, stoken, []{return myDataReady;});
if (ret) // data are ready
{
// Process data
...
}
else // execution was stopped
{
...
}
});