Checking whether std::thread member of my class is stopped - c++

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?

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.

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.

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.

Related

When std::thread is destructed and what happen to the shared_ptr if the pointer point to it?

When I create a std::thread instance, when will it be destructed? Is the time when the thread finish its task then it is destructed or it works as a normal object which will be destructed when it will not be used anymore?
//a fake function for std::thread
void func();
void main()
{
auto threadPtr = std::make_shared<std::thread>(func)
threadPtr->join();
// is thread object which threadPtr point destructed in here ?
//... other stuffs ....
}
Is thread object destructed after threadPtr->join()?
Is thread object destructed after threadPtr->join()?
No. join() ends the thread of execution that the std::thread object represents, it does not destroy the std::thread object.
When I create a std::thread instance, when will it be destructed?
It will be destroyed when threadPtr goes out of scope since it is an automatic object(it has automatic storage duration). The std::shared_ptr destructor will call the std::thread destructor, and then it will free the memory it obtained.
The underlying operating system thread may have terminated but that isn't the same as the C++ std::thread object being destructed.
Execute the following:
#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>
std::mutex cout_mutex;
std::atomic<bool> waiter{true};
void func(){
{
std::lock_guard<std::mutex> guard(cout_mutex);
std::cout << "funky\n";
}
while(waiter);//cheap spin waiting...
}
int main() {
auto threadPtr = std::make_shared<std::thread>(func);
{
std::lock_guard<std::mutex> guard(cout_mutex);
std::cout << "an active thread id: "<<threadPtr->get_id()<<'\n';
}
waiter=false;
threadPtr->join();
std::cout << "terminated thread id: "<< threadPtr->get_id()<<'\n';
return 0;
}
The output varies but possible output here is:
an active thread id: 47441922455296
funky
terminated thread id: thread::id of a non-executing thread
The object contained in threadptr remains valid until destructed but may be referencing a terminated thread.
std::thread is typically an implementation of a wrapper class (or the proxy design pattern). It contains a (possibly empty) reference to what is normally an operating system thread object. When the wrapped thread ends the reference may be made empty.

std::thread thread spun off in object, when does it terminate?

If I spin off an std::thread in the constructor of Bar when does it stop running? Is it guaranteed to stop when the Bar instance gets destructed?
class Bar {
public:
Bar() : thread(&Bar:foo, this) {
}
...
void foo() {
while (true) {//do stuff//}
}
private:
std::thread thread;
};
EDIT: How do I correctly terminate the std::thread in the destructor?
If I spin off an std::thread in the constructor of Bar when does it
stop running?
the thread will run as long as it executing the callable you provided it, or the program terminates.
Is it guaranteed to stop when the Bar instance gets destructed?
No. In order to guarantee that, call std::thread::join in Bar destructor.
Actually, if you hadn't call thread::join or thread::detach prior to Bar::~Bar, than your application will be terminated by calling automatically to std::terminate. so you must call either join (preferable) or detach (less recommended).
you also want to call therad::join on the object destructor because the spawned thread relies on the object to be alive, if the object is destructed while your thread is working on that object - you are using destructed object and you will have undefined behavior in your code.
Short answer: Yes and no. Yes, the thread ends, but not by the usual way (killing the thread), but by the main thread exiting due to a std::terminate call.
Long answer: The thread can only be safely destructed when the underlying function (thread) has finished executing. This can be done in 2 ways
calling join(), which waits for the thread to finish (in your case, never)
calling detach(), which detaches the thread from the main thread (in this case, the thread will end when the main thread closes - when the program terminates).
If the destructor is called if all of those conditions don't apply, then std::terminate is called:
it was default-constructed
it was moved from
join() has been called
detach() has been called
The C++ threading facilities do not include a built-in mechanism for terminating a thread. Instead, you must decide for yourself: a) a mechanism to signal the thread that it should terminate, b) that you do not care about the thread being aborted mid-operation when the process terminates and the OS simply ceases to run it's threads any more.
The std::thread object is not the thread itself but an opaque object containing a descriptor/handle for the thread, so in theory it could be destroyed without affecting the thread, and there were arguments for and against automatic termination of the thread itself. Instead, as a compromise, it was made so that destroying a std::thread object while the thread remained running and attached would cause the application to terminate.
As a result, In it's destructor there is some code like this:
~thread() {
if (this->joinable())
std::terminate(...);
}
Here's an example of using a simple atomic variable and checking for it in the thread. For more complex cases you may need to consider a condition_variable or other more sophisticated signaling mechanism.
#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>
class S {
std::atomic<bool> running_;
std::thread thread_;
public:
S() : running_(true), thread_([this] () { work(); }) {}
void cancel() { running_ = false; }
~S() {
if ( running_ )
cancel();
if ( thread_.joinable() )
thread_.join();
}
private:
void work() {
while ( running_ ) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "tick ...\n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "... tock\n";
}
std::cout << "!running\n";
}
};
int main()
{
std::cout << "main()\n";
{
S s;
std::this_thread::sleep_for(std::chrono::milliseconds(2750));
std::cout << "end of main, should see a tock and then end\n";
}
std::cout << "finished\n";
}
Live demo: http://coliru.stacked-crooked.com/a/3b179f0f9f8bc2e1

