I've got this test code to see, if a promise object is out of lifecycle, what happen to its future object:
#include <chrono>
#include <future>
#include <iostream>
#include <thread>
using namespace std;
void getValue(future<int>& future) {
cout << "sub process 1 \n";
try {
cout << "sub process 2 \n";
int value = future.get();
cout << "sub process 3\n";
cout << value << endl;
} catch (future_error &e) {
cerr << e.code() << '\n' << e.what() << endl;
} catch (exception e) {
cerr << e.what() << endl;
}
cout << "sub process 4\n";
}
int main() {
thread t;
{
promise<int> plocal;
future<int> flocal = plocal.get_future();
t = thread(getValue, ref(flocal));
}
t.join();
return 0;
}
I expect that in getValue
function, it either prints future::get result, or throws out runtime exception and prints exception info, because plocal
has been destructed in "main".
Acturally, this program prints:
sub process 1
sub process 2
and ends.
CodePudding user response:
Your problem is not about std::promise
or std::future
behavior.
You simply cause a data race (and consequently undefined behavior) by passing the flocal
object by-reference to the thread, accessing it in the thread, but also destroying it in the main thread without any synchronization.
This doesn't work no matter what type or kind of object flocal
is.
Pass the std::future
by-value via std::move
:
void getValue(future<int> future)
/*...*/
t = thread(getValue, std::move(flocal));
With this change the destructor of std::promise
will store a std::future_error
exception in the shared state and get
on the future in the thread will receive and throw it.
If you pass something with std::ref
to a thread you always have to make sure that the referenced object outlives the thread or you need to make sure that there is some synchronization mechanism to determine when the main thread may destroy the object.