Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Async Calls in C++

I want to call a method with async multiple times. A simplified example is shown below:

size_t counter(std::string &s)
{
    return s.size();
}

void stringCountAccumulator()
{
    std::vector<std::string> foos = {"this", "is", "spartaa"};
    size_t total = 0;
    for (std::string &s : foos)
    {
        std::future<size_t> fut = std::async(
            std::launch::async,
            counter, s);

        total += fut.get();
    }
    std::cout << "Total: " << total;
}

It seems that, fut.get() blocks other future calls. How can I implement this problem in C++? I need to call a function in a separate thread. This function "returns" a value.

like image 464
Turkdogan Tasdelen Avatar asked Feb 18 '17 10:02

Turkdogan Tasdelen


People also ask

How do I make multiple calls from async?

In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() . Promise. all() will wait for all the provided async calls to be resolved before it carries on(see Conclusion for caveat).

How to await an async function?

async and await Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

Why we need async and await?

Use of async and await enables the use of ordinary try / catch blocks around asynchronous code. Note: The await keyword is only valid inside async functions within regular JavaScript code. If you use it outside of an async function's body, you will get a SyntaxError .

How async works?

The async keyword turns a method into an async method, which allows you to use the await keyword in its body. When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete. await can only be used inside an async method.


1 Answers

void stringCountAccumulator()
{
  std::vector<std::string> foos = {"this", "is", "spartaa"};
  std::vector<std::future<size_t>> calcs;
  for (auto&& s : foos) {
    calcs.push_back( std::async(
      std::launch::async,
      counter, s)
    );
  }
  std::size_t total = 0;
  for (auto&& fut:calcs)
    total += fut.get();
  std::cout << "Total: " << total << "\n";
}

.get() is blocking. So don't block until you have queue'd up all tasks.

An alternative plan is to write/find a thread pool, and have each task update a possibly atomic (or mutex guarded) counter.

Have a finished-task counter guarded (again, possibly atomic).

Have a promise (of the total) which you fulfill when the last task is finished (fulfilled by the last task).

Return the future from that promise. Now you have a future representing the entire pool of threads calculating their value and adding it up, with lots of concurrency.

Some frameworks, like microsoft's ppl, have a system where it does something like this for you; you have tasks that return values, and a function object that combines the values, and get the result of the combination out of it.

like image 51
Yakk - Adam Nevraumont Avatar answered Sep 18 '22 10:09

Yakk - Adam Nevraumont