broken `std::promise`s (why do they break when I store many futures before `.get()`ing them?)

Viewed 84

I was writing a unit test for my thread pool pool. This class has a sum function member stored inside, that it uses over and over again. The input to this sum function is passed in to work.

unsigned num_tries(1e3);
std::vector<std::future<double>> futs;
for(size_t i = 0; i < num_tries; ++i){
    futs.push_back( std::move( pool.work(std::vector<double>{1.0, 1.0, 1.0})) );
}

So, this thread pool should take the sum of three ones over and over again. The function returns a std::future<double>. So far so good.

However, when I try to .get() the values once all the computation is finished, I get a std::future_error: Broken promise error.

for(size_t i = 0; i < num_tries; ++i){                            
    std::cout << futs[i].get() << "\n";
}

Why is this? I thought .get() was blocking.

My guess: pool only stores one std::promise that keeps getting re-assigned every time work is called. Everything works when I stick both of these lines in a single for loop, so that .get() is always called before the subsequent std::promise is made. In other words, there are no errors with this code:

unsigned num_tries(1e3);
std::future<double> fut;
for(size_t i = 0; i < num_tries; ++i){
    fut =  pool.work(std::vector<double>{1.0, 1.0, 1.0});
    std::cout << fut.get() << "\n";
}

If this is the case, how can I prevent others from making the same mistake that I am making now? Have it return a double and block inside, I suppose would be one way.

0 Answers
Related