Is it ok to move assign std::thread object from the same thread

Is it ok to do the following?
#include <iostream>
#include <thread>
std::thread th;
void foo()
{
std::cout << __func__ << std::endl;
th = std::thread(foo);
}
int main()
{
th = std::thread(foo);
th.join();
}
gcc crashes -- http://coliru.stacked-crooked.com/a/3c926507ab0f8a5c.
I know that there's almost no need to do this but I want to know the answer just for academic purposes.
th = std::thread(foo);
You're not joining on your thread.
http://en.cppreference.com/w/cpp/thread/thread
destructs the thread object, underlying thread must be joined or detached
As stated in comments on another answer, assignment has the same requirements as destruction, since the previous thread object is lost.

C++ Thread access issue with class member variables

After using threads for a while, I got into a situation where I needed a thread to run forever until a a function (or any sort of event) was called. To do this I created a bool value to control a while loop inside the function that was executed by the thread, but I quickly noticed that external variables are not updated after a thread starts running, causing the thread to never stop when it was asked to.
Heres some simple code to represent the issue:
#include <cstdio>
#include <thread>
#include <chrono>
class A {
public:
A();
void startThread();
void endThread();
private:
void threadCall();
bool active;
};
int main() {
A threadThing;
threadThing.startThread();
printf("[M] Thread Created\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
threadThing.endThread();
printf("[M] Thread Killed\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
A::A() {
active = false;
}
void A::startThread() {
active = true;
std::thread AThread(&A::threadCall, *this);
AThread.detach();
}
void A::endThread() {
active = false;
}
void A::threadCall() {
printf("[T] Thread Started\n");
while (active) {
std::this_thread::sleep_for(std::chrono::seconds(2));
}
printf("[T] Thread Ended\n");
}
The expected result of this would be that the main function starts the thread, the thread says it started, then 4 seconds later the thread is killed and the thread says it ended, when in reality the thread never says it ends. Is there a way to let the thread access the 'active' variable, or is my approach to this problem incorrect altogether? (Side note, I did try to figure this out on my own but only got stuff like local thread storage which seems like its only for storage inside of threads, not access to the outside but I could be wrong)
The problem is with the constructor of std::thread, it copies/moves by default.
std::thread AThread(&A::threadCall, *this);
this copies the object into the new thread, so checking the active variable in the new object has no effect.
you can remove the *
std::thread AThread(&A::threadCall, this);
you pass the object pointer into the new thread, it will call like the method like this(*this).threadCall().
Edit: as the comments say, this is not guarantee to be thread safe, you need to use std::atomic<bool> to be safe.
What you need to do is pass an A class pointer as an argument to your function that is your thread.
void A::startThread()
{
active = true;
std::thread AThread(threadCall, this);
AThread.detach();
}
void A::threadCall(A *aClass)
{
printf("[T] Thread Started\n");
while (aClass->active)
{
std::this_thread::sleep_for(std::chrono::seconds(2));
}
printf("[T] Thread Ended\n");
}

Why does thread.join fail when called in destructor of global variable

I reduced my problematic code to the following. I have a class C that runs a member function on its own thread. In the destructor of C I want to cleanly exit this thread. This works fine as long as c is defined within main (1), but not when it is a global variable (2). In the latter case, I see that the thread function returns but that the t.join() hangs.
#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
using namespace std;
class C
{
public:
C()
{
stop = false;
t = thread(&C::ThreadFunc, this);
}
~C()
{
stop = true;
cv.notify_all();
if (t.joinable())
{
cout << "joining" << endl;
t.join();
cout << "joined" << endl;
}
}
private:
void ThreadFunc()
{
while (true)
{
unique_lock<mutex> lock(m);
cv.wait(lock, [&]{return stop;});
cout << "returning" << endl;
return;
}
}
thread t;
mutex m;
condition_variable cv;
bool stop;
};
C c; // does *not* work (2)
int _tmain(int argc, _TCHAR* argv[])
{
C c; // does work (1)
return 0;
}
The reason I use a global variable is that it is actually part of a dll. When the destructor is triggered from DllMain on DLL_PROCESS_DETACH, the same problem occurs.
Is there an explanation and a solution to this problem?
It's a deadlock. You are holding a lock that t requires in order to terminate while you are waiting for t to terminate.
Say as part of t's detach process, it makes some calls into the DLL. How can the DLL sensibly handle a request when there is a thread (the thread that called join) that is partially attached to it? Once you start detaching, and until you finish detaching, the DLL is an inconsistent state and cannot sensibly handle thread attach and detach operations.
You really don't want to try to join a thread while your process is in a context you can't control.