completeOnTimeout
+ (T value, long timeout, TimeUnit unit) {
+ throw new UnsupportedOperationException(); }
+ }
+
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long RESULT;
private static final long STACK;
private static final long NEXT;
static {
try {
- final sun.misc.Unsafe u;
- UNSAFE = u = sun.misc.Unsafe.getUnsafe();
- Class> k = CompletableFuture.class;
- RESULT = u.objectFieldOffset(k.getDeclaredField("result"));
- STACK = u.objectFieldOffset(k.getDeclaredField("stack"));
- NEXT = u.objectFieldOffset
+ RESULT = U.objectFieldOffset
+ (CompletableFuture.class.getDeclaredField("result"));
+ STACK = U.objectFieldOffset
+ (CompletableFuture.class.getDeclaredField("stack"));
+ NEXT = U.objectFieldOffset
(Completion.class.getDeclaredField("next"));
- } catch (Exception x) {
- throw new Error(x);
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class> ensureLoaded = LockSupport.class;
}
}
diff -r ea54ac8672e7 -r e5e5ab01398e jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java Wed Oct 14 00:08:42 2015 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java Tue Oct 13 16:04:56 2015 -0700
@@ -34,12 +34,11 @@
*/
package java.util.concurrent;
-import java.util.function.Supplier;
-import java.util.function.Consumer;
+
import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
import java.util.function.Function;
-import java.util.function.BiFunction;
-import java.util.concurrent.Executor;
/**
* A stage of a possibly asynchronous computation, that performs an
@@ -56,9 +55,9 @@
* For example, {@code stage.thenApply(x -> square(x)).thenAccept(x ->
* System.out.print(x)).thenRun(() -> System.out.println())}. An
* additional form (compose) applies functions of stages
- * themselves, rather than their results.
+ * themselves, rather than their results.
*
- * One stage's execution may be triggered by completion of a
+ * One stage's execution may be triggered by completion of a
* single stage, or both of two stages, or either of two stages.
* Dependencies on a single stage are arranged using methods with
* prefix then. Those triggered by completion of
@@ -66,9 +65,9 @@
* effects, using correspondingly named methods. Those triggered by
* either of two stages make no guarantees about which of the
* results or effects are used for the dependent stage's
- * computation.
+ * computation.
*
- * Dependencies among stages control the triggering of
+ * Dependencies among stages control the triggering of
* computations, but do not otherwise guarantee any particular
* ordering. Additionally, execution of a new stage's computations may
* be arranged in any of three ways: default execution, default
@@ -81,7 +80,7 @@
* properties, and might not even support concurrent execution, but
* are arranged for processing in a way that accommodates asynchrony.
*
- * Two method forms support processing whether the triggering
+ * Two method forms support processing whether the triggering
* stage completed normally or exceptionally: Method {@link
* #whenComplete whenComplete} allows injection of an action
* regardless of outcome, otherwise preserving the outcome in its
@@ -100,7 +99,7 @@
* stage completes normally or exceptionally. In the case of method
* {@code whenComplete}, when the supplied action itself encounters an
* exception, then the stage exceptionally completes with this
- * exception if not already completed exceptionally.
+ * exception if not already completed exceptionally.
*
*
*
@@ -587,7 +586,7 @@
/**
* Returns a new CompletionStage that, when this stage completes
- * normally, is executed with this stage as the argument
+ * normally, is executed with this stage's result as the argument
* to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
@@ -603,7 +602,7 @@
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed using this stage's default asynchronous
- * execution facility, with this stage as the argument to the
+ * execution facility, with this stage's result as the argument to the
* supplied function.
*
* See the {@link CompletionStage} documentation for rules
@@ -652,12 +651,14 @@
* Returns a new CompletionStage with the same result or exception as
* this stage, that executes the given action when this stage completes.
*
- * When this stage is complete, the given action is invoked with the
- * result (or {@code null} if none) and the exception (or {@code null}
- * if none) of this stage as arguments. The returned stage is completed
- * when the action returns. If the supplied action itself encounters an
- * exception, then the returned stage exceptionally completes with this
- * exception unless this stage also completed exceptionally.
+ *
When this stage is complete, the given action is invoked
+ * with the result (or {@code null} if none) and the exception (or
+ * {@code null} if none) of this stage as arguments. The returned
+ * stage is completed when the action returns. If the supplied
+ * action itself encounters an exception, then the returned stage
+ * exceptionally completes with this exception unless this stage
+ * also completed exceptionally (in which case, the returned stage
+ * exceptionally completes with the original exception).
*
* @param action the action to perform
* @return the new CompletionStage
diff -r ea54ac8672e7 -r e5e5ab01398e jdk/test/java/util/concurrent/CompletableFuture/Basic.java
--- a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java Wed Oct 14 00:08:42 2015 +0200
+++ b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java Tue Oct 13 16:04:56 2015 -0700
@@ -53,7 +53,6 @@
import static java.util.concurrent.ForkJoinPool.*;
import java.util.concurrent.atomic.AtomicInteger;
-
public class Basic {
static void checkCompletedNormally(CompletableFuture> cf, Object value) {
@@ -66,6 +65,7 @@
try { equalAnyOf(cf.get(), values); } catch (Throwable x) { unexpected(x); }
try { equalAnyOf(cf.get(0L, SECONDS), values); } catch (Throwable x) { unexpected(x); }
check(cf.isDone(), "Expected isDone to be true, got:" + cf);
+ check(!cf.isCompletedExceptionally(), "Expected isCompletedExceptionally to return false");
check(!cf.isCancelled(), "Expected isCancelled to be false");
check(!cf.cancel(true), "Expected cancel to return false");
check(cf.toString().contains("[Completed normally]"));
@@ -97,6 +97,7 @@
catch (CancellationException x) { if (cancelled) pass(); else fail(); }
catch (ExecutionException x) { if (cancelled) check(x.getCause() instanceof CancellationException); else pass(); }
check(cf.isDone(), "Expected isDone to be true, got:" + cf);
+ check(cf.isCompletedExceptionally(), "Expected isCompletedExceptionally");
check(cf.isCancelled() == cancelled, "Expected isCancelled: " + cancelled + ", got:" + cf.isCancelled());
check(cf.cancel(true) == cancelled, "Expected cancel: " + cancelled + ", got:" + cf.cancel(true));
check(cf.toString().contains("[Completed exceptionally]")); // ## TODO: 'E'xceptionally
@@ -805,6 +806,49 @@
cf2 = cf1.handle((x,t) -> { check(t.getCause() == ex); return 2;});
checkCompletedExceptionally(cf1);
checkCompletedNormally(cf2, 2);
+
+ cf1 = supplyAsync(() -> 1);
+ cf2 = cf1.handleAsync((x,t) -> x+1);
+ checkCompletedNormally(cf1, 1);
+ checkCompletedNormally(cf2, 2);
+
+ cf1 = supplyAsync(() -> { throw ex; });
+ cf2 = cf1.handleAsync((x,t) -> { check(t.getCause() == ex); return 2;});
+ checkCompletedExceptionally(cf1);
+ checkCompletedNormally(cf2, 2);
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // whenComplete tests
+ //----------------------------------------------------------------
+ try {
+ AtomicInteger count = new AtomicInteger();
+ CompletableFuture cf2;
+ CompletableFuture cf1 = supplyAsync(() -> 1);
+ cf2 = cf1.whenComplete((x,t) -> count.getAndIncrement());
+ checkCompletedNormally(cf1, 1);
+ checkCompletedNormally(cf2, 1);
+ check(count.get() == 1, "action count should be incremented");
+
+ final RuntimeException ex = new RuntimeException();
+ cf1 = supplyAsync(() -> { throw ex; });
+ cf2 = cf1.whenComplete((x,t) -> count.getAndIncrement());
+ checkCompletedExceptionally(cf1);
+ checkCompletedExceptionally(cf2);
+ check(count.get() == 2, "action count should be incremented");
+
+ cf1 = supplyAsync(() -> 1);
+ cf2 = cf1.whenCompleteAsync((x,t) -> count.getAndIncrement());
+ checkCompletedNormally(cf1, 1);
+ checkCompletedNormally(cf2, 1);
+ check(count.get() == 3, "action count should be incremented");
+
+ cf1 = supplyAsync(() -> { throw ex; });
+ cf2 = cf1.whenCompleteAsync((x,t) -> count.getAndIncrement());
+ checkCompletedExceptionally(cf1);
+ checkCompletedExceptionally(cf2);
+ check(count.get() == 4, "action count should be incremented");
+
} catch (Throwable t) { unexpected(t); }
}
diff -r ea54ac8672e7 -r e5e5ab01398e jdk/test/java/util/concurrent/CompletableFuture/ThenComposeAsyncTest.java
--- a/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeAsyncTest.java Wed Oct 14 00:08:42 2015 +0200
+++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeAsyncTest.java Tue Oct 13 16:04:56 2015 -0700
@@ -27,7 +27,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
-
/**
* @test
* @bug 8029164
diff -r ea54ac8672e7 -r e5e5ab01398e jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java
--- a/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Wed Oct 14 00:08:42 2015 +0200
+++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Tue Oct 13 16:04:56 2015 -0700
@@ -33,7 +33,6 @@
import java.util.function.BiFunction;
import java.util.function.Consumer;
-
/**
* @test
* @bug 8068432 8072030