Opened 9 years ago

Last modified 9 years ago

#8600 assigned Bugs

wait_for_any hangs, if called with multiple copies of shared_future referencing same task

Reported by: Martin Apel <martin.apel@…> Owned by: viboes
Milestone: To Be Determined Component: thread
Version: Boost 1.53.0 Severity: Problem
Keywords: Cc:

Description

The following small test program shows the problem:

#include <iostream>
#include <boost/thread.hpp>

int calculate_the_answer_to_life_the_universe_and_everything()
{
    return 42;
}

int main(int argc, char* argv[])
{
   boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
   boost::shared_future<int> fi1 = boost::shared_future<int>(pt.get_future());
   boost::shared_future<int> fi2 = fi1;

   boost::thread task(boost::move(pt)); // launch task on a thread

   boost::wait_for_any(fi1, fi2);
   std::cout << "Wait for any returned\n";
   return (0);
}

This program hangs infinitely in the call to boost::wait_for_any. From the docs I would expect this to work, because it's allowed to copy shared_futures. If this is not allowed, a possibility would be needed, to find out, if two shared_futures point to the same task or not. Currently wait_for_any is unusable, if there are chances, that multiple shared_futures point to the same result.

Change History (6)

comment:1 by viboes, 9 years ago

Owner: changed from Anthony Williams to viboes
Status: newassigned

Thanks for catching this, even if I would not this to work.

I think the fix would be to document that the shared state of the N-futures must be different as a pre-condition.

I don't think the library must provide any check to avoid this usage.

comment:2 by Martin Apel <martin.apel@…>, 9 years ago

That's fine with me, as long as there is a possibility to detect, if two shared_futures point to the same object. Currently there is no such function, so there is no possibility to remove the duplicates before calling wait_for_any.

in reply to:  2 comment:3 by viboes, 9 years ago

Replying to Martin Apel <martin.apel@…>:

That's fine with me, as long as there is a possibility to detect, if two shared_futures point to the same object. Currently there is no such function, so there is no possibility to remove the duplicates before calling wait_for_any.

I understand your concern. I will see what can be done.

comment:4 by viboes, 9 years ago

What would you expect from the following code

int main(int argc, char* argv[])
{
   boost::packaged_task<int> pt(calculate_the_answer_to_life_the_universe_and_everything);
   boost::future<int> fi1 = pt.get_future();

   boost::thread task(boost::move(pt)); // launch task on a thread

   boost::wait_for_any(fi1, fi1);
   std::cout << "Wait for any returned\n";
   return (0);
}

comment:5 by Martin Apel <martin.apel@…>, 9 years ago

Interesting. I see that it's strange to explicitly pass two identical objects in there, but I would still expect it to wait correctly and not to silently hang infinitely. When called with iterators, this becomes more natural, because it's nothing special if a list contains the same item twice.

I would be perfectly happy to avoid this situation, if there only was a possibility to detect his. I have now found a workaround for my application, where I pass additional data and filter out futures based on this additional data. The best approach for me would be, if there was an operator== for shared_future objects, so I can compare, if they point to the same object or not. This would not incur any overhead and still make my use case possible.

comment:6 by viboes, 9 years ago

I have requested some advice to the std-proposal forum and when_all, when_any should work when the futures share the same associated shared state. I will need to rethink the algorithm.

Note: See TracTickets for help on using tickets.