Reputation: 12371
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?
Upvotes: 3
Views: 1640
Reputation: 62553
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 detach
ing 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::thread
s 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.
Upvotes: 5
Reputation: 218700
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";
}
Upvotes: 1
Reputation: 106068
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.
Upvotes: 0