in Source/Shared/arcana/threading/task.h [335:385]
inline task<void, ErrorT> when_all(gsl::span<task<void, ErrorT>> tasks)
{
if (tasks.empty())
{
return task_from_result<ErrorT>();
}
struct when_all_data
{
std::mutex mutex;
size_t pendingCount;
ErrorT error;
};
task_completion_source<void, ErrorT> result;
auto data = std::make_shared<when_all_data>();
data->pendingCount = tasks.size();
for (task<void, ErrorT>& task : tasks)
{
task.then(inline_scheduler, cancellation::none(), [data, result](const basic_expected<void, ErrorT>& exp) mutable noexcept(std::is_same<ErrorT, std::error_code>::value) {
bool last = false;
{
std::lock_guard<std::mutex> guard{ data->mutex };
data->pendingCount -= 1;
last = data->pendingCount == 0;
if (exp.has_error() && !data->error)
{
// set the first error, as it might have cascaded
data->error = exp.error();
}
}
if (last) // we were the last task to complete
{
if (data->error)
{
result.complete(make_unexpected(data->error));
}
else
{
result.complete();
}
}
});
}
return result;
}