Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable number of async threads with C++11

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;
 }
like image 647
Jack Simpson Avatar asked Nov 17 '14 03:11

Jack Simpson


People also ask

Does STD async use threads?

If the async flag is set, then a callable function will be executed in a separate thread. If the deferred flag is set, a callable function will be stored together with its arguments, but the std::async function will not launch a new thread.

Does STD async create a new thread?

If the deferred flag is set (i.e. (policy & std::launch::deferred) ! = 0), then async converts f and args... the same way as by std::thread constructor, but does not spawn a new thread of execution.

What does STD async return?

With a std::async call the return value of the supplied function (as determined by std::result_of) sets the template type of the returned std::future: // function returns an int so std::async() returns a std::future<int> std::future<int> fut = std::async(std::launch::async, []{ return 1; });


2 Answers

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.

like image 81
Galik Avatar answered Nov 03 '22 10:11

Galik


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;
}
like image 41
ALittleDiff Avatar answered Nov 03 '22 09:11

ALittleDiff