inline task when_all()

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;
    }