Why are plain threads dangerous
When we start a thread, there are two options. Either we will wait for the
thread to finish or we will not wait for it. A mechanism for waiting is
a .join()
member function. This is what we did in the first
article. The
.detach()
member function is the other option: not waiting
for the thread to finish.
Therefore, we must choose between these two options. If we don’t detach or join
the thread, the program will crash! If you don’t believe me, comment a
.join()
call in
helloWorld.cpp,
compile and run the program. You should get an error message:
Two options
Thus, we must call either join
or
detach
. The second option is not problematic. The
.detach()
is invoked right after the construction of a
thread.
The first approach, however, has some problems. Invoking the
.join()
right after constructor doesn’t make sense, because
there is no need for the new thread in this case. Therefore, there is some code
between the construction of the thread and the .join()
call.
But this code can emit an exception, which consequently means that the
.join()
will not be invoked and the program will crash.
The solution is a Guard
class. Let us have a look at it.
An object of the class has a reference to a thread. The destructor checks if the
thread is joinable and then joins it. A thread is joinable if
.join()
or .detach()
were not called
yet. A guard object can not be copied, because we declared copy constructor and
copy assignment operator with =delete
. Inability to copy
means that the object can not outlive the scope of referenced thread.
This class guarantees that .join()
member function will be
called in any case. When the function ends, the destructors of all objects in
the scope are called before the program exits. This also happens if the function
raises an exception and ends prematurely.
Acknowledgment
Thanks to Nino Bašić for comments and suggestions. Now the article looks more organized!
Summary
We learned why are the plain threads dangerous and how to make them safer with a
Guard
class.
In the next article, we will look how to pass an argument to a thread.
Links: