Candidate jdk9 CompletableFuture additions

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Candidate jdk9 CompletableFuture additions

Doug Lea

First among planned jdk9 changes are tentative additions to
CompletableFuture aimed to address suggestions and complaints upon
discovering that it is being used a lot more than we anticipated.
Comments on these would be welcome. Three categories:

1. Delays and timeouts. People need these all the time, but they are a
nuisance to do yourself. Method orTimeout(time, unit) covers the most
common timeout idiom. Method delayedExecutor(delay, unit, executor)
provides a one-shot delegated executor that waits out delay before
submitting.

2. During (and after) jdk8 discussions, there was a lot of
disagreement about what methods to expose in class CompletableFuture
and interface CompletionStage. The result was to make
CompletableFuture "maximal" and CompletionStage "minimal".  But we
didn't provide any reasonable way to provide any in-between forms via
subclassing. Added methods (mainly, a "virtual constructor") make this
easy.

3. A few common utilities were missing and either painful or
non-obvious to implement. Including "defensive copy" methods
and a static method to return a failed (exceptionally completed)
future.

See javadoc at
http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java/util/concurrent/CompletableFuture.html
Including some new guidance in class-level docs. Here's a paste of
added method javadocs:



     public <U> CompletableFuture<U> newIncompleteFuture()
     Creates a new incomplete CompletableFuture of the type to be returned by a
CompletionStage method. Subclasses should normally override this method to
return an instance of the same class as this CompletableFuture. The default
implementation returns an instance of class CompletableFuture.

     public Executor defaultExecutor()
     Returns the default Executor used for async methods that do not specify an
Executor. This class uses the ForkJoinPool.commonPool(), but may be overridden
in subclasses with an Executor that provides at least one independent thread.

     public CompletableFuture<T> copy()
     Returns a new CompletableFuture that is completed normally with the same
value as this Completablefuture when it completes normally. If this
CompletableFuture completes exceptionally, then the returned CompletableFuture
completes exceptionally with a CompletionException with this exception as cause.
The behavior equivalent is to thenApply(x -> x). This method may be useful as a
form of "defensive copying", to prevent clients from completing, while still
being able to arrange dependent actions.

     public CompletionStage<T> minimalCompletionStage()
     Returns a new CompletionStage that is completed normally with the same
value as this Completablefuture when it completes normally, and cannot be
independently completed or otherwise used in ways not defined by the methods of
interface CompletionStage. If this CompletableFuture completes exceptionally,
then the returned CompletionStage completes exceptionally with a
CompletionException with this exception as cause.

     public CompletableFuture<T> completeAsync(Supplier<T> supplier,
                                               Executor executor)
     Completes this CompletableFuture with the result of the given Supplier
function invoked from an asynchronous task using the given executor.

     public CompletableFuture<T> completeAsync(Supplier<T> supplier)
     Completes this CompletableFuture with the result of the given Supplier
function invoked from an asynchronous task using the the default executor.

     public CompletableFuture<T> orTimeout(long timeout,
                                           TimeUnit unit)

     Exceptionally completes this CompletableFuture with a TimeoutException if
not otherwise completed before the given timeout.
     public static Executor delayedExecutor(long delay,
                                            TimeUnit unit,
                                            Executor executor)

     Returns a new Executor that submits a task to the given base executor after
the given delay.
     public static Executor delayedExecutor(long delay,
                                            TimeUnit unit)

     Returns a new Executor that submits a task to the default executor after
the given delay.

     public static <U> CompletionStage<U> completedStage(U value)
     Returns a new CompletionStage that is already completed with the given
value and supports only those methods in interface CompletionStage.

     public static <U> CompletableFuture<U> failedFuture(Throwable ex)
     Returns a new CompletableFuture that is already completed exceptionally
with the given exception.


     public static <U> CompletableFuture<U> failedStage(Throwable ex)
     Returns a new CompletionStage that is already completed exceptionally with
the given exception and supports only those methods in interface CompletionStage.

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: [Spam]: Candidate jdk9 CompletableFuture additions

Millies, Sebastian
-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of Doug Lea
Sent: Wednesday, January 14, 2015 6:10 PM
To: [hidden email]
Subject: [Spam]: [concurrency-interest] Candidate jdk9 CompletableFuture additions

> Method orTimeout(time, unit) covers the most common timeout idiom
>     public CompletableFuture<T> orTimeout(long timeout,
>                                           TimeUnit unit)
>
>     Exceptionally completes this CompletableFuture with a TimeoutException if
>not otherwise completed before the given timeout.

I'd appreciate a method like orTimeout(defaultValue, time, unit), which completes normally with the given default value if not otherwise completed before the given timeout. (I would have expected this use case to be at least as completing exceptionally.)

