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
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).
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();
The std::thread::thread(F&& f, Args&&... args) constructor has this postcondition:
Postconditions: get_id() != id(). *this represents the newly started thread.
The definition of joinable() is
Returns: get_id() != id()
Therefore the constructor's postcondition is that the object is joinable, and the postcondition applies as soon as the constructor completes. It is irrelevant whether the OS has actually started the thread yet, the thread object still knows the new thread's ID and can still wait for it to complete and join it.
Related
// threadMovedFixed.cpp
#include <iostream>
#include <thread>
#include <utility>
int main(){
std::thread t([]{std::cout << std::this_thread::get_id() << std::endl;});
std::thread t2([]{std::cout << std::this_thread::get_id() << std::endl;});
t.join();
t = std::move(t2);
t.join();
std::cout << "\n";
std::cout << std::boolalpha << "t2.joinable(): " << t2.joinable() << std::endl;
}
I am looking at the following snippet, and it seems there are several issues here.
(1) t2 is being moved to t while t2 while it may be in the middle of executing its lambda. What happens to t2 in this case? Does t2 terminate right away and t re-executes t2's lambda from the the beginning, or does it pick up where t2 left off?
(2) t is receiving t2, but t could be in the middle of its execution of the lambda. What happens here? Does t terminate its own call immediately upon receiving t2?
What happens to t2 in this case?
It will no longer refer to a thread of execution.
Does t2 terminate right away
std::thread object isn't something that can be terminated. It potentially refers to a thread of execution which is something that can conceptually terminate. That thread of execution is not affected by the move. After the move, t refers to the thread of execution instead.
but t could be in the middle of its execution of the lambda.
t has been joined, and therefore it no longer refers to a thread of execution until t2 is assigned to it.
If t was joinable, then std::terminate would be called (which terminates the process).
Please keep in mind that C++ doesn't implement all the multithreading stuff but delegates that to OS. C++ multithreading classes are just wrappers with a convenient interface that follows C++ idioms.
So, there is no problem in moving a running thread to another std::thread object. Otherwise (look on it from another angle) why does std:thread even have a move constructor? Actually all the OS threads are running even without knowing that C++ has a wrapper. The OS thread (e.g. pthread) continue running being wrapped with another object.
Regarding your second question, t is not in the middle of it's execution cause it is already in non-joinable state.
While learning basic thread management, I found difficulty in understanding these lines (in bold) from a book.
Once you’ve started your thread, you need to explicitly decide whether
to wait for it to finish (by joining with it—see section 2.1.2) or
leave it to run on its own (by detaching it—see section 2.1.3). If you
don’t decide before the std::thread object is destroyed, then your
program is terminated (the std::thread destructor calls
std::terminate()). It’s therefore imperative that you ensure that the
thread is correctly joined or detached, even in the presence of
exceptions. See section 2.1.3 for a technique to handle this scenario.
Note that you only have to make this decision before the std::thread
object is destroyed—the thread itself may well have finished long
before you join with it or detach it, and if you detach it, then the
thread may continue running long after the std::thread object is
destroyed.
When does a thread run even after the thread object is destroyed? Anyone have sample code or any reference?
What this means is that the lifetime of the thread is not associated with the lifetime of the thread object.
So the following code:
#include <thread>
#include <iostream>
int main() {
{ //scope the thread object
std::thread thr = std::thread([]() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Thread stuff\r\n";
});
thr.detach();
} //thr is destroyed here
std::cout << "thr destroyed, start sleep\r\n";
std::this_thread::sleep_for(std::chrono::seconds(10));
std::cout << "sleep over\r\n";
}
Will output:
thr destroyed, start sleep
Thread stuff
sleep over
I am testing the new C++11 thread features. To do this, I start a thread by providing a lambda expression to its constructor:
int main()
{
thread t([]() {
cout << "Hello World!" << endl;
});
//this_thread::sleep_for(chrono::seconds(5));
cout << "I am done!" << endl;
getchar();
return 0;
}
But after I press a key (getchar), I get the error:
Can someone give a reason?
The behavior you're seeing is expected and the following explains how to avoid it.
From the std::thread::~thread documentation.
If *this has an associated thread (joinable() == true), std::terminate() is called.
A thread object does not have an associated thread (and is safe to destroy) after
it was default-constructed
it was moved from
join() has been called
detach() has been called
So what? I understand that join() must only be called for the main thread to wait for the worker thread. In this case, there is no purpose in waiting, because I press a key.
Why is there no purpose in waiting? What happens if the main function finishes execution before the std::cout stream object is used by the thread (albeit unlikely it's still possible even though you have the getchar() call)? Is that global stream object still valid for use by the thread?
Learning C++ multi-threading.
In my example, thread helper1 and helper2 have finished executing before the main thread finished. However, program crashes. I specifically, took out .join() statements, to see how program would behave, expecting no errors, since main() calls std::terminate after two other threads have finished.
void foo()
{
// simulate expensive operation
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "t1\n";
}
void bar()
{
// simulate expensive operation
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "t2\n";
}
int main()
{
std::cout << "starting first helper...\n";
std::thread helper1(foo);
std::cout << "starting second helper...\n";
std::thread helper2(bar);
std::this_thread::sleep_for(std::chrono::seconds(10));
std::cout << "waiting for helpers to finish..." << std::endl;
//helper1.join();
//helper2.join();
std::cout << "done!\n";
}
I'd say that your question doesn't make sense, because it's based on a false assumption. The only way to know that a thread has finished is when the thread's join() returns. Before join() returns, it is not the case that "the thread has finished". It may be true that some statement within the thread's execution has completed (e.g. the printing of a message, or better, the writing of an atomic variable), but the completion of the thread function itself is not measurable in any way other than by joining.
So none of the threads "have finished" until you join them.
Because std::~thread calls terminate if the associated thread is still joinable:
30.3.1.3 thread destructor [thread.thread.destr]
~thread();
If joinable(), calls std::terminate(). Otherwise, has no effects. [
Note: Either implicitly detaching or joining a joinable() thread in its destructor could result in difficult to debug correctness (for detach) or performance (for join) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. —end note]
You need to call either .detach() or .join(). Other than that, since you cannot be sure how the operating system schedules your threads, you could end up interrupting your threads any way, so better use .join() from the beginning.
Based on the reference, underlying thread must be joined or detached at the time the destructor is called. The destructor is invoked when main exits, and probably assumes that join or detach has been called.
The code should also not crash, as long as the following two lines are somewhere after helper1 and helper2 are constructed.
helper1.detach()
helper2.detach()
The CPU can schedule the three threads ( main / thread1 / thread2 ) in any order. It might happen that your main doesn't get a time to run and your threads exit. So, you need to keep keep join in main to take care of this case. Scheduling of threads is unpredictable, unless you are using an RTOS.
Sometime I have to use std::thread to speed up my application. I also know join() waits until a thread completes. This is easy to understand, but what's the difference between calling detach() and not calling it?
I thought that without detach(), the thread's method will work using a thread independently.
Not detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Calling with detaching:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}
In the destructor of std::thread, std::terminate is called if:
the thread was not joined (with t.join())
and was not detached either (with t.detach())
Thus, you should always either join or detach a thread before the flows of execution reaches the destructor.
When a program terminates (ie, main returns) the remaining detached threads executing in the background are not waited upon; instead their execution is suspended and their thread-local objects destructed.
Crucially, this means that the stack of those threads is not unwound and thus some destructors are not executed. Depending on the actions those destructors were supposed to undertake, this might be as bad a situation as if the program had crashed or had been killed. Hopefully the OS will release the locks on files, etc... but you could have corrupted shared memory, half-written files, and the like.
So, should you use join or detach ?
Use join
Unless you need to have more flexibility AND are willing to provide a synchronization mechanism to wait for the thread completion on your own, in which case you may use detach
You should call detach if you're not going to wait for the thread to complete with join but the thread instead will just keep running until it's done and then terminate without having the spawner thread waiting for it specifically; e.g.
std::thread(func).detach(); // It's done when it's done
detach basically will release the resources needed to be able to implement join.
It is a fatal error if a thread object ends its life and neither join nor detach has been called; in this case terminate is invoked.
This answer is aimed at answering question in the title, rather than explaining the difference between join and detach. So when should std::thread::detach be used?
In properly maintained C++ code std::thread::detach should not be used at all. Programmer must ensure that all the created threads gracefully exit releasing all the acquired resources and performing other necessary cleanup actions. This implies that giving up ownership of threads by invoking detach is not an option and therefore join should be used in all scenarios.
However some applications rely on old and often not well designed and supported APIs that may contain indefinitely blocking functions. Moving invocations of these functions into a dedicated thread to avoid blocking other stuff is a common practice. There is no way to make such a thread to exit gracefully so use of join will just lead to primary thread blocking. That's a situation when using detach would be a less evil alternative to, say, allocating thread object with dynamic storage duration and then purposely leaking it.
#include <LegacyApi.hpp>
#include <thread>
auto LegacyApiThreadEntry(void)
{
auto result{NastyBlockingFunction()};
// do something...
}
int main()
{
::std::thread legacy_api_thread{&LegacyApiThreadEntry};
// do something...
legacy_api_thread.detach();
return 0;
}
When you detach thread it means that you don't have to join() it before exiting main().
Thread library will actually wait for each such thread below-main, but you should not care about it.
detach() is mainly useful when you have a task that has to be done in background, but you don't care about its execution. This is usually a case for some libraries. They may silently create a background worker thread and detach it so you won't even notice it.
According to cppreference.com:
Separates the thread of execution from the thread object, allowing
execution to continue independently. Any allocated resources will be
freed once the thread exits.
After calling detach *this no longer owns any thread.
For example:
std::thread my_thread([&](){XXXX});
my_thread.detach();
Notice the local variable: my_thread, while the lifetime of my_thread is over, the destructor of std::thread will be called, and std::terminate() will be called within the destructor.
But if you use detach(), you should not use my_thread anymore, even if the lifetime of my_thread is over, nothing will happen to the new thread.
Maybe it is good idea to iterate what was mentioned in one of the answers above: When the main function is finished and main thread is closing, all spawn threads either will be terminated or suspended. So, if you are relying on detach to have a background thread continue running after the main thread is shutdown, you are in for a surprise. To see the effect try the following. If you uncomment the last sleep call, then the output file will be created and written to fine. Otherwise not:
#include <mutex>
#include <thread>
#include <iostream>
#include <fstream>
#include <array>
#include <chrono>
using Ms = std::chrono::milliseconds;
std::once_flag oflag;
std::mutex mx;
std::mutex printMx;
int globalCount{};
std::ofstream *logfile;
void do_one_time_task() {
//printMx.lock();
//std::cout<<"I am in thread with thread id: "<< std::this_thread::get_id() << std::endl;
//printMx.unlock();
std::call_once(oflag, [&]() {
// std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
// std::cout<<"Initialized globalCount to 3\n";
globalCount = 3;
logfile = new std::ofstream("testlog.txt");
//logfile.open("testlog.txt");
});
std::this_thread::sleep_for(Ms(100));
// some more here
for(int i=0; i<10; ++i){
mx.lock();
++globalCount;
*logfile << "thread: "<< std::this_thread::get_id() <<", globalCount = " << globalCount << std::endl;
std::this_thread::sleep_for(Ms(50));
mx.unlock();
std::this_thread::sleep_for(Ms(2));
}
std::this_thread::sleep_for(Ms(2000));
std::call_once(oflag, [&]() {
//std::cout << "Called once by thread: " << std::this_thread::get_id() << std::endl;
//std::cout << "closing logfile:\n";
logfile->close();
});
}
int main()
{
std::array<std::thread, 5> thArray;
for (int i = 0; i < 5; ++i)
thArray[i] = std::thread(do_one_time_task);
for (int i = 0; i < 5; ++i)
thArray[i].detach();
//std::this_thread::sleep_for(Ms(5000));
std::cout << "Main: globalCount = " << globalCount << std::endl;
return 0;
}