megapro17
megapro17

Reputation: 425

How to parallelize a function, that uses some variable

I have a function, that generates random URL, and try to download the file.

void tryURL()
{
    randURL.clear();
    for (unsigned short i = 0; i < urlLength; i++)  {
    randURL = randURL + (alphabet[(int)((double)rand() / (RAND_MAX + 1) * alphabetLength)]);
    }
    wcout << randURL << endl;
    HRESULT getImg = URLDownloadToFile(NULL, LPCWSTR( (beginURL + randURL + endURL).c_str() ), LPCWSTR( (randURL + L"/" + endURL).c_str() ), 0, NULL);
    if (SUCCEEDED(getImg))
    {
    wcout << L"Success" << endl;
    }
}

If I execute this function normally, It's work fine:

tryURL();
0ybOAt
tryURL();
lTPKaR
tryURL();
Ivi05m
...

But, I need to run this function repeatedly times at that moment. I tried this:

thread threads[10];

for (int i = 0; i < 10; ++i) {
    threads[i] = thread(tryURL);
}

for (int i = 0; i < 10; ++i) {
    threads[i].join();
}

And it always returns me same value

0ybOAt0ybOAt
0ybOAt

0ybOAt0ybOAt

0ybOAt
0ybOAt0ybOAt
0ybOAt
0ybOAt

And even endl don't show's up sometimes.

How can I fix it? I think, it broken because always using same variable randURL, but I don't know how to evade this.

Upvotes: 2

Views: 61

Answers (2)

Vittorio Romeo
Vittorio Romeo

Reputation: 93274

Instead of using the same variable, make tryURL return the URL:

// assuming that URLs are strings
std::string tryURL() { /* ... */ }

Then, create a vector of std::future<std::string> to represent the asynchronous computations that will return URLs:

std::vector<std::future<std::string>>> futures;
futures.reserve(10);

for (int i = 0; i < 10; ++i) 
{
    futures.emplace_back(std::async(std::launch::async, tryURL));
}

Finally, consume the URLs in the main thread:

for(auto& f : futures) 
{
    consume(f.get());
} 

Upvotes: 2

Niklas Angare
Niklas Angare

Reputation: 71

Other questions on StackOverflow provide some clues:

A simple fix for the rand() issue is to generate the URL:s in the main thread and pass them to the thread.

void tryURL(std::wstring URL)
...
// TODO: Set randURL to a random URL
threads[i] = thread(tryURL, randURL);

Upvotes: 0

Related Questions