[concurrency-interest] Layered exception handling with CompletableFuture

Kasper Nielsen kasperni at gmail.com
Sun Aug 31 03:14:15 EDT 2014


Sorry for hijacking this thread. But if additional functionality for
CompletableFuture is on the table. I have a couple of requests, some of
them just syntactically sugar.

1)
A simple way to create an immutable CompletionStage from a CompletionFuture.
Right now if I have something like like this
class ProvidedToUsers {
    CompletionFuture f;
    CompletionStage doAsyncStuff() {
        return f;
    }
}
Any client can just do:
xx.doAsyncStuff().toCompletionFuture().cancel();

Right now I'm using this to make an "immutable" future:

CompletableFuture<Void> cf = new CompletableFuture<>();
f.handle((a, b) -> {
    if (b == null) {
        cf.complete(null);
    } else {
        cf.completeExceptionally(b);
    }
    return null;
});
return cf;


2)
An easy way to create a CompletableFuture that is exceptionally completed:

return CompletableFuture.completedExceptionally(throwable);

is better than:

CompletableFuture<T> cf = new CompletableFuture<>();
cf.completeExceptionally(throwable);
return cf;

3)
An easy way to get the exceptional cause from a CompletableFuture, right
now I'm using this

if (cf.isCompletedExceptionally()) {
    try {
        cf.getNow(null);
    } catch (CancellationException e) {
        return e;
    } catch (CompletionException e) {
        return e.getCause();
    }
}
return null;

4)
With regards to async-io completions I'm using the following piece of code
to make completable futures that timeout at some point.

public static <T> CompletableFuture<T> timeout(CompletableFuture<T>
delegate, ScheduledExecutorService ses,
        long timeout, TimeUnit unit) {
    CompletableFuture<T> cf = new CompletableFuture<>();
    Future<?> f;
    try {
        f = ses.schedule(new Runnable() {
            public void run() {
                if (!delegate.isDone()) {
                    cf.completeExceptionally(new TimeoutException("Timed
out after " + timeout + " "
                            + unit.toString().toLowerCase()));
                }
            }
        }, timeout, unit);
    } catch (RejectedExecutionException e) {
        // Unfortunately TimeoutException does not allow exceptions in its
constructor
        cf.completeExceptionally(new RuntimeException("Could not schedule
timeout task, ", e));
        return cf;
    }
    delegate.handle(new BiFunction<T, Throwable, Void>() {
        public Void apply(T t, Throwable throwable) {
            // Users must manually purge if many outstanding tasks
            f.cancel(false);
            if (throwable != null) {
                cf.completeExceptionally(throwable);
            } else {
                cf.complete(t);
            }
            return null;
        }
    });
    return cf;
}

Something similar might be nice to add to CompletableFuture.

5)
Not related to CompletableFuture, but could CancellationException and
TimeoutException get constructors that also takes a
Throwable.

Cheers
  Kasper

On Sat, Aug 30, 2014 at 4:51 PM, Doug Lea <dl at cs.oswego.edu> wrote:

>
> It is easy to define utilities automating common use cases, including
> simple periodic suppliers (via a common ScheduledExecutor), and
> async-io completions (via adaptors from nio CompletionHandler).
>
> -Doug
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20140831/cfc304c6/attachment.html>


More information about the Concurrency-interest mailing list