简体   繁体   中英

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM