Start remaining futures without blocking

I have a loop over a set where I have to do an expensive calculation. I want to do this in parallel using a future class. As far as I understand, async starts a thread or snoozes it and only starts it when I call get () or wait (). Therefore, when I have threads that are not started and trying to get a result, I block the main thread, getting sequential processing. Is there a way to start the remaining pending processes, so everything is calculated in parallel and will not be blocked when get () is called.

// do the calculations
std::vector<std::future<class>> futureList;
for (auto elem : container)
{
  futureList.push_back(std::async(fct, elem));
}

// start remaining processes

// use the results
for (auto elem : futureList)
{
  processResult(elem.get())
} 

Thank you for your help.

+4
source share
2 answers

You can use:

std::async(std::launch::async, fct, elem)

Example:

#include <iostream>
#include <future>
#include <chrono>
#include <vector>
#include <stdexcept>

bool work() {
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    if( ! (std::rand() % 2)) throw std::runtime_error("Exception");
    return true;
}

int main() {
    const unsigned Elements = 10;

    typedef std::vector<std::future<bool>> future_container;
    future_container futures;

    for(unsigned i = 0; i < Elements; ++i)
    {
        futures.push_back(std::async(std::launch::async, work));
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }

    while( ! futures.empty()) {
        future_container::iterator f = futures.begin();
        while(f != futures.end())
        {
            if(f->wait_for(std::chrono::milliseconds(100)) == std::future_status::timeout) ++f;
            else {
                // Note:: Exception resulting due to the invokation of 
                //        the thread are thrown here.
                //        (See 30.6.6 Class template future)
                try {
                    std::cout << f->get() << '\n';
                }
                catch(const std::exception& e) {
                    std::cout << e.what() << '\n';
                }
                f = futures.erase(f);
            }
        }
    }
    return 0;
}
+1

- : (http://coliru.stacked-crooked.com/a/005c7d2345ad791c)

:

void processResult_async(std::future<myClass>& f) { processResult(f.get()); }

// use the results
std::vector<std::future<void>> results;
for (auto& elem : futureList)
{
    results.push_back(std::async(std::launch::async, processResult_async, std::ref(elem)));
}
0

Source: https://habr.com/ru/post/1535535/


All Articles