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
You could call std::terminate() from any thread and the thread you're referring to will forcefully end. You could arrange for ~thread() to be executed on the object of the target thread, without a intervening join() nor detach() on that object.
You can pause a thread by making it wait on a std::mutex .
A thread automatically terminates when it returns from its entry-point routine. A thread can also explicitly terminate itself or terminate any other thread in the process, using a mechanism called cancelation.
thread::detachSeparates the thread of execution from the thread object, allowing execution to continue independently. Any allocated resources will be freed once the thread exits.
How do I make tWorker "commit suicide" once bRetired becomes true?
You let the control flow exit the thread function. That std::this_thread::yield()
call in unnecessary.
How would the mutex be destroyed when the thread stops execution?
That mutex is a member of Boss
class. It gets destroyed in the destructor of Boss
when the object is getting destroyed.
I've read that std::thread objects cannot be interrupted in any way.
C++ API does not provide means to terminate an arbitrary thread. There has to be a way to tell a thread to terminate and then wait till it does, as you intend to do.
Does letting the thread do nothing (or calling std::this_thread::yield()) provide the same effect as killing the thread?
No.
There is a race condition on bRetired
variable though. It either needs to be std::atomic<bool>
or it should only be read and modified only when that mutex is locked.
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.
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