[concurrency-interest] We need to add blocking methods to CompletionStage!

Doug Lea dl at cs.oswego.edu
Sun Sep 25 08:03:40 EDT 2016


Thanks to Martin for trying to clarify disagreements about and
possible improvements to CompletableFuture and CompletionStage APIs.
A few notes:

The main issue continues to be: what would you like clients to be able
to do with a CompletableFuture returned to them.  This is reminiscent
of Collections APIs: is it OK for clients to add or remove items in a
collection passed or returned to them? In some cases, the consequences
of nonsensical modifications are no different in scope than other
usage errors, so the issue amounts to API usage guidance.  But
sometimes you need to prevent modifications. In which case, similar
answers apply for collections and completions (although it is not a
perfect analogy because you cannot sidestep issues using only pure
ImmutableCompletions -- someone needs to complete them).

1.  Producers can let clients do anything if the clients only modify a
copy. Unlike some Collections, "defensive copying" CompletableFutures
is fairly cheap, so is usually a good solution. Similarly, clients
should be able to easily make a copy themselves if they are in doubt
about for example upstream effects of calling cancel(). We now know
that copy() should have been in jdk8 (as it now is in jdk9) rather
than forcing people to do this via thenApply(x->x), which made the
defensive copying approach underused.

2. Alternatively, producers can return a type that does not allow some
operations.  Method minimalCompletionStage is analogous to Collections
unmodifiableCollection, but to some people, too minimal. Even joining
and status checks can lead to deadlocks and livelocks that some
producers want to make impossible to encounter without explicit client
action. Introducing only CompletionStage/minimalCompletionStage might
not have been the best approach, because further extending this
strategy leads to further controversy choosing among the many
plausible intermediary points of sets of methods to expose between
CompletionStage and CompletableFuture. But if we were to pick one, we
might consider something along the lines suggested by Kasper and
Viktor of
   interface FutureCompletion extends CompletionStage, Future {}
This allows joins and queries, but also raises the policy question of
whether cancel() should only cancel a copy or the source.


Separately, we also now know that it was uselessly mean-spirited to
allow CompletionStage.toCompletableFuture to throw UOE, since any
client can awkwardly emulate this using whenComplete.  I'm not sure
whether was can compatibly revise to disallow UOE and also
default-implement it.

-Doug



More information about the Concurrency-interest mailing list