in dispenso/detail/future_impl2.h [142:179]
auto whenAllTuple(Invoker& invoker, Futures&&... futures)
-> Future<std::tuple<std::decay_t<Futures>...>> {
using TupleType = std::tuple<std::decay_t<Futures>...>;
using ResultFuture = Future<TupleType>;
// TODO(bbudge): Can write something faster than make_shared using SmallBufferAllocator.
auto shared =
std::make_shared<detail::WhenAllSharedTuple<TupleType>>(std::forward<Futures>(futures)...);
auto whenComplete = [shared]() -> TupleType {
forEach(shared->tuple, [&shared](auto& future) {
if (0 == shared->count.load(std::memory_order_acquire)) {
return false;
}
future.wait();
return true;
});
return std::move(shared->tuple);
};
ResultFuture res(std::move(whenComplete), invoker);
shared->f = std::move(invoker.savedOffFn);
// Avoid sequencing issue by getting the reference prior to the std::move.
auto& tuple = shared->tuple;
forEach(tuple, [shared = std::move(shared)](auto& future) {
future.then(
[shared](auto&&) {
if (shared->count.fetch_sub(1, std::memory_order_release) == 1) {
shared->f();
}
},
kImmediateInvoker);
return true;
});
return res;
}