Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread joining issue

I was reading some manuals about threads and I've come to a thought that the code they show is not safe:

std::cout << "starting first helper...\n";
std::thread helper1(foo);

std::cout << "starting second helper...\n";
std::thread helper2(bar);

std::cout << "waiting for helpers to finish..." << std::endl;
helper1.join();   // #1 NOT SAFE
helper2.join();   // #2 NOT SAFE

I believe this code is not absolutely safe. If I am not mistaking there is no guarantee that helper1 and helper2 are already in joinable state when control reaches lines marked as #1 and #2. Threads could still be not launched and have no ids at this point. Which will cause an uncaught exception being thrown from std::thread::join()

I think the following code fixes the problem. Am I right?

std::cout << "starting first helper...\n";
std::thread helper1(foo);

std::cout << "starting second helper...\n";
std::thread helper2(bar);

std::cout << "waiting for helpers to finish..." << std::endl;
while ( helper1.joinable() == false ) { }
helper1.join();   // #1 SAFE
while ( helper2.joinable() == false ) { }
helper2.join();   // #2 SAFE
like image 885
Kolyunya Avatar asked Dec 20 '22 21:12

Kolyunya


2 Answers

A std::thread is joinable if it contains a thread state that has not been joined or detatched.

A std::thread gains a thread state by being non default constructed, or having one moveed into it from another std::thread. It loses it when moveed from.

There is no delay in gaining the thread state after construction completes. And it does not go away when the threaded function finishes. So there is not that problem.

There is the problem that if code throws above, you will fail to join or detatch, leading to bad news at program shutdown. Always wrap std::thread in a RAII wrapper to avoid that, or just use std::async that returns void and wrap the resulting std::future similarly (because the standard says it blocks in the dtor, but microsofts implementation does not, so you cannot trust if it will or not).

like image 184
Yakk - Adam Nevraumont Avatar answered Jan 04 '23 08:01

Yakk - Adam Nevraumont


You are perceiving threads in an overly complicated way. join is there to safely join a thread. Just use:

std::thread my_thread(my_main);
my_thread.join();
like image 42
Paul Evans Avatar answered Jan 04 '23 10:01

Paul Evans