CompletableFuture

Remi Forax forax at univ-mlv.fr
Tue Nov 27 14:01:28 PST 2012


On 11/27/2012 06:20 PM, Doug Lea wrote:
>
> This is not part of lambda-libs proper, but is a lambda-dependent
> j.u.c class -- the last item of our jsr166 JDK8 todo list (see JEP155
> http://openjdk.java.net/jeps/155), so it would be great to get
> some preliminary feedback on this here.
>
> Thanks especially to Sam for bugging me to get this going.
>
> This is the class that has variously been called FutureValue,
> SettableFuture, Promise, and other names. Since the focus is
> on possibly-async completions/callbacks, unifying the
> terminology around "complete" gives a big hint about usage.
> In some senses it is the less geeky, more limited, non-FJ variant
> of CountedCompleter (that I confess to loving much more
> but is vastly less obvious to use effectively.)
>
>
>
> /**
>  * A {@link Future} that may be explicitly completed (thus setting its
>  * value and status), and may support dependent CompletableFutures
>  * that trigger upon its completion.
>  */
> public class CompletableFuture<T> implements Future<T> {
>     // yes, a single, concrete class.
>     // todo: wildcards

here is the version with the wildcards :)

>
>     /**
>      * Creates a new incomplete CompletableFuture.
>      */
>     public CompletableFuture();
>
>     /**
>      * If not already completed, sets the value returned by get() and
>      * related methods to the given value.
>      *
>      * @return false if already done.
>      */
>     public boolean complete(T value);
>
>     /**
>      * If not already completed, causes invocations of get() to
>      * throw the given exception.
>      *
>      * @return false if already done.
>      */
>     public boolean completeExceptionally(Throwable ex);
>
>     // cascading completions
>
>     /**
>      * Creates and returns a CompletableFuture that is completed with
>      * the result of the given function of this CompletableFuture's
>      * result if/when this completes normally.
>      *
>      * @return the new CompletableFuture
>      */
>     public <U> CompletableFuture<U> then(Function<? super T,? extends 
> U> fn);
>
>     /**
>      * Creates and Returns a CompletableFuture that is completed with
>      * the result of the given function of this and the other given
>      * CompletableFuture's results if/when both complete normally.
>      *
>      * @return the new CompletableFuture
>      */
>     public <U,V> CompletableFuture<V> and(CompletableFuture<? extends 
> U> x, BiFunction<? super T,? super U,? extends V> fn);
>
>     /**
>      * Creates and returns a CompletableFuture that is completed with
>      * the result of the given function of either this or the other
>      * given CompletableFuture's results if/when either complete
>      * normally.
>      *
>      * @return the new CompletableFuture
>      */
>     public <U> CompletableFuture<U> or(CompletableFuture<? extends T> 
> x, BiFunction<? super T,? super T, ? extends U> fn);
>
>     // terminal completions
>
>     /**
>      * Performs the given action with the result of this
>      * CompletableFuture if/when it completes normally.
>      *
>      * @return this CompletableFuture, for convenience
>      */
>     public CompletableFuture<T> then(Block<? super T> action);

The result should be a Completable<?> not a CompletableFuture<T>, right ?

>
>     /**
>      * Performs the given action with the result of the given function
>      * of this and the other given CompletableFuture's results if/when
>      * both complete normally.
>      *
>      * @return this CompletableFuture, for convenience
>      */
>     public <U> CompletableFuture<T> and(CompletableFuture<? extends U> 
> x, BiBlock<? super T, ? super U> action);

See above.
Also, I think that we decided (correct me if I'm wrong) to not use the 
result type of a lambda to disambiguate overloads,
so completable.and(completable2, (a,b) -> foo(a, b)) is ambiguous.


>
>     /**
>      * Performs the given action with the result of the given function
>      * of either this or the other given CompletableFuture's results
>      * if/when either complete normally.
>      *
>      * @return this CompletableFuture, for convenience
>      */
>     public CompletableFuture<T> or(CompletableFuture<? extends T> x, 
> BiBlock<? super T, ? super T> action);

see above

>
>     /**
>      * Performs the given action with the exception triggering this
>      * CompletableFuture's completion if/when it completes exceptionally.
>      *
>      * @return this CompletableFuture, for convenience
>      */
>     public CompletableFuture<T> exceptionally(Block<Throwable> action);
>
>     // extracting results
>
>     /**
>      * Returns the value when complete, or throws an (unchecked)
>      * exception if completed exceptionally. (The checked exception
>      * variant is available using the timed form of get.)
>      */
>     public T get(); // overrides Future.get to tunnel exceptions
>
>     /**
>      * Returns the value if it is ready, else the given valueIfAbsent.
>      */
>     public T getNow(T valueIfAbsent);

I prefer T getNow(Supplier<? extends T> supplierOfValueIfAbsent);

>
>     // from Future
>     public T get(long timeout, TimeUnit unit)
>         throws InterruptedException, ExecutionException, 
> TimeoutException;
>
>     // misc
>
>     /**
>      * Whether or not already completed, sets the value returned by
>      * subsequent invocations of get() and related methods to the
>      * given value.
>      */
>     public void force(T value);

The semantics of complete and force regarding thread that is already 
waiting on get() is not clear for me.

>
>     public boolean cancel(boolean mayInterruptIfRunning);
>
>     public boolean isCancelled();
>
>     public boolean isDone(); // also alias isComplete?
> }

cheers,
Rémi



More information about the lambda-libs-spec-observers mailing list