Why can detached thread in C++11 execute even if the destructor has been called - c++

I just read the doc about std::thread.detach() in C++11.
Here is my test:
#include <iostream>
#include <thread>
#include <chrono>
static int counter = 0;
void func()
{
while (true) {
std::cout<<"running..."<<std::endl;
std::cout<<counter++<<std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
int main()
{
{
std::thread t(func);
t.detach();
} // t is released after this line
// t has died, so who is holding the resources of the detached thread???
std::cin.get();
return 0;
}
This code works as expected. So it seems that the thread can keep running even if its destructor has been invoked. Is this true?
If it's true, who on earth holds the resources of the thread after the object t is released? Is there some mechanism to hold the resources, for example, a hidden anonymous object?

In C++, std::thread does not manage the thread of execution itself. C++ does not have controls for managing the thread of execution at all.
std::thread manages the thread handle - the identifier of a thread (thread_t in Posix world, which was largely a model for std::thread). Such identifier is used to communicate (as in control) with the thread, but in C++, the only standard way of communication would be to join the thread (which is simply waiting for thread's completion) or detaching from it.
When std::thread destructor is called, the thread handle is also destructed, and no further controlling of the thread is possible. But the thread of execution itself remains and continues being managed by implementation (or, more precisely, operation system).
Please note, for non-detached threads std::threads destructors throws an exception if the thread has not been joined. This is simply a safeguard against developers accidentally loosing the thread handle when they didn't intend to.

You are correct that the thread keeps running if detached after the thread's destructor.
No one on earth hold the resources (unless you make arrangements for someone to). However when your application exits, the application shutdown process will end the thread.
One can still arrange to communicate with and "wait" for a detached thread. In essence, join() is a convenience API so that you don't have to do something like this:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
static int counter = 0;
std::atomic<bool> time_to_quit{false};
std::atomic<bool> has_quit{false};
void func()
{
while (!time_to_quit) {
std::cout<<"running..."<<std::endl;
std::cout<<counter++<<std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
has_quit = true;
}
int main()
{
{
std::thread t(func);
t.detach();
} // t is released after this line
using namespace std::chrono_literals;
std::this_thread::sleep_for(3s);
time_to_quit = true;
while (!has_quit)
;
std::cout << "orderly shutdown\n";
}

Threads of executions exist independently from the thread objects that you use to manage them in C++. When you detach a thread object, the thread of execution continues running, but the implementation (usually in combination with the Operating System) is responsible for it.

Related

C++ What possible ways can a detached thread signal it is terminating?

I had three initial ideas about this
Firstly some kind of counter? (Maybe using mutex?)
Some kind of semophore? (I don't know much about these) OR perhaps a promise/future combination
Some other kind of signal/slot mechanism, similar to that of the signal created by CTRL-C (SIGINT etc)
I'm working on some software which makes use of detached threads to do some work. Unfortunatly the threads don't clean up nicely, they just quit at the end of execution. This is fine for communication in one direction (ie; main() can quit first), but won't work the other way around - at the moment there is no way for main() to know when the threads have finished working and to exit gracefully.
To expand on those bullet points...
My initial idea was to have a protected region of variables - could be a counter or an array of flags, one for each thread, and to access these using a mutex. The mutex might not even be necessary if using one variable per detached thread to signal the end of the thread working, because main() will "poll" these variables, which is a read-only operation. Only the detached threads themselves need write access. If more than one detached thread uses the same counter/variable then a mutex would be required.
The next idea I had was to use a semophore (which is something I really know nothing about) or promise/future combinations, which I think would work as a possible option.
The final thought was some kind of signals mechanism, like possibly "stealing" a SIGxyz signal (like SIGINT) and using that to some how communicate the end of a thread execution. I'm not confident about this one however.
My question is really - how is this supposed to be done? What would the typical engineering solution to this problem be?
(Final thought: Using a file, or a pipe? Seems a bit complicated though?)
Perhaps I overlooked the question but I think you could use an atomic variable as a flag in order to notify the detached thread's termination.
Something like the following example:
#include <thread>
#include <iostream>
#include <atomic>
int main()
{
// Define a flag to notify detached thread's termination
std::atomic_bool term_flag;
// Define some function to run concurrently
auto func = [&term_flag](){
std::this_thread::sleep_for(std::chrono::seconds(2));
term_flag = true;
};
// Run and detach the thread
term_flag = false;
std::thread t(func);
t.detach();
// Wait until detached thread termination
while(!term_flag)
std::this_thread::yield();
std::cout << "Detached Thread has terminated properly" << std::endl;
return 0;
}
Output:
Detached Thread has terminated properly
EDIT:
As Hans Passant mentioned, you could also use a condition variable associated with a mutex to do it.
This would be a better solution (but a bit less readable in my humble opinion) since we have more control over how much to wait.
The basic example above could then be rewritten as:
#include <thread>
#include <iostream>
#include <mutex>
#include <condition_variable>
int main()
{
// Define the mutex and the condition variable to notify the detached thread's termination
std::mutex m;
std::condition_variable cv;
// Define some function to run concurrently
auto func = [&cv](){
std::this_thread::sleep_for(std::chrono::seconds(2));
cv.notify_one();
};
// Run and detach the thread
std::thread t(func);
t.detach();
// Wait until detached thread termination
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk);
}
std::cout << "Detached Thread has terminated properly" << std::endl;
return 0;
}

Std thread detach

Having this simple example:
#include <iostream> // std::cout
#include <thread> // std::thread, std::this_thread::sleep_for
#include <chrono> // std::chrono::seconds
void new_thread(int n) {
std::this_thread::sleep_for(std::chrono::seconds(n));
std::cout << "New thread - exiting!\n";
}
int main() {
std::thread (new_thread, 5).detach();
std::cout << "Main thread - exiting!\n";
return 0;
}
Is it possible for the new_thread not to be automatically terminated by the main thread and to do it's work - outputs New thread - exiting! after 5 secs?
I'm NOT mean the case of join when the main thread waits for a child, but for the main thread to detach the spawned thread and terminates leaving the new thread doing it's work?
Calling detach on a thread means that you don't care about what the thread does any more. If that thread doesn't finish executing before the program ends (when main returns), then you won't see its effects.
However, if the calling thread is around long enough for the detached thread to complete, then you will see the output. Demo.
[basic.start.main]/5 A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling std::exit with the return value as the argument. If control flows off the end of the compound-statement of main, the effect is equivalent to a return with operand 0.
[support.start.term]/9
[[noreturn]] void exit(int status);
Effects:
...
Finally, control is returned to the host environment.
You seem to expect that when main returns, the program waits for all threads to finish - in effect, implicitly joins all detached threads. That's not what happens - instead, the program terminates, and the operating system cleans up resources allocated to the process (including any threads).
detach separates your thread from the main thread. You want to use join()
Separates the thread of execution from the thread object, allowing
execution to continue independently. Any allocated resources will be
freed once the thread exits.
After calling detach *this no longer owns any thread.
From ref

Relation between running Thread and the thread object

While learning basic thread management, I found difficulty in understanding these lines (in bold) from a book.
Once you’ve started your thread, you need to explicitly decide whether
to wait for it to finish (by joining with it—see section 2.1.2) or
leave it to run on its own (by detaching it—see section 2.1.3). If you
don’t decide before the std::thread object is destroyed, then your
program is terminated (the std::thread destructor calls
std::terminate()). It’s therefore imperative that you ensure that the
thread is correctly joined or detached, even in the presence of
exceptions. See section 2.1.3 for a technique to handle this scenario.
Note that you only have to make this decision before the std::thread
object is destroyed—the thread itself may well have finished long
before you join with it or detach it, and if you detach it, then the
thread may continue running long after the std::thread object is
destroyed.
When does a thread run even after the thread object is destroyed? Anyone have sample code or any reference?
What this means is that the lifetime of the thread is not associated with the lifetime of the thread object.
So the following code:
#include <thread>
#include <iostream>
int main() {
{ //scope the thread object
std::thread thr = std::thread([]() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Thread stuff\r\n";
});
thr.detach();
} //thr is destroyed here
std::cout << "thr destroyed, start sleep\r\n";
std::this_thread::sleep_for(std::chrono::seconds(10));
std::cout << "sleep over\r\n";
}
Will output:
thr destroyed, start sleep
Thread stuff
sleep over

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

When should I use std::thread::detach?

Sometime I have to use std::thread to speed up my application. I also know join() waits until a thread completes. This is easy to understand, but what's the difference between calling detach() and not calling it?
I thought that without detach(), the thread's method will work using a thread independently.
Not detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Calling with detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}
In the destructor of std::thread, std::terminate is called if:
the thread was not joined (with t.join())
and was not detached either (with t.detach())
Thus, you should always either join or detach a thread before the flows of execution reaches the destructor.
When a program terminates (ie, main returns) the remaining detached threads executing in the background are not waited upon; instead their execution is suspended and their thread-local objects destructed.
Crucially, this means that the stack of those threads is not unwound and thus some destructors are not executed. Depending on the actions those destructors were supposed to undertake, this might be as bad a situation as if the program had crashed or had been killed. Hopefully the OS will release the locks on files, etc... but you could have corrupted shared memory, half-written files, and the like.
So, should you use join or detach ?
Use join
Unless you need to have more flexibility AND are willing to provide a synchronization mechanism to wait for the thread completion on your own, in which case you may use detach
You should call detach if you're not going to wait for the thread to complete with join but the thread instead will just keep running until it's done and then terminate without having the spawner thread waiting for it specifically; e.g.
std::thread(func).detach(); // It's done when it's done
detach basically will release the resources needed to be able to implement join.
It is a fatal error if a thread object ends its life and neither join nor detach has been called; in this case terminate is invoked.
This answer is aimed at answering question in the title, rather than explaining the difference between join and detach. So when should std::thread::detach be used?
In properly maintained C++ code std::thread::detach should not be used at all. Programmer must ensure that all the created threads gracefully exit releasing all the acquired resources and performing other necessary cleanup actions. This implies that giving up ownership of threads by invoking detach is not an option and therefore join should be used in all scenarios.
However some applications rely on old and often not well designed and supported APIs that may contain indefinitely blocking functions. Moving invocations of these functions into a dedicated thread to avoid blocking other stuff is a common practice. There is no way to make such a thread to exit gracefully so use of join will just lead to primary thread blocking. That's a situation when using detach would be a less evil alternative to, say, allocating thread object with dynamic storage duration and then purposely leaking it.
#include <LegacyApi.hpp>
#include <thread>
auto LegacyApiThreadEntry(void)
{
auto result{NastyBlockingFunction()};
// do something...
}
int main()
{
::std::thread legacy_api_thread{&LegacyApiThreadEntry};
// do something...
legacy_api_thread.detach();
return 0;
}
When you detach thread it means that you don't have to join() it before exiting main().
Thread library will actually wait for each such thread below-main, but you should not care about it.
detach() is mainly useful when you have a task that has to be done in background, but you don't care about its execution. This is usually a case for some libraries. They may silently create a background worker thread and detach it so you won't even notice it.
According to cppreference.com:
Separates the thread of execution from the thread object, allowing
execution to continue independently. Any allocated resources will be
freed once the thread exits.
After calling detach *this no longer owns any thread.
For example:
std::thread my_thread([&](){XXXX});
my_thread.detach();
Notice the local variable: my_thread, while the lifetime of my_thread is over, the destructor of std::thread will be called, and std::terminate() will be called within the destructor.
But if you use detach(), you should not use my_thread anymore, even if the lifetime of my_thread is over, nothing will happen to the new thread.
Maybe it is good idea to iterate what was mentioned in one of the answers above: When the main function is finished and main thread is closing, all spawn threads either will be terminated or suspended. So, if you are relying on detach to have a background thread continue running after the main thread is shutdown, you are in for a surprise. To see the effect try the following. If you uncomment the last sleep call, then the output file will be created and written to fine. Otherwise not:
#include <mutex>
#include <thread>
#include <iostream>
#include <fstream>
#include <array>
#include <chrono>
using Ms = std::chrono::milliseconds;
std::once_flag oflag;
std::mutex mx;
std::mutex printMx;
int globalCount{};
std::ofstream *logfile;
void do_one_time_task() {
//printMx.lock();
//std::cout<<"I am in thread with thread id: "<< std::this_thread::get_id() << std::endl;
//printMx.unlock();
std::call_once(oflag, [&]() {
// std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
// std::cout<<"Initialized globalCount to 3\n";
globalCount = 3;
logfile = new std::ofstream("testlog.txt");
//logfile.open("testlog.txt");
});
std::this_thread::sleep_for(Ms(100));
// some more here
for(int i=0; i<10; ++i){
mx.lock();
++globalCount;
*logfile << "thread: "<< std::this_thread::get_id() <<", globalCount = " << globalCount << std::endl;
std::this_thread::sleep_for(Ms(50));
mx.unlock();
std::this_thread::sleep_for(Ms(2));
}
std::this_thread::sleep_for(Ms(2000));
std::call_once(oflag, [&]() {
//std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
//std::cout << "closing logfile:\n";
logfile->close();
});
}
int main()
{
std::array<std::thread, 5> thArray;
for (int i = 0; i < 5; ++i)
thArray[i] = std::thread(do_one_time_task);
for (int i = 0; i < 5; ++i)
thArray[i].detach();
//std::this_thread::sleep_for(Ms(5000));
std::cout << "Main: globalCount = " << globalCount << std::endl;
return 0;
}