-2

As per my understanding it is fine to assign the thread object and call join function in C++ 11. eg as below :

#include <iostream>
#include <thread>
using namespace std;

void func()
{
    int a = 10;
    while (a == 10)
    {
        cout << "Calling func()" << endl;
    }
}

int main()
{
    thread t;
    t = std::thread(func);
    if (true == t.joinable())
    {
        t.join();
    }
    return 0;
}

But in an example code in my project's main() looking as below, I assign the head object after the join and I am surprised to see it works. Can someone explain me why it is working?

Code snip as below:

int main()
{
    thread t;
    if (true == t.joinable())
    {
        t.join();
    }
    t = std::thread(func);
    return 0;
}
5
  • func never return, so in the first case t.join() will get stuck forever. In the second case the join will never be called because at that point t.joinable() will be false. You can see all this in a debugger. Commented Jun 15 at 14:24
  • 1
    Have you tried the second code? It does not run as same as the first one, it's terminated. Commented Jun 15 at 14:31
  • "I assign the head object after the join and I am surprised to see it works" - It would work if that had been what your second snippet had done. There is however no join() called in the second snippet. Commented Jun 15 at 15:17
  • Yoda conditionals you do not need. The return value of joinable, assigned it cannot be. godbolt.org/z/hf18Gh7EE you should see if proof you require. Simpler you should get. Easier to read, if (t.joinable()) is. Commented Jun 15 at 18:13
  • " Can someone explain me why it is working?" Can you explain why you think this code should fail? Commented Jun 16 at 17:40

1 Answer 1

4

Why does it (seem to) work?

In your second example, there is no thread associated with the std::thread object t. As a result, t.joinable() is false when it is called, and no join is made. But you then move assign a thread to t and return from main(). As t is a local object, it's destructor is called:

If *this has an associated thread (joinable() == true), std::terminate() is called.

So terminate is called, but this looks pretty much as a normal situation since you do not expect anything else to happen afterwards in your snippet.

But why doesn't it work as you think?

If you want to understand the real problem of your second code snippet, I suggest rather to move all the code of main to a separate function, like:

int my_strange_test()
{
    thread t;
    if (true == t.joinable())
    {
        t.join();
    }
    t = std::thread(func);
    return 0;
}

int main() 
{
    cout << "Launch my test" << endl;
    my_strange_test(); 
    cout << "My test successfully finished" << endl;     
}

Here you'll see that the second message is never reached because of the abrupt termination (online demo).

How to get it right?

If you replace the testing function with your first snippet, it will work as expected. Ok, as you have an infinite loop, the thread will never finish what it does, so the join will wait forever. But just put an upper limit to the number of iterations and it'll be fine, online demo).

Alternatively, you may want the main thread to control when to finish the loop. You may then go for something like:

void func(atomic<bool>& on_off)
{
    while (on_off)
    {
        cout << "Calling func()" << endl;
    }
}

int my_strange_test()
{
    thread t;
    atomic<bool> run{true};
    t = std::thread(func, std::ref(run));  // tricky ! 
    this_thread::sleep_for(10ms);    // do something else
    if (true == t.joinable())
    {
        run = false;                 // tell thread to finish iterations
        t.join();                    // and wait that it returns
    }
    return 0;
}

Online demo

Sign up to request clarification or add additional context in comments.

2 Comments

@ user3772439, Christophe said, "...there is no thread associated with the std::thread object..." Note! "thread" and std::thread mean two different things. "Thread" refers to an object in the operating system that is responsible for executing your code, while std::thread refers to a C++ class whose methods provide means to create, destroy, and control operating system thread objects. A default constructed std::thread value is a "dummy" value that is not associated with any operating system thread—a place-holder value that can fill the t variable until a real thread can be created.
hi all , thanks for the response, issue got sorted in my exiting project i noticed that in the destructor, actually while trying to leave the main join function will be called.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.