From ba2432f8fe57181238cca97fd16742fa0fa98625 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 16 Jun 2025 18:51:59 +0200 Subject: [PATCH] libutil: add asyncJoin, a Result-based joinPromises we'll need this to asyncify withFramedSink and remove its thread pool. Change-Id: I1a099392c094f8441482fde3b2d3843931420ffa --- lix/libutil/async-collect.hh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lix/libutil/async-collect.hh b/lix/libutil/async-collect.hh index 3cf8a3e8a..76859a10f 100644 --- a/lix/libutil/async-collect.hh +++ b/lix/libutil/async-collect.hh @@ -136,4 +136,23 @@ kj::Promise> asyncSpread(Input && input, Fn fn) co_return result::success(); } +/** + * Run `promises` concurrently until they've all succeeded, or pass on + * the error returned by the first failing promise. This is similar to + * `kj::joinPromisesFailFast()`, but not limited to thrown exceptions. + */ +template +kj::Promise> asyncJoin(Promises &&... promises) + requires(std::same_as>> && ...) +{ + auto collect = + asyncCollect(kj::arr(std::pair{std::tuple{}, std::forward(promises)}...)); + while (auto r = co_await collect.next()) { + if (!r->second.has_value()) { + co_return std::move(r->second); + } + } + + co_return result::success(); +} }