Yves
Yves

Reputation: 12371

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

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

Answers (3)

SergeyA
SergeyA

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 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.

Upvotes: 5

Howard Hinnant
Howard Hinnant

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

Tony Delroy
Tony Delroy

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

Related Questions