Reputation: 1711
I'm working on a program where I'd like to use async in a loop. In the example code I've included there's only 10 elements, so I could easily create an explicit variable for each element. However, in my main program, the number of elements in the vector can vary. Ideally, I'd like to create a vector of async threads - one for every element in the array - which are pushed back on the async vector as I loop through.Then I want to wait for them all to complete, and then use "get()" to return all of their outputs.
The code below will call async by assigning an explicit variable for each thread, but does anyone know how to dynamically call async in a vector without having to explicitly assign a variable to it? Ideally, I'd like for this program to call "std::cout" once for each time it looped through, instead of just once.
#include <iostream>
#include <vector>
#include <string>
#include <future>
std::string hi (std::string input)
{
return "hello, this is " + input;
}
int main()
{
std::vector<std::string> test_vector( 10, "a test" );
std::future<std::string> a;
std::future<std::string> b;
for ( int i = 0; i < test_vector.size ( ); i++ )
{
a = std::async(std::launch::async, hi, test_vector[i]);
}
std::cout << a.get() << std::endl;
return 0;
}
Upvotes: 10
Views: 4115
Reputation: 48615
You can solve this by creating a vector of futures to match your threads vector, something like this:
#include <iostream>
#include <vector>
#include <string>
#include <future>
std::string hi(const std::string& input)
{
return "hello, this is " + input;
}
int main()
{
std::vector<std::string> tests = {"one", "two", "three", "four"};
std::vector<std::future<std::string>> futures;
// add the futures to the futures vector as you launch
// your asynchronous functions
for(auto&& t: tests)
futures.emplace_back(std::async(std::launch::async, hi, std::cref(t)));
// collect your results
for(auto&& f: futures)
std::cout << f.get() << '\n';
}
Note the use of std::cref to pass by const reference. Use std::ref to pass non const references.
Upvotes: 15
Reputation: 476
If I understood correctly, could be something like:
std::vector<std::future<std::string>> vessel;
for ( int i = 0; i < test_vector.size ( ); i++ )
{
std::future<std::string> aux;
aux = std::async(std::launch::async, hi);
vessel.push_back(aux);
}
Sorry I cannot post as a comment, but this way, depending on the logic, and if it works, then you should be able to dynamically manipulate the vector vessel
.
Update
better yet:
vessel.push_back(new std::future<std::string>);
vessel[vessel.size()-1] = std::async(std::launch::async, hi);
this way you don't need to explicitly declare a variable. But you will have to delete
once you are done:
for(int i=0; i<(int) vessel.size(); i++)
{
delete vessel[i];
}
Upvotes: 3
Reputation: 1211
An answer including std::cout
:
std::vector<std::future<std::string>> a;
for (int i = 0; i < 10; ++i) {
a.emplace_back(std::async(hi));
}
for (auto& element : a) {
std::cout << element.get() << std::endl;
}
Upvotes: 11