classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view


Pavel Rappo

Could anybody please explain to me one of the design decisions behind
CompletableFuture.anyOf? Namely an explicit difference between semantics of
`allOf` and `anyOf` methods.

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs):

    "...If no CompletableFutures are provided, returns a CompletableFuture
    completed with the value {@code null}..."

public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs):

    "...If no CompletableFutures are provided, returns an incomplete

I suppose this difference is due to difference in returned values. `allOf` can
safely return CompletableFuture.completedFuture(null) because the result is
always `Void` and it has nothing to do with results of any of the conjuncts.
On the other hand, `anyOf` is bound to return "a new CompletableFuture that is
completed with _the result or exception of any of the given CompletableFutures_
when one completes". Thus if "empty call" would have returned `null` it would
violate its contract. Because no CompletableFuture would have been actually
completed. Moreover we wouldn't be able to distinguish between this and the
situation when chosen disjunct completed with a null result. If my guess is
correct then the design is no doubt very consistent. At the same time, does an
"empty call" (or a call with a possibly zero-length array)


have any value for API clients and not masking a bug? If not, then wouldn't it
be appropriate to have a signature like this:

    CompletableFuture<Void> allOf(CompletableFuture<?> mandatory,
                                  CompletableFuture<?>... optional):

Concurrency-interest mailing list
[hidden email]