使用promise和future在C++中从线程返回多个值?

3
我想要做的是从每个线程中返回一个值。但是,它会出现这个异常信息。
libc++abi.dylib: terminating with uncaught exception of type std::__1::future_error: Operation not permitted on an object without an associated state.

代码看起来像这样。
vector<thread> t;
promise<class_name> promises;
vector<future<class_name>> futures;

for(int i = 0; i < NumberOfThreads; i++)
{
    futures.push_back(promises.get_future());
    t.push_back(thread(MyFunction ,i , pointList, std::move(promises)));
}

而 MyFunction 看起来像这样。
void MyFunction(int index, const vector<Point>& pointList, promise<class_name>&& p)
{
....
p.set_value(classObj);
}

如果我使用一个线程,那么它可以正常运行,没有异常消息。

有什么解决问题的想法吗?

2个回答

5

在将promise移动到其线程后,请勿重复使用它。将promise移动到循环体内,你的代码应该可以正常运行:

vector<thread> t;
vector<future<class_name>> futures;

for(int i = 0; i < NumberOfThreads; i++)
{
    promise<class_name> p;
    futures.push_back(p.get_future());
    t.push_back(thread(MyFunction ,i , pointList, std::move(p)));
}

3
当你进行操作时
std::promise<T> p;

创建一个带有空共享状态的承诺 p。这与没有共享状态不同。

当你将承诺 move-from(转移)时,共享状态也被带走了。

std::promise<T> p2=std::move(p);

现在,p没有共享状态,而p2具有p构造时的空共享状态。

当你向容器中的push_back时,它会执行类似上述构造的操作(可能重复执行)。

p现在是一个极其无用的变量。可以将其销毁、赋值或与另一个promise进行swap操作,但是对p的所有其他操作都是非法的。

像这样的函数:

template<class T>
void reset_promise( std::promise<T>& p ) {
  p = std::promise<T>{};
}

可以用来给p赋予一个空的共享状态。然而,考虑到promise的典型使用模式,我认为这没有什么意义。

std::vector<std::thread> t;
std::promise<class_name> promises;
std::vector<std::future<class_name>> futures;

for(int i = 0; i < NumberOfThreads; i++)
{
  futures.push_back(promises.get_future());
  t.push_back(thread(MyFunction ,i , pointList, std::move(promises)));
}

第一次循环,你跳出了 Promise。第二次循环,你尝试从一个已经被移走的 Promise 中获取 get_future,这会导致你的代码非法。

要么:

for(int i = 0; i < NumberOfThreads; i++)
{
  futures.push_back(promises.get_future());
  t.push_back(thread(MyFunction ,i , pointList, std::move(promises)));
  reset_promise(promises);
}

如果您真的想要重复使用promises变量,或者

std::vector<std::thread> t;
std::vector<std::future<class_name>> futures;

for(int i = 0; i < NumberOfThreads; i++)
{
  std::promise<class_name> promises;
  futures.push_back(promises.get_future());
  t.push_back(thread(MyFunction ,i , pointList, std::move(promises)));
}

这将确保您在使用它的时候拥有一个有效的promise。 在这种情况下,第二个可能是最好的选择:promises在小范围内构建、使用和丢弃。

基本上,promise被设计成最适合创建、提取未来、将promise移动到需要的位置并丢弃的模式。 如果一个已移动的promise具有共享状态,那么将会耗费资源(因为该共享状态通常存储在堆上),所以他们没有这样做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接