Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where is the thread going when a future leaves scope?

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().

ths destructor will call terminate() when it leaves scope.

But what about futures? 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?

like image 291
towi Avatar asked Oct 01 '11 14:10

towi


People also ask

What happens when thread goes out of scope?

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.

What happens when a thread goes out of scope C++?

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.

How do you stop a detached thread?

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 ...

How do you terminate a thread in C++?

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.


2 Answers

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().

like image 192
Tony The Lion Avatar answered Sep 21 '22 02:09

Tony The Lion


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.

like image 38
Stephan Dollberg Avatar answered Sep 21 '22 02:09

Stephan Dollberg