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: | 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 , 9 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
follow-up: 3 comment:2 by , 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.
comment:3 by , 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 , 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 , 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 , 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.

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.