Derek81
Derek81

Reputation: 162

Waiting for a thread to finish and future

Having such simple code:

void func(std::promise<int>* p) {
    int a = 10, b = 5;
    int result = a + b;
    std::cout << "From inside the Thread...." << std::endl;
    p->set_value(result);
}

int FP_main() {
    std::promise<int> p;
    std::future<int> f = p.get_future();
    std::thread th(func, &p);
    int ret = f.get();
    std::cout << "returned val: " << ret << std::endl;

    th.join();
    return 0;
}

Why do we need the join function call if there is get call just 2 lines above? Isn't the get function waiting for a thread to finish?

Upvotes: 4

Views: 1097

Answers (2)

jfMR
jfMR

Reputation: 24738

Why do we need the join function call if there is get call just 2 lines above?

Destroying a joinable std::thread object results in std::terminate() being called. This is regardless of whether or not its associated thread is done. So, the call to get() on the future is irrelevant when it comes to having to call join() on a joinable std::thread object before it is destroyed.

If you don't want to have to call join(), then you could just call detach() on the std::thread somewhere before its destruction. This way, the thread won't be joinable at the moment of destruction.

Upvotes: 1

quetzalcoatl
quetzalcoatl

Reputation: 33506

Because the thread is not the promise.
Promise is finished, but thread is not.

    p->set_value(result);
    // ...
    // HERE
    // ...
}

That are the last lines of func. The thread will now do its cleanups, will call destructors, etc. All while the promise is finished. Of couse, in 'HERE' the thread may a ton of other work - you can write a 1-hour long task in HERE to keep the thread alive and it will have nothing to do with the promise.

That's probably all clear already.

The last interesting bit is here:

int FP_main() {
    //...
    std::thread th(func, &p);
    //...

    th.join();
    return 0;
}

The 'th' is a local variable. When the main() returns, the destructor of th will be invoked. And that destructor throws an exception when the thread in question is not finished and not join'ed.

If the thread were busy after setting the value of the promise (i.e. doing destructors, or doing some 1-hour-long job), the std::thread's destructor invoked by } after return 0; would throw and crash the program. Hence, you need to join.

Upvotes: 4

Related Questions