-- Sebastian

Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt, Germany – Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Candidate jdk9 CompletableFuture additions

Doug Lea
On 01/14/2015 12:36 PM, Millies, Sebastian wrote:

> I'd appreciate a method like orTimeout(defaultValue, time, unit),

Yes; thanks. To be a little more consistent with naming...

     /**
      * Completes this CompletableFuture with the given value if not
      * otherwise completed before the given timeout.
      *
      * @param value the value to use upon timeout
      * @param timeout how long to wait before completing.
      * @param unit a {@code TimeUnit} determining how to interpret the
      *        {@code timeout} parameter
      * @return this CompletableFuture
      * @since 1.9
      */
     public CompletableFuture<T> completeOnTimeout(T value, long timeout,
                                                   TimeUnit unit)

-Doug


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Candidate jdk9 CompletableFuture additions

Remi Forax
In reply to this post by Doug Lea
The Supplier of completeAsync() should be a Supplier<? extends T>
(and yes, supplyAsync() should also take a Supplier<? extends T> but
it's too late).

cheers,
Rémi

On 01/14/2015 06:09 PM, Doug Lea wrote:

>
> First among planned jdk9 changes are tentative additions to
> CompletableFuture aimed to address suggestions and complaints upon
> discovering that it is being used a lot more than we anticipated.
> Comments on these would be welcome. Three categories:
>
> 1. Delays and timeouts. People need these all the time, but they are a
> nuisance to do yourself. Method orTimeout(time, unit) covers the most
> common timeout idiom. Method delayedExecutor(delay, unit, executor)
> provides a one-shot delegated executor that waits out delay before
> submitting.
>
> 2. During (and after) jdk8 discussions, there was a lot of
> disagreement about what methods to expose in class CompletableFuture
> and interface CompletionStage. The result was to make
> CompletableFuture "maximal" and CompletionStage "minimal".  But we
> didn't provide any reasonable way to provide any in-between forms via
> subclassing. Added methods (mainly, a "virtual constructor") make this
> easy.
>
> 3. A few common utilities were missing and either painful or
> non-obvious to implement. Including "defensive copy" methods
> and a static method to return a failed (exceptionally completed)
> future.
>
> See javadoc at
> http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java/util/concurrent/CompletableFuture.html
> Including some new guidance in class-level docs. Here's a paste of
> added method javadocs:
>
>
>
>     public <U> CompletableFuture<U> newIncompleteFuture()
>     Creates a new incomplete CompletableFuture of the type to be
> returned by a CompletionStage method. Subclasses should normally
> override this method to return an instance of the same class as this
> CompletableFuture. The default implementation returns an instance of
> class CompletableFuture.
>
>     public Executor defaultExecutor()
>     Returns the default Executor used for async methods that do not
> specify an Executor. This class uses the ForkJoinPool.commonPool(),
> but may be overridden in subclasses with an Executor that provides at
> least one independent thread.
>
>     public CompletableFuture<T> copy()
>     Returns a new CompletableFuture that is completed normally with
> the same value as this Completablefuture when it completes normally.
> If this CompletableFuture completes exceptionally, then the returned
> CompletableFuture completes exceptionally with a CompletionException
> with this exception as cause. The behavior equivalent is to
> thenApply(x -> x). This method may be useful as a form of "defensive
> copying", to prevent clients from completing, while still being able
> to arrange dependent actions.
>
>     public CompletionStage<T> minimalCompletionStage()
>     Returns a new CompletionStage that is completed normally with the
> same value as this Completablefuture when it completes normally, and
> cannot be independently completed or otherwise used in ways not
> defined by the methods of interface CompletionStage. If this
> CompletableFuture completes exceptionally, then the returned
> CompletionStage completes exceptionally with a CompletionException
> with this exception as cause.
>
>     public CompletableFuture<T> completeAsync(Supplier<T> supplier,
>                                               Executor executor)
>     Completes this CompletableFuture with the result of the given
> Supplier function invoked from an asynchronous task using the given
> executor.
>
>     public CompletableFuture<T> completeAsync(Supplier<T> supplier)
>     Completes this CompletableFuture with the result of the given
> Supplier function invoked from an asynchronous task using the the
> default executor.
>
>     public CompletableFuture<T> orTimeout(long timeout,
>                                           TimeUnit unit)
>
>     Exceptionally completes this CompletableFuture with a
> TimeoutException if not otherwise completed before the given timeout.
>     public static Executor delayedExecutor(long delay,
>                                            TimeUnit unit,
>                                            Executor executor)
>
>     Returns a new Executor that submits a task to the given base
> executor after the given delay.
>     public static Executor delayedExecutor(long delay,
>                                            TimeUnit unit)
>
>     Returns a new Executor that submits a task to the default executor
> after the given delay.
>
>     public static <U> CompletionStage<U> completedStage(U value)
>     Returns a new CompletionStage that is already completed with the
> given value and supports only those methods in interface CompletionStage.
>
>     public static <U> CompletableFuture<U> failedFuture(Throwable ex)
>     Returns a new CompletableFuture that is already completed
> exceptionally with the given exception.
>
>
>     public static <U> CompletableFuture<U> failedStage(Throwable ex)
>     Returns a new CompletionStage that is already completed
> exceptionally with the given exception and supports only those methods
> in interface CompletionStage.
>
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Candidate jdk9 CompletableFuture additions

Martin Buchholz-3
In reply to this post by Doug Lea
Does delayedExecutor belong in Executors.java?

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Candidate jdk9 CompletableFuture additions

Kasper Nielsen-4
In reply to this post by Doug Lea

    public static <U> CompletionStage<U> completedStage(U value)
    Returns a new CompletionStage that is already completed with the given value and supports only those methods in interface CompletionStage.

    public static <U> CompletableFuture<U> failedStage(Throwable ex)
    Returns a new CompletionStage that is already completed exceptionally with the given exception and supports only those methods in interface CompletionStage.

I think it makes more sense to have these methods on CompletionStage instead of CompletionFuture?
Also shouldn't failedStage return a CompletionStage?

- Kasper


 
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Candidate jdk9 CompletableFuture additions

Doug Lea
In reply to this post by Remi Forax
Note: Anyone feeling brave can run snapshots on jdk8+ by getting
http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166.jar
and running java -Xbootclasspath/p:jsr166.jar

On 01/14/2015 02:26 PM, Remi Forax wrote:
> The Supplier of completeAsync() should be a Supplier<? extends T>

Thanks! fixed.

On 01/14/2015 05:12 PM, Kasper Nielsen wrote:
> public static <U> CompletionStage<U> completedStage(U value)
> public static <U> CompletableFuture<U> failedStage(Throwable ex)

> I think it makes more sense to have these methods on CompletionStage instead
> of CompletionFuture?

It would, but static methods are not allowed in interfaces.

> Also shouldn't failedStage return a CompletionStage?

Yes; thanks! Fixed.

On 01/14/2015 04:41 PM, Martin Buchholz wrote:
> Does delayedExecutor belong in Executors.java?

I considered doing this more generally in Executors.
But the scheme here relies on using the 1-thread
ScheduledThreadPoolExecutor only for triggering, cancelling,
and completing (but never running) tasks, so even if an
Executors version were available, we'd probably still use
a customized form here.

-Doug
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Candidate jdk9 CompletableFuture additions

Kasper Nielsen-4
On 01/14/2015 05:12 PM, Kasper Nielsen wrote:
public static <U> CompletionStage<U> completedStage(U value)
public static <U> CompletableFuture<U> failedStage(Throwable ex)

I think it makes more sense to have these methods on CompletionStage instead
of CompletionFuture?

It would, but static methods are not allowed in interfaces.

Since Java 8 they are.

- Kasper 

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Candidate jdk9 CompletableFuture additions

Doug Lea
On 01/15/2015 04:01 AM, Kasper Nielsen wrote:

>     On 01/14/2015 05:12 PM, Kasper Nielsen wrote:
>
>         public static <U> CompletionStage<U> completedStage(U value)
>         public static <U> CompletionStage<U> failedStage(Throwable ex)>
>
>         I think it makes more sense to have these methods on CompletionStage instead
>         of CompletionFuture?
>
>
>     It would, but static methods are not allowed in interfaces.
>
>
> Since Java 8 they are.
>

Right; thanks. I'm wavering about whether we want to do this here though.
Keeping CompletionStage all-abstract and CompletableFuture all-concrete
seems mildly preferable. But other opinions would be welcome.

-Doug


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Candidate jdk9 CompletableFuture additions

Viktor Klang

Keeping the interfaces as untangled as possible would be nice IMO

--
Cheers,

On 15 Jan 2015 21:12, "Doug Lea" <[hidden email]> wrote:
On 01/15/2015 04:01 AM, Kasper Nielsen wrote:
    On 01/14/2015 05:12 PM, Kasper Nielsen wrote:

        public static <U> CompletionStage<U> completedStage(U value)
        public static <U> CompletionStage<U> failedStage(Throwable ex)>

        I think it makes more sense to have these methods on CompletionStage instead
        of CompletionFuture?


    It would, but static methods are not allowed in interfaces.


Since Java 8 they are.


Right; thanks. I'm wavering about whether we want to do this here though.
Keeping CompletionStage all-abstract and CompletableFuture all-concrete
seems mildly preferable. But other opinions would be welcome.

-Doug


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest