Class AsyncFut

java.lang.Object
org.ores.async.AsyncFut

public final class AsyncFut extends Object
Promise-returning sibling to Asyncc. Each combinator returns a CompletableFuture instead of taking an error-first final callback — the same vocabulary, the JDK's promise shape.

AsyncFut is implemented in terms of Asyncc (via WrapFuture), so every combinator inherits the v0.2.x concurrency hardening: at-most-once final callback, lost-update-free counters, slot-write-before-counter-increment ordering, no ArrayList resize race, the ParallelLimit <= limit-in-flight invariant, etc. The wrapper layer adds one CompletableFuture allocation per call; use Asyncc directly if you need to shave that ~5 µs.

Task shape

Most combinators take a list (or function) of Suppliers that produce a CompletionStage. The supplier is invoked when the combinator chooses to start that task — this is crucial for Series, ParallelLimit, and Race, where eagerly-started futures would defeat the point. If you already have an in-flight future, wrap it as () -> theFuture.

Quick examples

   // Parallel: fan out N tasks, collect their results
   CompletableFuture<List<String>> both = AsyncFut.Parallel(List.of(
       () -> CompletableFuture.supplyAsync(this::fetchA, exec),
       () -> CompletableFuture.supplyAsync(this::fetchB, exec)
   ));
   both.thenAccept(results -> reply.send(combine(results.get(0), results.get(1))));

   // ParallelLimit: same but with a concurrency cap
   CompletableFuture<List<Path>> downloaded = AsyncFut.ParallelLimit(8, downloads);

   // Series: sequential, collect each result
   CompletableFuture<List<Step>> chain = AsyncFut.Series(List.of(
       () -> validate(req), () -> persist(req), () -> notify(req)
   ));

   // Race: first completer wins
   CompletableFuture<String> winner = AsyncFut.Race(List.of(
       () -> fromPrimary(), () -> fromReplica()
   ));

   // Map: async transform preserving input order
   CompletableFuture<List<Profile>> profiles =
       AsyncFut.Map(userIds, id -> fetchProfileAsync(id));

   // Reduce: sequential fold with an async reducer
   CompletableFuture<BigDecimal> total =
       AsyncFut.Reduce(transactions, BigDecimal.ZERO,
           (acc, txn) -> computeAsync(acc, txn));

   // Times: run the same task N times
   CompletableFuture<List<Sample>> samples =
       AsyncFut.Times(8, i -> generateSampleAsync(i));

   // Each: fire-and-forget per element, complete with Void when all done
   CompletableFuture<Void> sent =
       AsyncFut.Each(users, u -> sendEmailAsync(u));
 

Error semantics

Each combinator's returned future completes exceptionally with the first error any task produces (just like Asyncc's short-circuit). Subsequent task completions are absorbed by the at-most-once guard.

Interop

You can mix Asyncc and AsyncFut freely via WrapFuture:

   // AsyncFut.Parallel inside an Asyncc.Waterfall step:
   Asyncc.Waterfall(List.of(
       c -> c.success(parseRequest(raw)),
       (req, c) -> WrapFuture.fromStage(
               AsyncFut.Parallel(List.of(
                   () -> lookupA(req), () -> lookupB(req)
               ))
           ).run(c)
   ), wrap(finalValue -> reply.send(finalValue)));
 
Since:
0.2.7
See Also: