8211283: Miscellaneous changes imported from jsr166 CVS 2018-11

Reviewed-by: martin, chegar
This commit is contained in:
Doug Lea 2018-11-28 15:25:14 -08:00
parent 5a5aa52772
commit 53d3a4f50c
14 changed files with 218 additions and 213 deletions

View file

@ -37,7 +37,6 @@ package java.util;
import java.io.Serializable;
import java.util.function.Consumer;
import java.util.function.Predicate;
import jdk.internal.access.SharedSecrets;
/**

View file

@ -2542,6 +2542,8 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
setTabAt(tab, i, fwd);
advance = true;
}
else if (f instanceof ReservationNode)
throw new IllegalStateException("Recursive update");
}
}
}

View file

@ -564,8 +564,8 @@ public class Exchanger<V> {
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 @@ public class Exchanger<V> {
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();

View file

@ -1230,14 +1230,13 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
/**
* 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
*/

View file

@ -199,10 +199,11 @@ public class LockSupport {
* 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 @@ public class LockSupport {
* 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

View file

@ -65,22 +65,23 @@ import jdk.internal.vm.annotation.ReservedStackAccess;
* 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 @@ import jdk.internal.vm.annotation.ReservedStackAccess;
* 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 @@ import jdk.internal.vm.annotation.ReservedStackAccess;
* #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&trade; 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

View file

@ -93,14 +93,14 @@ public class LongAdderDemo {
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) {

View file

@ -953,17 +953,19 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
(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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
(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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
(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 @@ public class CompletableFutureTest extends JSR166TestCase {
assertEquals(1, ex1.getSuppressed().length);
assertSame(ex2, ex1.getSuppressed()[0]);
}
assertEquals(1, a.get());
assertEquals(1, ran.get());
}}
/**
@ -1174,22 +1176,22 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
(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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
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 @@ public class CompletableFutureTest extends JSR166TestCase {
checkCompletedWithWrappedException(g.toCompletableFuture(), ex2);
checkCompletedExceptionally(f, ex1);
checkCompletedExceptionally(d.toCompletableFuture(), ex1);
assertEquals(1, a.get());
assertEquals(1, ran.get());
}}
/**

View file

@ -865,4 +865,20 @@ public class ConcurrentHashMapTest extends JSR166TestCase {
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));
}
}

View file

@ -136,7 +136,7 @@ public class ForkJoinPoolTest extends JSR166TestCase {
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();
}
}

View file

@ -144,13 +144,21 @@ import junit.framework.TestSuite;
*
* <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.
* <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 @@ public class JSR166TestCase extends TestCase {
/**
* 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)
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;
else if (s == Thread.State.TERMINATED)
} 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());
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 @@ public class JSR166TestCase extends TestCase {
/**
* 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 @@ public class JSR166TestCase extends TestCase {
* 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 @@ public class JSR166TestCase extends TestCase {
* 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 class JSR166TestCase extends TestCase {
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 class JSR166TestCase extends TestCase {
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 @@ public class JSR166TestCase extends TestCase {
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 class JSR166TestCase extends TestCase {
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 @@ public class JSR166TestCase extends TestCase {
return realCompute();
} catch (Throwable fail) {
threadUnexpectedException(fail);
return null;
}
throw new AssertionError("unreached");
}
}

View file

@ -225,7 +225,7 @@ public class RecursiveTaskTest extends JSR166TestCase {
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 @@ public class RecursiveTaskTest extends JSR166TestCase {
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();
}
}

View file

@ -676,7 +676,7 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase {
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;

View file

@ -634,7 +634,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
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;