[concurrency-interest] Future.isCompletedNormally Future.isCompletedAbnormally

Martin Buchholz martinrb at google.com
Mon Mar 9 14:31:20 EDT 2015


I just realized to my horror that existing
CompletableFuture.isCompletedExceptionally and
ForkJoinTask.isCompletedAbnormally have (more or less) the same semantics,
and return true on cancellation.
There's no existing method that returns true on abnormal completion but not
on cancellation.

Existing spec for ForkJoinTask states:

The execution status of tasks may be queried at several levels of detail:
isDone()
<https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html#isDone-->
is true if a task completed in any way (including the case where a task was
cancelled without executing); isCompletedNormally()
<https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html#isCompletedNormally-->
is true if a task completed without cancellation or encountering an
exception; isCancelled()
<https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html#isCancelled-->
is true if the task was cancelled (in which case getException()
<https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html#getException-->
returns a CancellationException
<https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CancellationException.html>);
and isCompletedAbnormally()
<https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html#isCompletedAbnormally-->
is true if a task was either cancelled or encountered an exception, in
which case getException()
<https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html#getException-->
will return either the encountered exception or CancellationException
<https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CancellationException.html>.


Can we achieve general consensus that propagating some of these small
convenience methods to more Future implementations is useful?

v 0.2

Index: java/util/concurrent/CompletableFuture.java
===================================================================
RCS file:
/export/home/jsr166/jsr166/jsr166/src/main/java/util/concurrent/CompletableFuture.java,v
retrieving revision 1.158
diff -u -r1.158 CompletableFuture.java
--- java/util/concurrent/CompletableFuture.java    17 Jan 2015 20:05:02
-0000    1.158
+++ java/util/concurrent/CompletableFuture.java    9 Mar 2015 18:12:39 -0000
@@ -2314,6 +2314,29 @@
     }

     /**
+     * Returns {@code true} if this CompletableFuture completed
exceptionally or was cancelled.
+     *
+     * @return {@code true} if this CompletableFuture completed
exceptionally or was cancelled
+     */
+    public final boolean isCompletedAbnormally() {
+        return isCompletedExceptionally();
+    }
+
+    /**
+     * Returns {@code true} if this CompletableFuture completed without
throwing an
+     * exception and was not cancelled.
+     *
+     * @return {@code true} if this CompletableFuture completed without
throwing an
+     * exception and was not cancelled
+     */
+    public final boolean isCompletedNormally() {
+        Object r;
+        return (r = result) != null
+            && (r == NIL
+                || !(r instanceof AltResult));
+    }
+
+    /**
      * Forcibly sets or resets the value subsequently returned by
      * method {@link #get()} and related methods, whether or not
      * already completed. This method is designed for use only in
Index: java/util/concurrent/Future.java
===================================================================
RCS file:
/export/home/jsr166/jsr166/jsr166/src/main/java/util/concurrent/Future.java,v
retrieving revision 1.40
diff -u -r1.40 Future.java
--- java/util/concurrent/Future.java    17 Feb 2015 18:55:39 -0000    1.40
+++ java/util/concurrent/Future.java    9 Mar 2015 18:12:39 -0000
@@ -110,6 +110,74 @@
     boolean isDone();

     /**
+     * Returns {@code true} if this task completed by throwing an
exception or was cancelled.
+     *
+     * @return {@code true} if this task completed by throwing an
exception or was cancelled
+     */
+    default boolean isCompletedAbnormally() {
+        if (isDone()) {
+            if (isCancelled())
+                return true;
+            // Support Future implementations that throw
+            // InterruptedException even when result is available.
+            boolean interrupted = false;
+            try {
+                retry: for (;;) {
+                    try {
+                        get();
+                    } catch (ExecutionException e) {
+                        return true;
+                    } catch (InterruptedException e) {
+                        interrupted = true;
+                        continue retry;
+                    } catch (CancellationException hmmm) {
+                        // Unexpected, given that isCancelled() returned
false
+                    }
+                    break;
+                }
+            } finally {
+                if (interrupted)
+                    Thread.currentThread().interrupt();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if this task completed without throwing an
+     * exception and was not cancelled.
+     *
+     * @return {@code true} if this task completed without throwing an
+     * exception and was not cancelled
+     */
+    default boolean isCompletedNormally() {
+        if (isDone() && !isCancelled()) {
+            // Support Future implementations that throw
+            // InterruptedException even when result is available.
+            boolean interrupted = false;
+            try {
+                retry: for (;;) {
+                    try {
+                        get();
+                        return true;
+                    } catch (ExecutionException e) {
+                    } catch (InterruptedException e) {
+                        interrupted = true;
+                        continue retry;
+                    } catch (CancellationException hmmm) {
+                        // Unexpected, given that isCancelled() returned
false
+                    }
+                    break;
+                }
+            } finally {
+                if (interrupted)
+                    Thread.currentThread().interrupt();
+            }
+        }
+        return false;
+    }
+
+    /**
      * Waits if necessary for the computation to complete, and then
      * retrieves its result.
      *
Index: java/util/concurrent/FutureTask.java
===================================================================
RCS file:
/export/home/jsr166/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java,v
retrieving revision 1.111
diff -u -r1.111 FutureTask.java
--- java/util/concurrent/FutureTask.java    5 Mar 2015 00:32:52 -0000
1.111
+++ java/util/concurrent/FutureTask.java    9 Mar 2015 18:12:39 -0000
@@ -133,6 +133,32 @@
         return state != NEW;
     }

+    /**
+     * Returns {@code true} if this task completed by throwing an
exception or was cancelled.
+     *
+     * @return {@code true} if this task completed by throwing an
exception or was cancelled
+     */
+    public final boolean isCompletedAbnormally() {
+        int s;
+        while ((s = state) == COMPLETING)
+            Thread.yield();
+        return s == EXCEPTIONAL || s >= CANCELLED;
+    }
+
+    /**
+     * Returns {@code true} if this task completed without throwing an
+     * exception and was not cancelled.
+     *
+     * @return {@code true} if this task completed without throwing an
+     * exception and was not cancelled
+     */
+    public final boolean isCompletedNormally() {
+        int s;
+        while ((s = state) == COMPLETING)
+            Thread.yield();
+        return s == NORMAL;
+    }
+
     public boolean cancel(boolean mayInterruptIfRunning) {
         if (!(state == NEW &&
               U.compareAndSwapInt(this, STATE, NEW,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20150309/f6f84913/attachment-0001.html>


More information about the Concurrency-interest mailing list