| 235 | } |
| 236 | |
| 237 | Future<> AllComplete(const std::vector<Future<>>& futures) { |
| 238 | struct State { |
| 239 | explicit State(int64_t n_futures) : mutex(), n_remaining(n_futures) {} |
| 240 | |
| 241 | std::mutex mutex; |
| 242 | std::atomic<size_t> n_remaining; |
| 243 | }; |
| 244 | |
| 245 | if (futures.empty()) { |
| 246 | return Future<>::MakeFinished(); |
| 247 | } |
| 248 | |
| 249 | auto state = std::make_shared<State>(futures.size()); |
| 250 | auto out = Future<>::Make(); |
| 251 | for (const auto& future : futures) { |
| 252 | future.AddCallback([state, out](const Status& status) mutable { |
| 253 | if (!status.ok()) { |
| 254 | std::unique_lock<std::mutex> lock(state->mutex); |
| 255 | if (!out.is_finished()) { |
| 256 | out.MarkFinished(status); |
| 257 | } |
| 258 | return; |
| 259 | } |
| 260 | if (state->n_remaining.fetch_sub(1) != 1) return; |
| 261 | out.MarkFinished(); |
| 262 | }); |
| 263 | } |
| 264 | return out; |
| 265 | } |
| 266 | |
| 267 | Future<> AllFinished(const std::vector<Future<>>& futures) { |
| 268 | return All(futures).Then([](const std::vector<Result<internal::Empty>>& results) { |