我的理解是,如果我们调用从promise获得的未来,那么它将等到调用set_value,如果永远不会被调用,程序将永远等待但是当我使用promise rvalue reference时,这种行为不起作用(它是抛出破碎的承诺未来错误)虽然同样使用左值参考(永远等待)。任何推理都是因为我相信它应该在rvalue引用的情况下永远等待吗?
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
void calculateValue(std::promise<int> &&p)
//void calculateValue(std::promise<int> &p) //uncomment this it will wait
{
using namespace std::chrono_literals;
std::cout<<"This is start of thread function "<<std::endl;
//Do long operations
std::this_thread::sleep_for(2s);
// p.set_value(8);
std::cout<<"This is end of thread function "<<std::endl;
}
int main() {
std::promise<int> p;
auto fut = p.get_future();
std::thread t(calculateValue,std::move(p));
//uncomment this it will wait
//std::thread t(calculateValue,std::ref(p);
std::cout<<"main function ..."<<std::endl;
std::cout<<"value is "<<fut.get()<<std::endl;
t.join();
return 0;
}
答案 0 :(得分:2)
使用此形式的thread
构造函数时:
std::thread t(calculateValue, std::move(p));
然后,在内部,p
被移动到std::promise
的临时对象。此临时用作参数类型的calculateValue
独立的参数:
void calculateValue(std::promise<int> &&p) // option #1
void calculateValue(std::promise<int> p) // option #2
在线程完成执行之前,临时(或第二种情况下的p
参数)被销毁,这会触发std::future_error
,因为共享状态尚未就绪(set_value
已有没被调用过。)
但是,如果您使用std::reference_wrapper
:
std::thread t(calculateValue, std::ref(p));
然后,原始的promise不会被移动,它仍然存在,并且在main
结束之前不会调用它的析构函数。从未达到过,因为主线程将等待fut.get()
。
底线:问题根本与calculateValue
参数的形式无关。它是关于你是否从p
转移到临时的,它实际上定义了与未来(及其共享状态)相关的承诺的析构函数是否被破坏。
答案 1 :(得分:1)
当您执行std::move(p)
时,您有效地放弃了p
对该主题的所有权。 p
函数中的承诺main
没有任何未来,所以说。
当您传递引用(使用std::ref
)时,您仍然拥有承诺,并且线程函数只引用main
函数中的承诺。它类似于将指针传递给变量p
。
这就是你的程序在移动承诺时无法等待的原因,但在传递引用时会等待它。