2

对来自n3721 “std::future 和相关 API 的改进”的 C++20 中即将推出的功能的后续参考

#include <iostream>
#include <future>
#include <exception>

using std::cout;
using std::endl;

int main() {
    auto prom_one = std::promise<std::future<int>>{};
    auto fut_one = prom_one.get_future();

    std::thread{[prom_one = std::move(prom_one)]() mutable {
        auto prom_two = std::promise<int>{};
        auto fut_two = prom_two.get_future();
        prom_two.set_value(1);
        prom_one.set_value(std::move(fut_two));
    }}.detach();

    auto inner_fut_unwrap = fut_one.unwrap();
    auto inner_fut_get = fut_one.get();

    auto th_one = std::thread{[&]() {
        cout << inner_fut_unwrap.get() << endl;
    }};
    auto th_two = std::thread{[&]() {
        cout << inner_fut_get.get() < endl;
    }};

    th_one.join();
    th_two.join();

    return 0;
}

在上面的代码中,哪个将赢得打印竞赛1th_one还是th_two


为了澄清我在说什么种族,这里有两种(潜在的)种族情况,后者是真正让我感到困惑的情况。

第一个是内在未来的设定和展开;未包装的未来应该作为内部未来的合适代理,即使实际set_value尚未被调用内部未来。因此unwrap(),无论另一端发生什么,都必须返回一个公开线程安全接口的代理。

另一种情况是,get()当它的代理已经存在于其他地方时,来自未来的 a 会发生什么,在这个例子inner_fut_unwrap中是 的代理 inner_fut_get。在这种情况下,谁应该赢得比赛?未包装的未来或通过get()对外部未来的调用获取的未来?

4

1 回答 1

1

这段代码让我担心对什么是future和promise存在某种误解,以及什么.get()是。也有点奇怪,我们using namespace std;跟了很多std::.

让我们分解一下。这是重要的部分:

#include <iostream>
#include <future>

int main() {
    auto prom_one = std::promise<std::future<int>>{};
    auto fut_one = prom_one.get_future();
    auto inner_fut_unwrap = fut_one.unwrap();
    auto inner_fut_get = fut_one.get();
    // Boom! throws std::future_error()

因此,两个线程都没有“赢得”比赛,因为两个线程实际上都没有机会运行。请注意您在 p13 上为 链接的文档.unwrap()

删除最外层的未来并返回一个代理到内部的未来。

所以最外层的未来fut_one, 是无效的。当您调用时.get(),它会抛出std::future_error1。没有种族。

1:不保证。技术上未定义的行为。

于 2017-05-14T04:52:25.160 回答