Say I have a worker thread tWorker
, which is initialized when Boss
is constructed and tells it to do work()
, until bRetired
is true. An std::mutex
, mtx
, locks some data (vFiles
) so that tWorker
owns it when he's working on it.
How do I make tWorker
"commit suicide" once bRetired
becomes true
? How would the mutex
be destroyed when the thread stops execution?
I've read that std::thread
objects cannot be interrupted in any way. Does letting the thread do nothing (or calling std::this_thread::yield()
) provide the same effect as killing the thread?
class Boss {
private:
std::thread tWorker;
std::mutex mtx;
bool bRetired;
std::vector< std::string > vFiles;
void work() {
while ( bRetired == false ) {
// Do your job!
mtx.lock();
// ... Do something about vFiles ...
mtx.unlock();
}
// tWorker has retired, commit suicide
// ** How? **
// Does this suffice if I want to "kill" the thread?
std::this_thread::yield();
}
public:
Boss() {
bRetired = false;
tWorker = std::thread( &Boss::work, this );
// Have worker do its job independently
// **Bonus Question** : Should this be tWorker.join() or tWorker.detach()?
tWorker.detach();
}
retire() {
bRetired = true;
}
}
Notes
The call to std::thread::yield()
is unrequired and does not kill the calling thread:
Provides a hint to the implementation to reschedule the execution of threads, allowing other threads to run.
Just exit the function to exit the thread.
Note that the use of bRetired
is incorrect as two threads can be accessing the same memory location and one of those threads is modifying it: this is undefined behaviour. Also, the change made in the function retire()
, a different thread, will not be seen by the thread executing run()
: use atomic<bool>
for atomicity and visibility.
If join()
was used within the constructor the constructor would not return until the thread exited, which would never happen as it would be impossible to call retire()
because the object would not be available (as the constructor would not have returned). If it is required to synchronize with the exiting of the thread then do not detach()
but join()
in the retire()
function:
void retire() {
bRetired = true;
tWorker.join();
}
Use RAII for acquiring mutex
es (std::lock_guard
for example) to ensure it always released. The mutex
will be destroyed when it goes out of scope, in this case when its containing class is destructed.