【问题标题】:Race in std::future::unwrap() and std::future::get()在 std::future::unwrap() 和 std::future::get() 中竞争
【发布时间】:2017-10-12 18:50:35
【问题描述】:

来自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;
}

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


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

第一个是内在未来的设定和展开;即使没有在内部未来调用实际的set_value,未包装的未来也应该作为内部未来的合适代理。所以unwrap() 必须返回一个公开线程安全接口的代理,而不管另一端发生什么。

另一种情况是未来的get() 的代理已经存在于其他地方,在此示例中inner_fut_unwrapinner_fut_get 的代理。在这种情况下,谁应该赢得比赛?未包装的未来或通过在外部未来上调用get() 获取的未来?

【问题讨论】:

标签: c++ c++11 future unwrap c++20


【解决方案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:不保证。技术上未定义的行为。

【讨论】:

  • 你在暗示什么误解?第一个线程的目的是表明unwrap() 必须在激烈的条件下工作,例如当内部未来甚至还没有出现以及内部未来已经被设定为外部未来时。
  • 第二个和第三个线程提出了一个问题,即哪个线程实际上从内部未来和未包装未来的共享状态中获取值。两者不应该得到相同的值,只有一个应该; future 不要求值是可复制的,只需要可移动的,这与 shared_future 不同。这篇论文甚至说,来自内部未来的价值将被转移到外部未来。然而,没有提到在激烈的情况下会发生什么,这就是我在问题中提出的问题
  • 对不起,你是对的。下次你可能想把它放在问题中,而不是仅仅发布一大段代码并要求我们弄清楚问题是什么。
猜你喜欢
  • 1970-01-01
  • 2014-11-10
  • 2021-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-15
  • 1970-01-01
相关资源
最近更新 更多