CompletableFuture
Remi Forax
forax at univ-mlv.fr
Thu Nov 29 06:53:17 PST 2012
On 11/29/2012 01:22 PM, Doug Lea wrote:
> On 11/28/12 15:34, Doug Lea wrote:
>
>> Here's how to make trees/dags:
>>
>> t1 = new CompletableFuture();
>> t2 = t1.then(fun1);
>> t3 = t1.then(fun2);
>> t4 = t2.then(fun3);
>> t5 = new CompletableFuture();
>> t6 = t1.and(t3, fun4);
>
> (typo; should be t6 = t5.and(t3, fun4);
>>
>> This gives you (hoping the ascii-arg makes it through):
>>
>>
>> / -> t2 -> t4
>> t1
>> \ -> t3
>> \
>> t5 -----> & t6
>>
>> Does that help?
>>
>
> Also, here's an update that contains a start on fleshing out some
> of the mechanics and intent, and adds a few things based on
> my own mangling of some suggestions by Chris Poviik (Google).
>
>
> /*
> * Written by Doug Lea with assistance from members of JCP JSR-166
> * Expert Group and released to the public domain, as explained at
> * http://creativecommons.org/publicdomain/zero/1.0/
> */
>
> import java.util.concurrent.Future;
> import java.util.concurrent.TimeUnit;
> import java.util.concurrent.ExecutionException;
> import java.util.concurrent.TimeoutException;
>
> /**
> * A {@link Future} that may be explicitly completed (thus setting its
> * value and status), and may support dependent CompletableFutures
> * that trigger upon its completion.
> *
> * <p>Functions and actions supplied for dependent completions using
> * {@code then}, {@code and}, {@code or}, and {@code exceptionally}
> * are performed by the thread that completes the current
> * CompletableFuture, or by the caller of the method, if already
> * complete.
> *
> * <p> When two or more threads attempt to {@link #complete} or {@link
> * #completeExceptionally} a CompletableFuture, only one of them will
> * succeed. When completion entails computation of a function (or void
> * action), the function is executed <em>after</em> establishing
> * precedence. If this function terminates abruptly with an exception,
> * then method {@code complete} acts as {@code completeExceptionally}
> * with that exception. Method {@link #isCompleting} can be used to
> * determine if a completion function gets "stuck", and method {@link
> * #force} can be used in attempts to recover.
> *
> * <p>This class itself does not provide explicit support for
> * asynchronous execution, but can be used in conjunction with several
> * forms of concurrency. For examples, a new CompletableFuture may be
> * constructed with (a function of) the results of an asynchronous
> * task. Also, a supplied dependent action may itself fork a new task.
> *
> */
> public class CompletableFuture<T> implements Future<T> {
>
> /**
> * Creates a new incomplete CompletableFuture.
> */
> public CompletableFuture();
>
> /**
> * Creates a new CompletableFuture that is completed with the
> * result of the given Future, if/when it completes.
> */
> public CompletableFuture(Future<T> f);
should be CompletableFuture(Future<? extends T> f) because Future as no
set method.
>
> /**
> * Creates a new CompletableFuture that is completed with the
> * result of applying the given function to the result of the
> * given Future, if/when it completes.
> */
> public <U> CompletableFuture(Future<U> f, Function<? super U, T> fn);
again Future<? extends U>.
>
> /**
> * If not already completed, sets the value returned by get() and
> * related methods to the given value.
> *
> * @return true if this invocation of {@code complete} caused
> * this CompletableFuture to transition to a completed state,
> * else false.
> */
> public boolean complete(T value);
>
> /**
> * If not already completed, causes invocations of get() to
> * throw the given exception.
> *
> * @return true if this invocation of {@code
> * completeExceptionally} caused this CompletableFuture to
> * transition to a completed state, else false.
> */
> public boolean completeExceptionally(Throwable ex);
>
> // Cascading functional 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);
Thinking a little more about this one, fn should be a Function not a
BiFunction
given that only one of the two completables needs to complete.
>
> // Action (vs function) forms
>
> /**
> * Creates and returns a CompletableFuture that is completed
> * after performing the given action with the result of this
> * CompletableFuture if/when it completes normally.
> *
> * @return the new CompletableFuture
> */
> public CompletableFuture<Void> then(Block<? super T> action);
>
> /**
> * Creates and returns a CompletableFuture that is completed
> * after performing 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 the new CompletableFuture
> */
> public <U> CompletableFuture<Void> and(CompletableFuture<? extends
> U> x,
> BiBlock<? super T, ? super
> U> action);
I think that CompletableFuture<?> is better as return type than
CompletableFuture<Void>
otherwise users may want to declare a local variable Void.
> /**
> * Creates and returns a CompletableFuture that is completed
> * after performing the given action with the result of either
> * this or the other given CompletableFuture's results if/when
> * either complete normally.
> *
> * @return the new CompletableFuture
> */
> public CompletableFuture<Void> or(CompletableFuture<? extends T> x,
> BiBlock<? super T, ? super T>
> action);
see above.
>
> /**
> * Creates and returns a CompletableFuture that is completed after
> * performing the given action with the exception triggering this
> * CompletableFuture's completion if/when it completes
> * exceptionally.
> *
> * @return the new CompletableFuture
> */
> public CompletableFuture<Void> exceptionally(Block<Throwable>
> action);
see above.
>
> // 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();
>
> /**
> * Returns the value if completed, else the given valueIfAbsent.
> */
> public T getNow(T valueIfAbsent);
still think it should use a supplier as parameter and not the value.
>
> /**
> * Waits if necessary for at most the given time for the computation
> * to complete, and then retrieves its result, if available.
> *
> * @param timeout the maximum time to wait
> * @param unit the time unit of the timeout argument
> * @return the computed result
> * @throws CancellationException if the computation was cancelled
> * @throws ExecutionException if the computation threw an
> * exception
> * @throws InterruptedException if the current thread was interrupted
> * while waiting
> * @throws TimeoutException if the wait timed out
> */
> T get(long timeout, TimeUnit unit)
> throws InterruptedException, ExecutionException,
> TimeoutException;
>
> // misc
>
> /**
> * Whether or not already completed, sets the value subsequently
> * returned by method get() and related methods to the given
> * value. This method is designed primarily for use in recovery
> * actions.
> *
> * @param value the completion value
> */
> public void force(T value);
>
> /**
> * Returns true if this CompletableFuture is in the process of
> * completing but has not yet completed. This method is designed
> * to help diagnose cases in which supplied completion functions
> * become "stuck" in the process of completion.
> */
> public boolean isCompleting();
>
> /**
> * Attempts to cancel further processing of this task. This
> * attempt will fail if already completed. If successful,
> * subsequent calls to {@link #isCancelled}, {@link #isDone}, and
> * {@code cancel} will return {@code true} and calls to {@link
> * #get} and related methods will result in {@code
> * CancellationException}.
> *
> * @param mayInterruptIfRunning this value has no effect in the
> * default implementation because interrupts are not used to
> * control processing.
> *
> * @return {@code true} if this task is now cancelled
> */
> public boolean cancel(boolean mayInterruptIfRunning);
>
> /**
> * Returns {@code true} if this CompletableFuture was cancelled
> * before it completed normally.
> *
> * @return {@code true} if this CompletableFuture was cancelled
> * before it completed normally
> */
> public boolean isCancelled();
>
> /**
> * Returns {@code true} if completed in any fashion: normally,
> * exceptionally, or cancellation.
> *
> * @return {@code true} if completed
> */
> public boolean isDone();
> }
>
Rémi
More information about the lambda-libs-spec-observers
mailing list