Search code examples
c++stdthread

When thread's destructor is being called?


I came across an example of basic std::thread usage from "The C++ programming language" by Bjarne Stroustrup, and it confuses me. Here is the example:

void run(int i, int n) // warning: really poor code
{
    thread t1 {f};
    thread t2;
    vector<Foo> v;
    // ...
    if (i<n)
    {
        thread t3 {g};
        // ...
        t2 = move(t3); // move t3 to outer scope
    }
    v[i] = Foo{}; // might throw
    // ...
    t1.join();
    t2.join();
}

As Stroustrup writes:

we may never reach the two join()s at the end. In that case, the destructor for t1 will terminate the program.

But, in which case is t1's destructor called? The t1 thread is not going out of its scope. There is no explicit delete call, either.

I tried to run this code with appropriate changes, but still I couldn't find how t1's destructor is being called.


Solution

  • But, in which case is t1's destructor called? The t1 thread is not going out of its scope. There is no explicit delete call, either.

    The code specifically says that the line v[i] = Foo{}; may throw an exception. If that happens, control never reaches the line t1.join(); afterwards in the same block scope, but all local variables of the scope, including t1, are still destroyed and their destructors called.

    When the destructor of std::thread is called while the thread is neither joined nor detached, then the destructor will call std::terminate which terminates the whole program by default, via a call to std::abort.

    More generally, the code is broken unless you can be sure that nothing before the .join calls will throw an exception. If you can't be sure of that, then you must wrap it in try { /*...*/ } catch(...) { t1.join(); throw; }. Technically, you need to do the same for t2 separately as well, since t1.join() is also allowed to throw, although that might be a situation in which your program will have major problems to continue execution anyway.

    With C++20, you can use std::jthread to avoid such problems.