| 729 | /// will be stored in the result vector alongside successful results. |
| 730 | template <typename T> |
| 731 | Future<std::vector<Result<T>>> All(std::vector<Future<T>> futures) { |
| 732 | struct State { |
| 733 | explicit State(std::vector<Future<T>> f) |
| 734 | : futures(std::move(f)), n_remaining(futures.size()) {} |
| 735 | |
| 736 | std::vector<Future<T>> futures; |
| 737 | std::atomic<size_t> n_remaining; |
| 738 | }; |
| 739 | |
| 740 | if (futures.size() == 0) { |
| 741 | return {std::vector<Result<T>>{}}; |
| 742 | } |
| 743 | |
| 744 | auto state = std::make_shared<State>(std::move(futures)); |
| 745 | |
| 746 | auto out = Future<std::vector<Result<T>>>::Make(); |
| 747 | for (const Future<T>& future : state->futures) { |
| 748 | future.AddCallback([state, out](const Result<T>&) mutable { |
| 749 | if (state->n_remaining.fetch_sub(1) != 1) return; |
| 750 | |
| 751 | std::vector<Result<T>> results(state->futures.size()); |
| 752 | for (size_t i = 0; i < results.size(); ++i) { |
| 753 | results[i] = state->futures[i].result(); |
| 754 | } |
| 755 | out.MarkFinished(std::move(results)); |
| 756 | }); |
| 757 | } |
| 758 | return out; |
| 759 | } |
| 760 | |
| 761 | /// \brief Create a Future which completes when all of `futures` complete. |
| 762 | /// |