curiousguy12
curiousguy12

Reputation: 1807

Is there a data race on packaged task arguments?

A thread is created via a packaged task and a std::vector is returned.

#include <iostream>
#include <future>
#include <thread>
#include <vector>

std::vector<int> func(int &arg)
{
    std::vector<int> v = {1,2,3,4};

    arg = 10;

    return v;
}

int main()
{
    std::packaged_task<std::vector<int>(int &)> pt{func};
    auto fut = pt.get_future();

    int arg = 0;
    std::thread thr{std::move(pt), std::ref(arg)};

    auto vec = fut.get();

    std::cout << arg << std::endl;  // data race here ?

    thr.join();
}

The std::future guarantees that the vector is synchronized with the main thread (before join), but I am not sure about the status of the packaged task argument (which is passed by reference).

So the question is whether there is a data race on arg ?

Upvotes: 3

Views: 78

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275500

int arg=0;

this happens-before we start the thread thr, as it is sequenced-before it.

arg = 10;

this happens-before vec is initialized, due to the .get() call:

auto vec=fut.get();

which is sequenced-before

std::cout << arg << std::endl;

so I see no data race here.

While not authortative, cpp reference claims:

The promise is the "push" end of the promise-future communication channel: the operation that stores a value in the shared state synchronizes-with (as defined in std::memory_order) the successful return from any function that is waiting on the shared state (such as std::future::get).

there are similar words for std::async as well. I believe a similar guarantee holds for packaged_task; it is intended to be used as a primitive to help implement your own std::async like behaviour after all.

Upvotes: 3

Related Questions