lightxbulb
lightxbulb

Reputation: 1321

std::thread pass vector element by reference

I'm trying to figure out why the following works:

threaded thr[8] = { threaded(), threaded() ,threaded() ,threaded() ,threaded() ,threaded() ,threaded() ,threaded() };
std::vector<std::thread> vec;
for (int i = 0; i < threads; i++)
{
    vec.push_back(std::thread(&threaded::calc, &thr[i], i, num_samples));
}

And the following doesn't:

std::vector<threaded> thr;
std::vector<std::thread> vec;
for (int i = 0; i < threads; i++)
{
    thr.push_back(threaded());
    vec.push_back(std::thread(&threaded::calc, &thr[i], i, num_samples));
}

I tried with a std::ref instead of & - it still doesn't work. Here's threaded's definition:

struct threaded
{
    float elapsed1 = 0;
    float elapsed2 = 0;
    float res = 0;
    float res_jit = 0;
    void calc(int thread, int num_samples){//do something}
};

By doesn't work I mean, that when using vector and &, I get a memory access violation, when I try to use std::ref(thr[i]) instead of &, it doesn't want to compile with the following errors:

Error   C2672   'std::invoke': no matching overloaded function found        

and

Error   C2893   Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'        

If I use just thr[i] it works fine, but I want to modify the values of the threaded class, so I don't really want to pass a copy.

Upvotes: 0

Views: 820

Answers (1)

Piotr Skotnicki
Piotr Skotnicki

Reputation: 48457

As vector thr gets bigger with each push_back call, eventually exceeding the capacity of a reserved memory region, it needs to reallocate its storage and copy (or move) its elements to the newly allocated space. Once it happens, the objects start to live under new memory addresses, thus the previously obtained addresses are invalidated. In order to prevent relocation, reserve enough space before entering the loop:

std::vector<threaded> thr;
thr.reserve(threads);

or default-construct all elements at once:

std::vector<threaded> thr(threads);

Upvotes: 2

Related Questions