jeudi 27 juin 2019

Is standard guarantee safe usage of std::future after moving std::packaged_task?

Let's say we have following code:

#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;
}

It works perfect on my Visual Studio environment, as you see I retrieve std::future right before I moving std::packaged_task to newly created std::shared_ptr. I've took a look into C++ standard about std::packaged_task, so §30.6.9.1 packaged_task(packaged_task&& rhs) noexcept p.6:

Effects: constructs a new packaged_task object and transfers ownership of rhs’s shared state to *this, leaving rhs with no shared state. Moves the stored task from rhs to *this.

and §30.6.9 p.2 says:

When the packaged_task object is invoked, its stored task is invoked and the result (whether normal or exceptional) stored in the shared state. Any futures that share the shared state will then be able to access the stored result.

Based on this info I have two questions:

1) Am I right saying that std::packaged_task would be linked to the same std::future after std::move?

2) It's safe to use my std::shared_ptr in other thread and execute task there, checking std::future from current one?

Aucun commentaire:

Enregistrer un commentaire