Является ли стандартная гарантия безопасного использования std :: future после перемещения std :: packaged_task? - PullRequest
4 голосов
/ 27 июня 2019

Допустим, у нас есть следующий код:

#include <iostream>
#include <future>

int main() {
    auto packagedTask = std::packaged_task<int()>([] {
        std::cout << "hello!\n";
        return 10;
        });

    auto packagedTaskFuture = packagedTask.get_future();
    auto packagedTaskPtr = std::make_shared<decltype(packagedTask)>(std::move(packagedTask));

    auto v1 = packagedTaskFuture.valid(); // is valid
    auto v2 = packagedTaskFuture.wait_for(std::chrono::seconds(0)); // timeout state
    (*packagedTaskPtr)(); // execute task
    auto v3 = packagedTaskFuture.wait_for(std::chrono::seconds(1)); // ready state
    auto v4 = packagedTaskFuture.get(); // 10

    return 0;
}

Он отлично работает в моей среде Visual Studio, как вы видите, я получаю std::future непосредственно перед тем, как переместить std::packaged_task во вновь созданный std::shared_ptr.Я ознакомился со стандартом C ++ в отношении std::packaged_task, поэтому §30.6.9.1 packaged_task(packaged_task&& rhs) noexcept p.6:

Эффекты: создает новый объект packaged_task и передает владение общим состоянием rhs в* это, оставляя rhs без общего состояния.Перемещает сохраненную задачу из rhs в * this.

и §30.6.9 p.2 говорит:

Когда вызывается объект packaged_task, вызывается его сохраненная задачаи результат (будь то нормальный или исключительный) сохраняется в общем состоянии.Любые фьючерсы, которые совместно используют общее состояние, смогут получить доступ к сохраненному результату.

На основании этой информации у меня есть два вопроса:

1) Правильно ли я говорю, что std::packaged_task будет связан с тем же std::future после std::move?

2) Безопасно ли использовать мой std::shared_ptr в другом потоке и выполнять там задачу, проверяя std::future из текущего?

1 Ответ

2 голосов
/ 27 июня 2019

Таким образом, стандарт говорит о (скрытом) общем состоянии. Это общее состояние перемещается на std::move копии на основе.

Объекты - упакованная задача, будущее - должны рассматриваться как различные виды интеллектуальных указателей, которые имеют ссылки на это общее состояние.

Существует ноль состояний гонки, которые могут быть вызваны взаимодействием этого общего состояния в нескольких потоках. Единственные условия гонки, которые могут возникнуть, это если вы взаимодействуете с одним и тем же объектом из нескольких потоков, и хотя бы в одном потоке вы вызываете не const метод.

«Общее состояние» в примитивах параллелизма C ++ является концептуальным и даже не может быть объектом . У него нет методов.

Итак, да и да.

...