Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should you use std::thread::joinable?

It is stated on the site cppreference with respect to std::thread::joinable :

Checks if the thread object identifies an active thread of execution. Specifically, returns true if get_id() != std::thread::id(). So a default constructed thread is not joinable. A thread that has finished executing code, but has not yet been joined is still considered an active thread of execution and is therefore joinable.

What follows on the std::thread::join documentation:

Error Conditions

resource_deadlock_would_occur if this->get_id() == std::this_thread::get_id() (deadlock detected)

Is the only purpose of this method to detect such a situation? We currently and brazenly only call thread->join without a joinable wrapper, what is the danger of such an approach?

like image 240
Ben Crowhurst Avatar asked Mar 21 '17 10:03

Ben Crowhurst


2 Answers

From the information you quoted:

So a default constructed thread is not joinable.

There's your answer. If you don't know whether your thread was default constructed or not, you do not know whether it was joinable.

So, near the end of your program/function/routine, when you want to join the thread (and you do need to do this, before the std::thread goes out of scope), you must do it conditionally. And this is how you do that.

#include <thread>

void bar(const unsigned int);

/**
 * This class may be default-constructed (in which case it does nothing),
 * or constructed with an `unsigned int` argument which shall be passed
 * to `bar()` in a worker thread.
 */
struct Foo
{
   Foo() {}

   Foo(const unsigned int x)
      : doThingsThread([&]() { bar(x); })
   {}

   ~Foo()
   {
      // The thread *MUST* be joined before destruction, if it
      // is joinable. Otherwise, it *CAN'T* be joined.
      if (doThingsThread.joinable())
         doThingsThread.join();
   }
private:
   std::thread doThingsThread;
};
like image 138
Lightness Races in Orbit Avatar answered Nov 09 '22 11:11

Lightness Races in Orbit


You use joinable when you have a std::thread object which may already have been joined, or may not reference an actual thread of execution (TOE - i.e., OS thread), and you want to join it if not already joined.

e.g. if you were implementing the proposed joinable_thread class, then the destructor would say if(thr.joinable()) thr.join();, to cover the case that someone already called join explicitly.

like image 23
Anthony Williams Avatar answered Nov 09 '22 13:11

Anthony Williams