8211283: Miscellaneous changes imported from jsr166 CVS 2018-11
Reviewed-by: martin, chegar
--- a/src/java.base/share/classes/java/util/ArrayDeque.java Wed Nov 28 15:25:14 2018 -0800
+++ b/src/java.base/share/classes/java/util/ArrayDeque.java Wed Nov 28 15:25:14 2018 -0800
@@ -37,7 +37,6 @@
import java.io.Serializable;
import java.util.function.Consumer;
import java.util.function.Predicate;
-
import jdk.internal.access.SharedSecrets;
/**
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Wed Nov 28 15:25:14 2018 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Wed Nov 28 15:25:14 2018 -0800
@@ -2542,6 +2542,8 @@
setTabAt(tab, i, fwd);
advance = true;
}
+ else if (f instanceof ReservationNode)
+ throw new IllegalStateException("Recursive update");
}
}
}
--- a/src/java.base/share/classes/java/util/concurrent/Exchanger.java Wed Nov 28 15:25:14 2018 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/Exchanger.java Wed Nov 28 15:25:14 2018 -0800
@@ -564,8 +564,8 @@
Object item = (x == null) ? NULL_ITEM : x; // translate null args
if (((a = arena) != null ||
(v = slotExchange(item, false, 0L)) == null) &&
- ((Thread.interrupted() || // disambiguates null return
- (v = arenaExchange(item, false, 0L)) == null)))
+ (Thread.interrupted() || // disambiguates null return
+ (v = arenaExchange(item, false, 0L)) == null))
throw new InterruptedException();
return (v == NULL_ITEM) ? null : (V)v;
}
@@ -620,8 +620,8 @@
long ns = unit.toNanos(timeout);
if ((arena != null ||
(v = slotExchange(item, true, ns)) == null) &&
- ((Thread.interrupted() ||
- (v = arenaExchange(item, true, ns)) == null)))
+ (Thread.interrupted() ||
+ (v = arenaExchange(item, true, ns)) == null))
throw new InterruptedException();
if (v == TIMED_OUT)
throw new TimeoutException();
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java Wed Nov 28 15:25:14 2018 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java Wed Nov 28 15:25:14 2018 -0800
@@ -1230,14 +1230,13 @@
/**
* Immediately performs the base action of this task and returns
* true if, upon return from this method, this task is guaranteed
- * to have completed normally. This method may return false
- * otherwise, to indicate that this task is not necessarily
- * complete (or is not known to be complete), for example in
- * asynchronous actions that require explicit invocations of
- * completion methods. This method may also throw an (unchecked)
- * exception to indicate abnormal exit. This method is designed to
- * support extensions, and should not in general be called
- * otherwise.
+ * to have completed. This method may return false otherwise, to
+ * indicate that this task is not necessarily complete (or is not
+ * known to be complete), for example in asynchronous actions that
+ * require explicit invocations of completion methods. This method
+ * may also throw an (unchecked) exception to indicate abnormal
+ * exit. This method is designed to support extensions, and should
+ * not in general be called otherwise.
*
* @return {@code true} if this task is known to have completed normally
*/
--- a/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Wed Nov 28 15:25:14 2018 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Wed Nov 28 15:25:14 2018 -0800
@@ -199,10 +199,11 @@
* Disables the current thread for thread scheduling purposes, for up to
* the specified waiting time, unless the permit is available.
*
- * <p>If the permit is available then it is consumed and the call
- * returns immediately; otherwise the current thread becomes disabled
- * for thread scheduling purposes and lies dormant until one of four
- * things happens:
+ * <p>If the specified waiting time is zero or negative, the
+ * method does nothing. Otherwise, if the permit is available then
+ * it is consumed and the call returns immediately; otherwise the
+ * current thread becomes disabled for thread scheduling purposes
+ * and lies dormant until one of four things happens:
*
* <ul>
* <li>Some other thread invokes {@link #unpark unpark} with the
@@ -327,10 +328,11 @@
* Disables the current thread for thread scheduling purposes, for up to
* the specified waiting time, unless the permit is available.
*
- * <p>If the permit is available then it is consumed and the call
- * returns immediately; otherwise the current thread becomes disabled
- * for thread scheduling purposes and lies dormant until one of four
- * things happens:
+ * <p>If the specified waiting time is zero or negative, the
+ * method does nothing. Otherwise, if the permit is available then
+ * it is consumed and the call returns immediately; otherwise the
+ * current thread becomes disabled for thread scheduling purposes
+ * and lies dormant until one of four things happens:
*
* <ul>
* <li>Some other thread invokes {@link #unpark unpark} with the
--- a/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Wed Nov 28 15:25:14 2018 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Wed Nov 28 15:25:14 2018 -0800
@@ -65,22 +65,23 @@
* and timed versions of {@code tryReadLock} are also provided.
*
* <li><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
- * returns a non-zero stamp only if the lock is not currently held
- * in write mode. Method {@link #validate} returns true if the lock
- * has not been acquired in write mode since obtaining a given
- * stamp. This mode can be thought of as an extremely weak version
- * of a read-lock, that can be broken by a writer at any time. The
- * use of optimistic mode for short read-only code segments often
- * reduces contention and improves throughput. However, its use is
- * inherently fragile. Optimistic read sections should only read
- * fields and hold them in local variables for later use after
- * validation. Fields read while in optimistic mode may be wildly
- * inconsistent, so usage applies only when you are familiar enough
- * with data representations to check consistency and/or repeatedly
- * invoke method {@code validate()}. For example, such steps are
- * typically required when first reading an object or array
- * reference, and then accessing one of its fields, elements or
- * methods.
+ * returns a non-zero stamp only if the lock is not currently held in
+ * write mode. Method {@link #validate} returns true if the lock has not
+ * been acquired in write mode since obtaining a given stamp, in which
+ * case all actions prior to the most recent write lock release
+ * happen-before actions following the call to {@code tryOptimisticRead}.
+ * This mode can be thought of as an extremely weak version of a
+ * read-lock, that can be broken by a writer at any time. The use of
+ * optimistic read mode for short read-only code segments often reduces
+ * contention and improves throughput. However, its use is inherently
+ * fragile. Optimistic read sections should only read fields and hold
+ * them in local variables for later use after validation. Fields read
+ * while in optimistic read mode may be wildly inconsistent, so usage
+ * applies only when you are familiar enough with data representations to
+ * check consistency and/or repeatedly invoke method {@code validate()}.
+ * For example, such steps are typically required when first reading an
+ * object or array reference, and then accessing one of its fields,
+ * elements or methods.
*
* </ul>
*
@@ -88,8 +89,8 @@
* conversions across the three modes. For example, method {@link
* #tryConvertToWriteLock} attempts to "upgrade" a mode, returning
* a valid write stamp if (1) already in writing mode (2) in reading
- * mode and there are no other readers or (3) in optimistic mode and
- * the lock is available. The forms of these methods are designed to
+ * mode and there are no other readers or (3) in optimistic read mode
+ * and the lock is available. The forms of these methods are designed to
* help reduce some of the code bloat that otherwise occurs in
* retry-based designs.
*
@@ -129,6 +130,19 @@
* #asReadWriteLock()} in applications requiring only the associated
* set of functionality.
*
+ * <p><b>Memory Synchronization.</b> Methods with the effect of
+ * successfully locking in any mode have the same memory
+ * synchronization effects as a <em>Lock</em> action described in
+ * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
+ * Chapter 17 of <cite>The Java™ Language Specification</cite></a>.
+ * Methods successfully unlocking in write mode have the same memory
+ * synchronization effects as an <em>Unlock</em> action. In optimistic
+ * read usages, actions prior to the most recent write mode unlock action
+ * are guaranteed to happen-before those following a tryOptimisticRead
+ * only if a later validate returns true; otherwise there is no guarantee
+ * that the reads between tryOptimisticRead and validate obtain a
+ * consistent snapshot.
+ *
* <p><b>Sample Usage.</b> The following illustrates some usage idioms
* in a class that maintains simple two-dimensional points. The sample
* code illustrates some try/catch conventions even though they are
--- a/test/jdk/java/util/concurrent/atomic/LongAdderDemo.java Wed Nov 28 15:25:14 2018 -0800
+++ b/test/jdk/java/util/concurrent/atomic/LongAdderDemo.java Wed Nov 28 15:25:14 2018 -0800
@@ -93,14 +93,14 @@
report(nthreads, incs, timeTasks(phaser), a.sum());
}
- static void report(int nthreads, int incs, long time, long sum) {
+ static void report(int nthreads, int incs, long elapsedNanos, long sum) {
long total = (long)nthreads * incs;
if (sum != total)
throw new Error(sum + " != " + total);
- double secs = (double)time / (1000L * 1000 * 1000);
- long rate = total * (1000L) / time;
+ double elapsedSecs = (double)elapsedNanos / (1000L * 1000 * 1000);
+ long rate = total * 1000L / elapsedNanos;
System.out.printf("threads:%3d Time: %7.3fsec Incs per microsec: %4d\n",
- nthreads, secs, rate);
+ nthreads, elapsedSecs, rate);
}
static long timeTasks(Phaser phaser) {
--- a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java Wed Nov 28 15:25:14 2018 -0800
+++ b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java Wed Nov 28 15:25:14 2018 -0800
@@ -953,17 +953,19 @@
for (boolean createIncomplete : new boolean[] { true, false })
for (Integer v1 : new Integer[] { 1, null })
{
+ final AtomicInteger ran = new AtomicInteger(0);
final CompletableFuture<Integer> f = new CompletableFuture<>();
if (!createIncomplete) assertTrue(f.complete(v1));
final CompletableFuture<Integer> g = m.exceptionally
(f, (Throwable t) -> {
- threadFail("should not be called");
- return null; // unreached
+ ran.getAndIncrement();
+ throw new AssertionError("should not be called");
});
if (createIncomplete) assertTrue(f.complete(v1));
checkCompletedNormally(g, v1);
checkCompletedNormally(f, v1);
+ assertEquals(0, ran.get());
}}
/**
@@ -975,21 +977,21 @@
for (boolean createIncomplete : new boolean[] { true, false })
for (Integer v1 : new Integer[] { 1, null })
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
if (!createIncomplete) f.completeExceptionally(ex);
final CompletableFuture<Integer> g = m.exceptionally
(f, (Throwable t) -> {
m.checkExecutionMode();
- threadAssertSame(t, ex);
- a.getAndIncrement();
+ assertSame(t, ex);
+ ran.getAndIncrement();
return v1;
});
if (createIncomplete) f.completeExceptionally(ex);
checkCompletedNormally(g, v1);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1000,7 +1002,7 @@
for (ExecutionMode m : ExecutionMode.values())
for (boolean createIncomplete : new boolean[] { true, false })
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex1 = new CFException();
final CFException ex2 = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
@@ -1008,15 +1010,15 @@
final CompletableFuture<Integer> g = m.exceptionally
(f, (Throwable t) -> {
m.checkExecutionMode();
- threadAssertSame(t, ex1);
- a.getAndIncrement();
+ assertSame(t, ex1);
+ ran.getAndIncrement();
throw ex2;
});
if (createIncomplete) f.completeExceptionally(ex1);
checkCompletedWithWrappedException(g, ex2);
checkCompletedExceptionally(f, ex1);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1028,22 +1030,22 @@
for (boolean createIncomplete : new boolean[] { true, false })
for (Integer v1 : new Integer[] { 1, null })
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CompletableFuture<Integer> f = new CompletableFuture<>();
if (!createIncomplete) assertTrue(f.complete(v1));
final CompletableFuture<Integer> g = m.whenComplete
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertSame(result, v1);
- threadAssertNull(t);
- a.getAndIncrement();
+ assertSame(result, v1);
+ assertNull(t);
+ ran.getAndIncrement();
});
if (createIncomplete) assertTrue(f.complete(v1));
checkCompletedNormally(g, v1);
checkCompletedNormally(f, v1);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1054,7 +1056,7 @@
for (ExecutionMode m : ExecutionMode.values())
for (boolean createIncomplete : new boolean[] { true, false })
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
if (!createIncomplete) f.completeExceptionally(ex);
@@ -1062,15 +1064,15 @@
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertNull(result);
- threadAssertSame(t, ex);
- a.getAndIncrement();
+ assertNull(result);
+ assertSame(t, ex);
+ ran.getAndIncrement();
});
if (createIncomplete) f.completeExceptionally(ex);
checkCompletedWithWrappedException(g, ex);
checkCompletedExceptionally(f, ex);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1082,22 +1084,22 @@
for (boolean mayInterruptIfRunning : new boolean[] { true, false })
for (boolean createIncomplete : new boolean[] { true, false })
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CompletableFuture<Integer> f = new CompletableFuture<>();
if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
final CompletableFuture<Integer> g = m.whenComplete
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertNull(result);
- threadAssertTrue(t instanceof CancellationException);
- a.getAndIncrement();
+ assertNull(result);
+ assertTrue(t instanceof CancellationException);
+ ran.getAndIncrement();
});
if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
checkCompletedWithWrappedCancellationException(g);
checkCancelled(f);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1109,7 +1111,7 @@
for (ExecutionMode m : ExecutionMode.values())
for (Integer v1 : new Integer[] { 1, null })
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
if (!createIncomplete) assertTrue(f.complete(v1));
@@ -1117,16 +1119,16 @@
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertSame(result, v1);
- threadAssertNull(t);
- a.getAndIncrement();
+ assertSame(result, v1);
+ assertNull(t);
+ ran.getAndIncrement();
throw ex;
});
if (createIncomplete) assertTrue(f.complete(v1));
checkCompletedWithWrappedException(g, ex);
checkCompletedNormally(f, v1);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1138,7 +1140,7 @@
for (boolean createIncomplete : new boolean[] { true, false })
for (ExecutionMode m : ExecutionMode.values())
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex1 = new CFException();
final CFException ex2 = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
@@ -1148,9 +1150,9 @@
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertSame(t, ex1);
- threadAssertNull(result);
- a.getAndIncrement();
+ assertSame(t, ex1);
+ assertNull(result);
+ ran.getAndIncrement();
throw ex2;
});
if (createIncomplete) f.completeExceptionally(ex1);
@@ -1161,7 +1163,7 @@
assertEquals(1, ex1.getSuppressed().length);
assertSame(ex2, ex1.getSuppressed()[0]);
}
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1174,22 +1176,22 @@
for (Integer v1 : new Integer[] { 1, null })
{
final CompletableFuture<Integer> f = new CompletableFuture<>();
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
if (!createIncomplete) assertTrue(f.complete(v1));
final CompletableFuture<Integer> g = m.handle
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertSame(result, v1);
- threadAssertNull(t);
- a.getAndIncrement();
+ assertSame(result, v1);
+ assertNull(t);
+ ran.getAndIncrement();
return inc(v1);
});
if (createIncomplete) assertTrue(f.complete(v1));
checkCompletedNormally(g, inc(v1));
checkCompletedNormally(f, v1);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1202,23 +1204,23 @@
for (Integer v1 : new Integer[] { 1, null })
{
final CompletableFuture<Integer> f = new CompletableFuture<>();
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex = new CFException();
if (!createIncomplete) f.completeExceptionally(ex);
final CompletableFuture<Integer> g = m.handle
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertNull(result);
- threadAssertSame(t, ex);
- a.getAndIncrement();
+ assertNull(result);
+ assertSame(t, ex);
+ ran.getAndIncrement();
return v1;
});
if (createIncomplete) f.completeExceptionally(ex);
checkCompletedNormally(g, v1);
checkCompletedExceptionally(f, ex);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1232,22 +1234,22 @@
for (Integer v1 : new Integer[] { 1, null })
{
final CompletableFuture<Integer> f = new CompletableFuture<>();
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
final CompletableFuture<Integer> g = m.handle
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertNull(result);
- threadAssertTrue(t instanceof CancellationException);
- a.getAndIncrement();
+ assertNull(result);
+ assertTrue(t instanceof CancellationException);
+ ran.getAndIncrement();
return v1;
});
if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
checkCompletedNormally(g, v1);
checkCancelled(f);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1260,23 +1262,23 @@
for (Integer v1 : new Integer[] { 1, null })
{
final CompletableFuture<Integer> f = new CompletableFuture<>();
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex = new CFException();
if (!createIncomplete) assertTrue(f.complete(v1));
final CompletableFuture<Integer> g = m.handle
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertSame(result, v1);
- threadAssertNull(t);
- a.getAndIncrement();
+ assertSame(result, v1);
+ assertNull(t);
+ ran.getAndIncrement();
throw ex;
});
if (createIncomplete) assertTrue(f.complete(v1));
checkCompletedWithWrappedException(g, ex);
checkCompletedNormally(f, v1);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -1288,7 +1290,7 @@
for (boolean createIncomplete : new boolean[] { true, false })
for (ExecutionMode m : ExecutionMode.values())
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex1 = new CFException();
final CFException ex2 = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
@@ -1298,16 +1300,16 @@
(f,
(Integer result, Throwable t) -> {
m.checkExecutionMode();
- threadAssertNull(result);
- threadAssertSame(ex1, t);
- a.getAndIncrement();
+ assertNull(result);
+ assertSame(ex1, t);
+ ran.getAndIncrement();
throw ex2;
});
if (createIncomplete) f.completeExceptionally(ex1);
checkCompletedWithWrappedException(g, ex2);
checkCompletedExceptionally(f, ex1);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
@@ -3143,30 +3145,30 @@
case 0:
assertTrue(f.complete(v1));
assertTrue(g.completeExceptionally(ex));
- h = m.thenCompose(f, (x -> g));
+ h = m.thenCompose(f, x -> g);
break;
case 1:
assertTrue(f.complete(v1));
- h = m.thenCompose(f, (x -> g));
+ h = m.thenCompose(f, x -> g);
assertTrue(g.completeExceptionally(ex));
break;
case 2:
assertTrue(g.completeExceptionally(ex));
assertTrue(f.complete(v1));
- h = m.thenCompose(f, (x -> g));
+ h = m.thenCompose(f, x -> g);
break;
case 3:
assertTrue(g.completeExceptionally(ex));
- h = m.thenCompose(f, (x -> g));
+ h = m.thenCompose(f, x -> g);
assertTrue(f.complete(v1));
break;
case 4:
- h = m.thenCompose(f, (x -> g));
+ h = m.thenCompose(f, x -> g);
assertTrue(f.complete(v1));
assertTrue(g.completeExceptionally(ex));
break;
case 5:
- h = m.thenCompose(f, (x -> g));
+ h = m.thenCompose(f, x -> g);
assertTrue(f.complete(v1));
assertTrue(g.completeExceptionally(ex));
break;
@@ -3258,30 +3260,30 @@
case 0:
assertTrue(f.completeExceptionally(ex0));
assertTrue(g.completeExceptionally(ex));
- h = m.exceptionallyCompose(f, (x -> g));
+ h = m.exceptionallyCompose(f, x -> g);
break;
case 1:
assertTrue(f.completeExceptionally(ex0));
- h = m.exceptionallyCompose(f, (x -> g));
+ h = m.exceptionallyCompose(f, x -> g);
assertTrue(g.completeExceptionally(ex));
break;
case 2:
assertTrue(g.completeExceptionally(ex));
assertTrue(f.completeExceptionally(ex0));
- h = m.exceptionallyCompose(f, (x -> g));
+ h = m.exceptionallyCompose(f, x -> g);
break;
case 3:
assertTrue(g.completeExceptionally(ex));
- h = m.exceptionallyCompose(f, (x -> g));
+ h = m.exceptionallyCompose(f, x -> g);
assertTrue(f.completeExceptionally(ex0));
break;
case 4:
- h = m.exceptionallyCompose(f, (x -> g));
+ h = m.exceptionallyCompose(f, x -> g);
assertTrue(f.completeExceptionally(ex0));
assertTrue(g.completeExceptionally(ex));
break;
case 5:
- h = m.exceptionallyCompose(f, (x -> g));
+ h = m.exceptionallyCompose(f, x -> g);
assertTrue(f.completeExceptionally(ex0));
assertTrue(g.completeExceptionally(ex));
break;
@@ -3672,12 +3674,6 @@
final CompletableFuture<Integer> complete = CompletableFuture.completedFuture(v);
final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
- List<CompletableFuture<?>> futures = new ArrayList<>();
-
- List<CompletableFuture<Integer>> srcs = new ArrayList<>();
- srcs.add(complete);
- srcs.add(incomplete);
-
List<CompletableFuture<?>> fs = new ArrayList<>();
fs.add(incomplete.thenRunAsync(() -> {}, e));
fs.add(incomplete.thenAcceptAsync(z -> {}, e));
@@ -4862,18 +4858,21 @@
for (boolean createIncomplete : new boolean[] { true, false })
for (Integer v1 : new Integer[] { 1, null })
{
+ final AtomicInteger ran = new AtomicInteger(0);
final CompletableFuture<Integer> f = new CompletableFuture<>();
final DelegatedCompletionStage<Integer> d =
new DelegatedCompletionStage<Integer>(f);
if (!createIncomplete) assertTrue(f.complete(v1));
final CompletionStage<Integer> g = d.exceptionallyAsync
((Throwable t) -> {
- threadFail("should not be called");
- return null; // unreached
+ ran.getAndIncrement();
+ throw new AssertionError("should not be called");
});
if (createIncomplete) assertTrue(f.complete(v1));
checkCompletedNormally(g.toCompletableFuture(), v1);
+ checkCompletedNormally(f, v1);
+ assertEquals(0, ran.get());
}}
/**
@@ -4884,7 +4883,7 @@
for (boolean createIncomplete : new boolean[] { true, false })
for (Integer v1 : new Integer[] { 1, null })
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
final DelegatedCompletionStage<Integer> d =
@@ -4892,14 +4891,15 @@
if (!createIncomplete) f.completeExceptionally(ex);
final CompletionStage<Integer> g = d.exceptionallyAsync
((Throwable t) -> {
- threadAssertSame(t, ex);
- a.getAndIncrement();
+ assertSame(t, ex);
+ ran.getAndIncrement();
return v1;
});
if (createIncomplete) f.completeExceptionally(ex);
checkCompletedNormally(g.toCompletableFuture(), v1);
- assertEquals(1, a.get());
+ checkCompletedExceptionally(f, ex);
+ assertEquals(1, ran.get());
}}
/**
@@ -4910,7 +4910,7 @@
public void testDefaultExceptionallyAsync_exceptionalCompletionActionFailed() {
for (boolean createIncomplete : new boolean[] { true, false })
{
- final AtomicInteger a = new AtomicInteger(0);
+ final AtomicInteger ran = new AtomicInteger(0);
final CFException ex1 = new CFException();
final CFException ex2 = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
@@ -4919,8 +4919,8 @@
if (!createIncomplete) f.completeExceptionally(ex1);
final CompletionStage<Integer> g = d.exceptionallyAsync
((Throwable t) -> {
- threadAssertSame(t, ex1);
- a.getAndIncrement();
+ assertSame(t, ex1);
+ ran.getAndIncrement();
throw ex2;
});
if (createIncomplete) f.completeExceptionally(ex1);
@@ -4928,7 +4928,7 @@
checkCompletedWithWrappedException(g.toCompletableFuture(), ex2);
checkCompletedExceptionally(f, ex1);
checkCompletedExceptionally(d.toCompletableFuture(), ex1);
- assertEquals(1, a.get());
+ assertEquals(1, ran.get());
}}
/**
--- a/test/jdk/java/util/concurrent/tck/ConcurrentHashMapTest.java Wed Nov 28 15:25:14 2018 -0800
+++ b/test/jdk/java/util/concurrent/tck/ConcurrentHashMapTest.java Wed Nov 28 15:25:14 2018 -0800
@@ -865,4 +865,20 @@
assertEquals(mapSize, map.size());
}
+ public void testReentrantComputeIfAbsent() {
+ ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>(16);
+ try {
+ for (int i = 0; i < 100; i++) { // force a resize
+ map.computeIfAbsent(i, key -> findValue(map, key));
+ }
+ fail("recursive computeIfAbsent should throw IllegalStateException");
+ } catch (IllegalStateException success) {}
+ }
+
+ private Integer findValue(ConcurrentHashMap<Integer, Integer> map,
+ Integer key) {
+ return (key % 5 == 0) ? key :
+ map.computeIfAbsent(key + 1, k -> findValue(map, k));
+ }
+
}
--- a/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java Wed Nov 28 15:25:14 2018 -0800
+++ b/test/jdk/java/util/concurrent/tck/ForkJoinPoolTest.java Wed Nov 28 15:25:14 2018 -0800
@@ -136,7 +136,7 @@
return n;
FibTask f1 = new FibTask(n - 1);
f1.fork();
- return (new FibTask(n - 2)).compute() + f1.join();
+ return new FibTask(n - 2).compute() + f1.join();
}
}
--- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java Wed Nov 28 15:25:14 2018 -0800
+++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java Wed Nov 28 15:25:14 2018 -0800
@@ -144,13 +144,21 @@
*
* <ol>
*
- * <li>All assertions in code running in generated threads must use
- * the forms {@link #threadFail}, {@link #threadAssertTrue}, {@link
- * #threadAssertEquals}, or {@link #threadAssertNull}, (not
- * {@code fail}, {@code assertTrue}, etc.) It is OK (but not
- * particularly recommended) for other code to use these forms too.
- * Only the most typically used JUnit assertion methods are defined
- * this way, but enough to live with.
+ * <li>All code not running in the main test thread (manually spawned threads
+ * or the common fork join pool) must be checked for failure (and completion!).
+ * Mechanisms that can be used to ensure this are:
+ * <ol>
+ * <li>Signalling via a synchronizer like AtomicInteger or CountDownLatch
+ * that the task completed normally, which is checked before returning from
+ * the test method in the main thread.
+ * <li>Using the forms {@link #threadFail}, {@link #threadAssertTrue},
+ * or {@link #threadAssertNull}, (not {@code fail}, {@code assertTrue}, etc.)
+ * Only the most typically used JUnit assertion methods are defined
+ * this way, but enough to live with.
+ * <li>Recording failure explicitly using {@link #threadUnexpectedException}
+ * or {@link #threadRecordFailure}.
+ * <li>Using a wrapper like CheckedRunnable that uses one the mechanisms above.
+ * </ol>
*
* <li>If you override {@link #setUp} or {@link #tearDown}, make sure
* to invoke {@code super.setUp} and {@code super.tearDown} within
@@ -1318,22 +1326,33 @@
/**
* Spin-waits up to the specified number of milliseconds for the given
* thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING.
+ * @param waitingForGodot if non-null, an additional condition to satisfy
*/
- void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis) {
- long startTime = 0L;
- for (;;) {
- Thread.State s = thread.getState();
- if (s == Thread.State.BLOCKED ||
- s == Thread.State.WAITING ||
- s == Thread.State.TIMED_WAITING)
- return;
- else if (s == Thread.State.TERMINATED)
+ void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis,
+ Callable<Boolean> waitingForGodot) {
+ for (long startTime = 0L;;) {
+ switch (thread.getState()) {
+ default: break;
+ case BLOCKED: case WAITING: case TIMED_WAITING:
+ try {
+ if (waitingForGodot == null || waitingForGodot.call())
+ return;
+ } catch (Throwable fail) { threadUnexpectedException(fail); }
+ break;
+ case TERMINATED:
fail("Unexpected thread termination");
- else if (startTime == 0L)
+ }
+
+ if (startTime == 0L)
startTime = System.nanoTime();
else if (millisElapsedSince(startTime) > timeoutMillis) {
- threadAssertTrue(thread.isAlive());
- fail("timed out waiting for thread to enter wait state");
+ assertTrue(thread.isAlive());
+ if (waitingForGodot == null
+ || thread.getState() == Thread.State.RUNNABLE)
+ fail("timed out waiting for thread to enter wait state");
+ else
+ fail("timed out waiting for condition, thread state="
+ + thread.getState());
}
Thread.yield();
}
@@ -1341,32 +1360,10 @@
/**
* Spin-waits up to the specified number of milliseconds for the given
- * thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING,
- * and additionally satisfy the given condition.
+ * thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING.
*/
- void waitForThreadToEnterWaitState(
- Thread thread, long timeoutMillis, Callable<Boolean> waitingForGodot) {
- long startTime = 0L;
- for (;;) {
- Thread.State s = thread.getState();
- if (s == Thread.State.BLOCKED ||
- s == Thread.State.WAITING ||
- s == Thread.State.TIMED_WAITING) {
- try {
- if (waitingForGodot.call())
- return;
- } catch (Throwable fail) { threadUnexpectedException(fail); }
- }
- else if (s == Thread.State.TERMINATED)
- fail("Unexpected thread termination");
- else if (startTime == 0L)
- startTime = System.nanoTime();
- else if (millisElapsedSince(startTime) > timeoutMillis) {
- threadAssertTrue(thread.isAlive());
- fail("timed out waiting for thread to enter wait state");
- }
- Thread.yield();
- }
+ void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis) {
+ waitForThreadToEnterWaitState(thread, timeoutMillis, null);
}
/**
@@ -1374,7 +1371,7 @@
* enter a wait state: BLOCKED, WAITING, or TIMED_WAITING.
*/
void waitForThreadToEnterWaitState(Thread thread) {
- waitForThreadToEnterWaitState(thread, LONG_DELAY_MS);
+ waitForThreadToEnterWaitState(thread, LONG_DELAY_MS, null);
}
/**
@@ -1382,8 +1379,8 @@
* enter a wait state: BLOCKED, WAITING, or TIMED_WAITING,
* and additionally satisfy the given condition.
*/
- void waitForThreadToEnterWaitState(
- Thread thread, Callable<Boolean> waitingForGodot) {
+ void waitForThreadToEnterWaitState(Thread thread,
+ Callable<Boolean> waitingForGodot) {
waitForThreadToEnterWaitState(thread, LONG_DELAY_MS, waitingForGodot);
}
@@ -1491,11 +1488,12 @@
public final void run() {
try {
realRun();
- threadShouldThrow(exceptionClass.getSimpleName());
} catch (Throwable t) {
if (! exceptionClass.isInstance(t))
threadUnexpectedException(t);
+ return;
}
+ threadShouldThrow(exceptionClass.getSimpleName());
}
}
@@ -1505,12 +1503,13 @@
public final void run() {
try {
realRun();
- threadShouldThrow("InterruptedException");
} catch (InterruptedException success) {
threadAssertFalse(Thread.interrupted());
+ return;
} catch (Throwable fail) {
threadUnexpectedException(fail);
}
+ threadShouldThrow("InterruptedException");
}
}
@@ -1522,26 +1521,8 @@
return realCall();
} catch (Throwable fail) {
threadUnexpectedException(fail);
- return null;
}
- }
- }
-
- public abstract class CheckedInterruptedCallable<T>
- implements Callable<T> {
- protected abstract T realCall() throws Throwable;
-
- public final T call() {
- try {
- T result = realCall();
- threadShouldThrow("InterruptedException");
- return result;
- } catch (InterruptedException success) {
- threadAssertFalse(Thread.interrupted());
- } catch (Throwable fail) {
- threadUnexpectedException(fail);
- }
- return null;
+ throw new AssertionError("unreached");
}
}
@@ -1656,14 +1637,6 @@
public String call() { throw new NullPointerException(); }
}
- public class SmallPossiblyInterruptedRunnable extends CheckedRunnable {
- protected void realRun() {
- try {
- delay(SMALL_DELAY_MS);
- } catch (InterruptedException ok) {}
- }
- }
-
public Runnable possiblyInterruptedRunnable(final long timeoutMillis) {
return new CheckedRunnable() {
protected void realRun() {
@@ -1719,8 +1692,8 @@
return realCompute();
} catch (Throwable fail) {
threadUnexpectedException(fail);
- return null;
}
+ throw new AssertionError("unreached");
}
}
--- a/test/jdk/java/util/concurrent/tck/RecursiveTaskTest.java Wed Nov 28 15:25:14 2018 -0800
+++ b/test/jdk/java/util/concurrent/tck/RecursiveTaskTest.java Wed Nov 28 15:25:14 2018 -0800
@@ -225,7 +225,7 @@
return n;
FibTask f1 = new FibTask(n - 1);
f1.fork();
- return (new FibTask(n - 2)).compute() + f1.join();
+ return new FibTask(n - 2).compute() + f1.join();
}
public void publicSetRawResult(Integer result) {
@@ -244,7 +244,7 @@
throw new FJException();
FailingFibTask f1 = new FailingFibTask(n - 1);
f1.fork();
- return (new FibTask(n - 2)).compute() + f1.join();
+ return new FibTask(n - 2).compute() + f1.join();
}
}
--- a/test/jdk/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Wed Nov 28 15:25:14 2018 -0800
+++ b/test/jdk/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Wed Nov 28 15:25:14 2018 -0800
@@ -676,7 +676,7 @@
final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p, releaser)) {
for (int i = 0; i < tasks.length; i++)
- tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
+ tasks[i] = p.schedule(possiblyInterruptedRunnable(SMALL_DELAY_MS),
LONG_DELAY_MS, MILLISECONDS);
int max = tasks.length;
if (tasks[4].cancel(true)) --max;
--- a/test/jdk/java/util/concurrent/tck/ScheduledExecutorTest.java Wed Nov 28 15:25:14 2018 -0800
+++ b/test/jdk/java/util/concurrent/tck/ScheduledExecutorTest.java Wed Nov 28 15:25:14 2018 -0800
@@ -634,7 +634,7 @@
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p, releaser)) {
for (int i = 0; i < tasks.length; i++)
- tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
+ tasks[i] = p.schedule(possiblyInterruptedRunnable(SMALL_DELAY_MS),
LONG_DELAY_MS, MILLISECONDS);
int max = tasks.length;
if (tasks[4].cancel(true)) --max;