Reputation: 326
I have a class which has a std::thread member. I detach it in the constructor, and I wanted to be sure that, when the object is destroyed, the thread is stopped and destroyed too.
How can I achieve this?
Upvotes: 2
Views: 136
Reputation: 4473
Let's see through an example how can an std::thread
be handled to be ensured that will be stopped and destroyed when the enclosure object is destroyed:
#include <mutex>
#include <condition_variable>
#include <thread>
#include <atomic>
#include <cstdlib>
#include <ctime>
#include <iostream>
class ThreadTester {
public:
ThreadTester() : isAlive(true), randomNumber(0) {
// Start the background operation.
myThread = std::thread(&ThreadTester::createRandom, this);
}
virtual ~ThreadTester() {
{
// Stop the running thread.
std::unique_lock<std::recursive_mutex> lk(mutex);
isAlive = false;
condition.notify_all();
}
// Join the stopped thread.
if(myThread.joinable())
myThread.join();
}
int getRandom() const {
return randomNumber;
}
private:
void createRandom() {
std::unique_lock<std::recursive_mutex> lk(mutex);
// Do something with 250ms intervall while the isAlive is true.
while(isAlive) {
condition.wait_for(lk, std::chrono::milliseconds(250));
if(isAlive) {
randomNumber = rand() % 100;
}
}
}
std::recursive_mutex mutex;
std::condition_variable_any condition;
bool isAlive;
std::thread myThread;
std::atomic_int randomNumber;
};
int main() {
srand(time(NULL));
const ThreadTester tester;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Test: " << tester.getRandom() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Test: " << tester.getRandom() << std::endl;
return 0;
}
I my example I hold the thread until it become stopped to make it sure it can be destroyed safely. I don't think so that detaching a thread is a good practice.
Upvotes: 0
Reputation: 385108
I have a class which has a std::thread member
Okay!
I detach it in the constructor
Alright. That means you don't want the class to manage the thread any more. No problem.
and I wanted to be sure that when the object is destroyed, the thread is stopped and destroyed too
Oh, so… huh. You do want the class to manage the thread? Interesting.
Don't detach the thread.
It is literally the anti-what-you-want-to-do and single-handedly responsible for your problem.
Upvotes: 2
Reputation: 180414
Once you detach
a std::thread
you no longer have control of that thread. the std::thread
object releases it and all the resources of the thread will not be freed until the thread finishes or the process(program) exits. If you want to stop a detached thread you would have to send a signal to it with some sort of flag(std::atomic<bool>
comes to mind) or std::condition_variable
to have it end itself.
If you want the thread to live with the class and then once the class is destroyed then terminate the thread then you do not want to call detach
. Instead what you would do is call join()
in the destructor which stops the destructor from running until the thread finishes. Once it does then the destructor will continue and you will know that the thread has ended and everything has been cleaned up.
Upvotes: 2