With threads I know that terminate()
is called when the thread-variable leaves scope:
size_t fibrec(size_t n) {
return n<2 ? 1 : fibrec(n-2)+fibrec(n-1);
}
int main() {
std::thread th{ fibrec, 35 };
// no join here
} // ~th will call terminate().
th
s destructor will call terminate()
when it leaves scope.
But what about future
s? Where is the thread they run going? Is it detached? How is it ended?
#include <iostream>
#include <future> // async
using namespace std;
size_t fibrec(size_t n) {
return n<2 ? 1 : fibrec(n-2)+fibrec(n-1);
}
struct Fibrec {
size_t operator()(size_t n) { return fibrec(n); }
const size_t name_;
Fibrec(size_t name) : name_(name) {}
~Fibrec() { cerr << "~"<<name_<< endl; }
};
void execit() {
auto f1 = async( Fibrec{33}, 33 );
auto f2 = async( Fibrec{34}, 34 );
// no fx.get() here !!!
}; // ~f1, ~f2, but no terminate()! Where do the threads go?
int main() {
auto f0 = async( Fibrec{35}, 35 );
execit();
cerr << "fib(35)= " << f0.get() << endl;
}
When execit()
is left the futures f1
and f2
are destroyed. But their threads should still be running? The destructor of Fibrec
is called, of course. But where are the threads going? The program does not crash, so I guess, the become joined? Or maybe detached? Or are they stopped or canceled? I believe that is not trivially done in C++11?
The thread continues to execute until the thread procedure is complete. So even if the Thread object is unreferenced, the thread will still run. Save this answer.
So after } t goes out of scope but the actual thread will keep on running until its instruction completes. Save this answer. Show activity on this post. detach basically releases the std::thread object instance which is the C++ "handle" to the actual OS thread, thereby making it impossible to join the thread later.
In C++, once the thread is detached or uses the detach() function, then we cannot stop such threads, and still, if there is a need for stopping such threads, then only one way is to return the thread from the initial thread function by instantiating it in main() function, adding the Boolean value but before exiting ...
The C++11 does not have direct method to terminate the threads. The std::future<void> can be used to the thread, and it should exit when value in future is available. If we want to send a signal to the thread, but does not send the actual value, we can pass void type object.
The future
is the result of the async operation, it's is not a thread by itself. The async
function spawns a new thread to do the computation, and when that is finished, the result is written to a future
object.
Depending on the implemented policy, you will either have to call .get()
or .wait()
on the future to get the result. Invoking this will do the work on the thread on which it is called
If policy is
std::launch::async
then runs INVOKE(fff,xyz...) on its own thread. The returned std::future will become ready when this thread is complete, and will hold either the return value or exception thrown by the function invocation. The destructor of the last future object associated with the asynchronous state of the returned std::future shall block until the future is ready.If policy is
std::launch::deferred
then fff and xyz... are stored in the returned std::future as a deferred function call. The first call to the wait() or get() member functions on a future that shares the same associated state will execute INVOKE(fff,xyz...) synchronously on the thread that called wait() or get().
Here is a very basic std::async
implementation(without a task-pool or std::launch
stuff):
template< class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type>
async( Function&& f, Args&&... args )
{
std::packged_task<F(Args...)> task(std::forward<F>(f), std::forward<Args>(args)...);
auto ret = task.get_future();
std::thread t(std::move(task));
t.detach();
return ret;
}
You see that the actually computation is done in a detached thread. The future is just a synchronization object. std::packaged_task
is just another wrapper for the std::promise
set_value
/set_exception
logic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With