Гонка при распространении исключений с помощью std::future::unwrap

Ознакомление с документом об улучшениях API std::future здесь 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?

Я понимаю это неправильно? В приведенном выше коде нет гонки?


person Curious    schedule 12.05.2017    source источник


Ответы (1)


Я понял, что в приведенном выше коде нет никакой гонки, так как с вложенным будущим - std::future<std::future<int>> есть только две возможности, либо внутреннее будущее было установлено через вызов std::promise::set_value, либо было установлено исключение, а внутреннее будущее не связано во внешнее будущее вообще (как в приведенном выше коде).

Если внутреннее будущее не было связано, тогда выбрасывается исключение внешнего будущего. И если внутреннее будущее было связано, нет возможности для броска внешнего будущего, потому что обещание внешнего будущего уже вызывало set_value с внутренним будущим один раз, поэтому установка исключения после этого для самого внешнего будущего недействительна (что вызовет выбрасывается само исключение).

Я думаю, это то, о чем говорила газета, когда писала

Это происходит потому, что внутреннее будущее не выходило

person Curious    schedule 12.05.2017