使用 std::future::unwrap 进行异常传播

Race in exception propagation with std::future::unwrap

本文关键字:异常 传播 unwrap std future 使用      更新时间:2023-10-16

关于改进std::future的API的论文在这里n3721。 在未包装期货的异常传播方面似乎存在一场竞赛。 该文件说

如果外部未来

抛出异常,并且对返回的未来调用 .get((,则返回的未来将引发与外部未来相同的异常。之所以如此,是因为内在的未来没有退出

所以我的意思是在以下情况下

#include <iostream>
#include <future>
#include <exception>
using namespace std;
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();
        std::thread{[prom_two = std::move(prom_two)]() mutable {
            prom_two.set_exception(std::make_exception_ptr(std::logic_error{}));
        }}.detach();
        prom_one.set_exception(std::make_exception_ptr(std::bad_alloc{}));
    }}.detach();

    auto inner_fut = fut_one.unwrap();
    cout << inner_fut.get() << endl;
    return 0;
}

我之前谈到的比赛是 - 会抛出哪个例外? 内std::logic_error还是外std::bad_alloc

我弄错了吗? 上面的代码中没有种族吗?

我意识到上面的代码没有任何种族,因为对于嵌套的未来 - std::future<std::future<int>>只有两种可能性,要么通过调用std::promise::set_value设置了内部未来,要么设置了异常,并且内部未来根本不与外部未来相关联(如上面的代码所示(。

如果内在的未来没有被链接,那么外在未来的异常将是抛出的异常。 如果内在未来已经链接,那么外在未来就没有抛出的空间,因为外在未来的承诺已经与内在未来调用了一次set_value,所以在那之后在外在未来本身设置异常是无效的(这将导致异常本身被抛出(。

我认为这就是报纸在说的时候所说的

之所以如此,是因为内在的未来没有退出