我尝试理解future
和promise
的概念,但是在使用它们作为函数的返回值时遇到了一些问题。
我想出了下面的代码
#include <iostream>
#include <string>
#include <thread>
#include <future>
#include <chrono>
std::future<int> func(int i);
class A{
public:
A(std::promise<int> && prms, int i):thread_([&]{
std::cout << "Thread created in A\n";
std::this_thread::sleep_for(std::chrono::milliseconds(200));
prms.set_value(i*2);
thread_.detach();
}){std::cout << "Call constructor of A\n";}
~A(){std::cout << "Call A's Destructor\n";}
private:
std::thread thread_;
};
int main()
{
auto a_inst = func(2);
a_inst.wait();
std::cout << a_inst.get() << std::endl;
}
std::future<int> func(int i){
std::promise<int> prms;
//std::future<int> ftr = prms.get_future();
A A1(std::move(prms), i);
return prms.get_future();
}
因此main
应该从func
的返回值创建一个Future,等待赋值Future,然后打印它。
但是当我执行它时,A
是在不执行线程的情况下构造和销毁的。有人可以引导我朝正确的方向吗?
修改
我添加了包含不同promises
的向量。线程不直接处理promise
,而是调用processQueue
函数来执行此操作。类A
对象创建一次,并将unique_ptr引用传递给需要它的函数。
#include <iostream>
#include <string>
#include <thread>
#include <future>
#include <chrono>
#include <vector>
#include <mutex>
class A{
public:
int element_pointer = 0;
A():thread_([&]() {
std::cout << "Thread created in A\n";
for(;;){
std::this_thread::sleep_for(std::chrono::milliseconds(200));
processQueue();
}
//local_promise.set_value(local_i*2);
})
{
std::cout << "Call constructor of A\n";
}
~A(){
thread_.detach();
std::cout << "Call A's Destructor\n";
}
void enq(std::promise<int> prms){
std::lock_guard<std::mutex> guard(m);
local_prmses_.push_back(std::move(prms));
std::cout << "Queue now holds " << local_prmses_.size() << " elements\n";
}
private:
std::thread thread_;
std::mutex m;
std::vector<std::promise<int>> local_prmses_;
void processQueue(){
std::lock_guard<std::mutex> guard(m);
std::cout << "execute processQueue()" << std::endl;
if(element_pointer < local_prmses_.size()){
for(element_pointer; element_pointer<local_prmses_.size(); element_pointer++){
local_prmses_[element_pointer].set_value(6);
std::cout << "Promise assigned\n";
}
} else {
std::cout << "Nothing to process" << std::endl;
}
}
};
std::future<int> func(std::unique_ptr<A>& obj, int i);
int main()
{
std::unique_ptr<A> obj = std::make_unique<A>();
auto futr = func(obj, 9);
//a_inst.wait();
//std::cout << a_inst.get() << std::endl;
for(;;){
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
if(futr.valid()){
std::cout << "Yepeee!\n";
std::cout << "Result is " << futr.get() << std::endl;
}
std::cout << "waiting...\n";
}
}
std::future<int> func(std::unique_ptr<A>& obj, int i){
std::promise<int> prms;
auto fut = prms.get_future();
obj->enq(std::move(prms));
return fut;
}
答案 0 :(得分:3)
2个问题:
您正在A
中破坏线程对象,然后才能分离线程。
例如,您可以在A析构函数中分离线程,以便在A完全被析构之前控制流将到达它。
您的线程对象中的lambda正在处理仅在func
函数范围内有效的promise。一旦控制流离开此范围,您的诺言就会被破坏并抛出一个破损的诺言异常。为防止这种情况,您的lambda函数应拥有promise的所有权。如果需要所有权,则必须确保在所有权运动之前获得未来。
这将导致以下代码(我刚刚删除了您的错误。它的良好设计是否是另一个问题;-P):
#include <iostream>
#include <string>
#include <thread>
#include <future>
#include <chrono>
std::future<int> func(int i);
class A{
public:
A(std::promise<int> prms, int i):thread_([local_promise = std::move(prms), local_i = i]() mutable {
std::cout << "Thread created in A\n";
std::this_thread::sleep_for(std::chrono::milliseconds(200));
local_promise.set_value(local_i*2);
})
{
std::cout << "Call constructor of A\n";
}
~A(){
thread_.detach();
std::cout << "Call A's Destructor\n";
}
private:
std::thread thread_;
};
int main()
{
auto a_inst = func(9);
a_inst.wait();
std::cout << a_inst.get() << std::endl;
}
std::future<int> func(int i){
std::promise<int> prms;
auto fut = prms.get_future();
A A1(std::move(prms), i);
return fut;
}