Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the reason for a joinable std::thread not join automatically?

Sometimes it would be useful if a joinable std::thread had the hability to execute thread::join() on its destructor. See the examples below.

Example 1 (error): The object std::thread has been destroyed after the throw of the exception. Once the the flow exits the scope, the destructor is called BEFORE the join happens. It makes STL show an error message of 'abort'.

int main( int argc, const char * argv[] )
{
    try
    {
        thread t( [] ()
        {
            this_thread::sleep_for( chrono::seconds( 1 ) );
            cout << "thread done" << endl;
        } );

        throw exception( "some exception" );

        t.join();
    }
    catch ( const exception & )
    {
        cout << "exception caught!" << endl;
    }

    cout << "main done" << endl;

    return 0;
}

Example 2 (correct way): The object t is created before my try-catch block and the join() is put on both try and catch blocks. So it guarantees that the join() happens.

int main( int argc, const char * argv[] )
{
    thread t;

    try
    {
        t = thread( [] ()
        {
            this_thread::sleep_for( chrono::seconds( 1 ) );
            cout << "thread done" << endl;
        } );

        throw exception( "some exception" );

        t.join( );
    }
    catch ( const exception & )
    {
        t.join();
        cout << "exception caught!" << endl;
    }

    cout << "main done" << endl;

    return 0;
}

...AND THE QUESTION IS: What is the reason for a joinable std::thread not join automatically on its destructor?

It would be much easier if it happened automatically. The way it's done today requires one must be careful when using threads inside try-catch blocks, for example... but I am sure someone THOUGHT when designed std::thread this way. So there must be a reason for that... what is that reason?

PS: I know we can envolve std::thread in a class and put the join() on the destructor of this new class... so it becomes automatic. But this is not the point. My question is really about std::thread itself.

like image 348
Wagner Patriota Avatar asked Jan 24 '14 13:01

Wagner Patriota


People also ask

What happens when you don't join a thread?

Another scenario is spawning helper threads when processing tasks. If you don't join these threads, you might end up using more resources than there are concurrent tasks, making it harder to measure the load. To be clear, if you don't call join , the thread will complete at some point anyway, it won't leak or anything.

What does it mean for a thread to be joinable?

A thread object is said to be joinable if it identifies/represent an active thread of execution. A thread is not joinable if: It was default-constructed. If either of its member join or detach has been called. It has been moved elsewhere.

Does join destroy a thread C++?

When thread::join() returns, the OS thread of execution has completed and the C++ thread object can be destroyed.

Why do we need to join thread in C++?

The C++ thread join is used to blocks the threads until the first thread execution process is completed on which particular join() method is called to avoid the misconceptions or errors in the code.


1 Answers

The reason is simply so that you are forced to think about it. If a std::thread object is destroyed due to an exception escaping the scope then a join may cause a blocking wait during stack unwinding, which is often undesirable, and can lead to deadlock if the thread that is being waited for is in turn waiting for some action on the part of the thread doing the waiting.

By having the application terminate in this situation you as a programmer are forced to actively think about the conditions that would cause the object to be destroyed, and ensure that the thread is joined correctly.

like image 138
Anthony Williams Avatar answered Sep 22 '22 12:09

Anthony Williams