--- jsr166/src/test/tck/ForkJoinTask8Test.java 2015/09/08 23:56:19 1.15 +++ jsr166/src/test/tck/ForkJoinTask8Test.java 2021/01/26 13:33:06 1.35 @@ -5,10 +5,8 @@ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.Arrays; -import java.util.Collections; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; @@ -74,7 +72,7 @@ public class ForkJoinTask8Test extends J } private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) { - try { + try (PoolCleaner cleaner = cleaner(pool)) { assertFalse(a.isDone()); assertFalse(a.isCompletedNormally()); assertFalse(a.isCompletedAbnormally()); @@ -90,12 +88,10 @@ public class ForkJoinTask8Test extends J assertFalse(a.isCancelled()); assertNull(a.getException()); assertNull(a.getRawResult()); - } finally { - joinPool(pool); } } - void checkNotDone(ForkJoinTask a) { + void checkNotDone(ForkJoinTask a) { assertFalse(a.isDone()); assertFalse(a.isCompletedNormally()); assertFalse(a.isCompletedAbnormally()); @@ -103,10 +99,11 @@ public class ForkJoinTask8Test extends J assertNull(a.getException()); assertNull(a.getRawResult()); if (a instanceof BinaryAsyncAction) - assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == INITIAL_STATE); + assertEquals(INITIAL_STATE, + ((BinaryAsyncAction)a).getForkJoinTaskTag()); try { - a.get(0L, SECONDS); + a.get(randomExpiredTimeout(), randomTimeUnit()); shouldThrow(); } catch (TimeoutException success) { } catch (Throwable fail) { threadUnexpectedException(fail); } @@ -116,43 +113,46 @@ public class ForkJoinTask8Test extends J checkCompletedNormally(a, null); } - void checkCompletedNormally(ForkJoinTask a, T expected) { + void checkCompletedNormally(ForkJoinTask a, T expectedValue) { assertTrue(a.isDone()); assertFalse(a.isCancelled()); assertTrue(a.isCompletedNormally()); assertFalse(a.isCompletedAbnormally()); assertNull(a.getException()); - assertSame(expected, a.getRawResult()); + assertSame(expectedValue, a.getRawResult()); if (a instanceof BinaryAsyncAction) - assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == COMPLETE_STATE); + assertEquals(COMPLETE_STATE, + ((BinaryAsyncAction)a).getForkJoinTaskTag()); { Thread.currentThread().interrupt(); - long t0 = System.nanoTime(); - assertSame(expected, a.join()); - assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS); + long startTime = System.nanoTime(); + assertSame(expectedValue, a.join()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); Thread.interrupted(); } { Thread.currentThread().interrupt(); - long t0 = System.nanoTime(); + long startTime = System.nanoTime(); a.quietlyJoin(); // should be no-op - assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); Thread.interrupted(); } assertFalse(a.cancel(false)); assertFalse(a.cancel(true)); + + T v1 = null, v2 = null; try { - assertSame(expected, a.get()); - } catch (Throwable fail) { threadUnexpectedException(fail); } - try { - assertSame(expected, a.get(5L, SECONDS)); + v1 = a.get(); + v2 = a.get(randomTimeout(), randomTimeUnit()); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertSame(expectedValue, v1); + assertSame(expectedValue, v2); } - void checkCompletedAbnormally(ForkJoinTask a, Throwable t) { + void checkCompletedAbnormally(ForkJoinTask a, Throwable t) { assertTrue(a.isDone()); assertFalse(a.isCancelled()); assertFalse(a.isCompletedNormally()); @@ -174,9 +174,9 @@ public class ForkJoinTask8Test extends J Thread.interrupted(); { - long t0 = System.nanoTime(); + long startTime = System.nanoTime(); a.quietlyJoin(); // should be no-op - assertTrue(millisElapsedSince(t0) < SMALL_DELAY_MS); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); } try { @@ -187,7 +187,7 @@ public class ForkJoinTask8Test extends J } catch (Throwable fail) { threadUnexpectedException(fail); } try { - a.get(5L, SECONDS); + a.get(randomTimeout(), randomTimeUnit()); shouldThrow(); } catch (ExecutionException success) { assertSame(t.getClass(), success.getCause().getClass()); @@ -200,9 +200,9 @@ public class ForkJoinTask8Test extends J abstract static class BinaryAsyncAction extends ForkJoinTask { - private BinaryAsyncAction parent; + private volatile BinaryAsyncAction parent; - private BinaryAsyncAction sibling; + private volatile BinaryAsyncAction sibling; protected BinaryAsyncAction() { setForkJoinTaskTag(INITIAL_STATE); @@ -245,6 +245,14 @@ public class ForkJoinTask8Test extends J super.completeExceptionally(ex); } + public boolean cancel(boolean mayInterruptIfRunning) { + if (super.cancel(mayInterruptIfRunning)) { + completeExceptionally(new FJException()); + return true; + } + return false; + } + public final void complete() { BinaryAsyncAction a = this; for (;;) { @@ -267,13 +275,12 @@ public class ForkJoinTask8Test extends J } public final void completeExceptionally(Throwable ex) { - BinaryAsyncAction a = this; - while (!a.isCompletedAbnormally()) { + for (BinaryAsyncAction a = this;;) { a.completeThisExceptionally(ex); BinaryAsyncAction s = a.sibling; - if (s != null) - s.cancel(false); - if (!a.onException() || (a = a.parent) == null) + if (s != null && !s.isDone()) + s.completeExceptionally(ex); + if ((a = a.parent) == null) break; } } @@ -305,21 +312,20 @@ public class ForkJoinTask8Test extends J try { AsyncFib f = this; int n = f.number; - if (n > 1) { - while (n > 1) { - AsyncFib p = f; - AsyncFib r = new AsyncFib(n - 2); - f = new AsyncFib(--n); - p.linkSubtasks(r, f); - r.fork(); - } - f.number = n; + while (n > 1) { + AsyncFib p = f; + AsyncFib r = new AsyncFib(n - 2); + f = new AsyncFib(--n); + p.linkSubtasks(r, f); + r.fork(); } f.complete(); } catch (Throwable ex) { compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE); } + if (getForkJoinTaskTag() == EXCEPTION_STATE) + throw new FJException(); return false; } @@ -341,9 +347,9 @@ public class ForkJoinTask8Test extends J } public final boolean exec() { - FailingAsyncFib f = this; - int n = f.number; - if (n > 1) { + try { + FailingAsyncFib f = this; + int n = f.number; while (n > 1) { FailingAsyncFib p = f; FailingAsyncFib r = new FailingAsyncFib(n - 2); @@ -351,9 +357,13 @@ public class ForkJoinTask8Test extends J p.linkSubtasks(r, f); r.fork(); } - f.number = n; + f.complete(); } - f.complete(); + catch (Throwable ex) { + compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE); + } + if (getForkJoinTaskTag() == EXCEPTION_STATE) + throw new FJException(); return false; } @@ -479,7 +489,7 @@ public class ForkJoinTask8Test extends J AsyncFib f = new AsyncFib(8); assertSame(f, f.fork()); try { - f.get(5L, null); + f.get(randomTimeout(), null); shouldThrow(); } catch (NullPointerException success) {} }}; @@ -522,6 +532,8 @@ public class ForkJoinTask8Test extends J AsyncFib f = new AsyncFib(8); assertSame(f, f.fork()); helpQuiesce(); + while (!f.isDone()) // wait out race + ; assertEquals(0, getQueuedTaskCount()); f.checkCompletedNormally(); }}; @@ -863,14 +875,13 @@ public class ForkJoinTask8Test extends J RecursiveAction a = new CheckedRecursiveAction() { protected void realCompute() { AsyncFib nul = null; - Runnable[] throwingActions = { + assertThrows( + NullPointerException.class, () -> invokeAll(nul), () -> invokeAll(nul, nul), () -> invokeAll(new AsyncFib(8), new AsyncFib(9), nul), () -> invokeAll(new AsyncFib(8), nul, new AsyncFib(9)), - () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)), - }; - assertThrows(NullPointerException.class, throwingActions); + () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9))); }}; testInvokeOnPool(pool, a); } @@ -912,8 +923,8 @@ public class ForkJoinTask8Test extends J protected void realCompute() { AsyncFib f = new AsyncFib(8); FailingAsyncFib g = new FailingAsyncFib(9); - ForkJoinTask[] tasks = { f, g }; - Collections.shuffle(Arrays.asList(tasks)); + ForkJoinTask[] tasks = { f, g }; + shuffle(tasks); try { invokeAll(tasks[0], tasks[1]); shouldThrow(); @@ -939,8 +950,8 @@ public class ForkJoinTask8Test extends J AsyncFib f = new AsyncFib(8); FailingAsyncFib g = new FailingAsyncFib(9); AsyncFib h = new AsyncFib(7); - ForkJoinTask[] tasks = { f, g, h }; - Collections.shuffle(Arrays.asList(tasks)); + ForkJoinTask[] tasks = { f, g, h }; + shuffle(tasks); try { invokeAll(tasks[0], tasks[1], tasks[2]); shouldThrow(); @@ -966,8 +977,8 @@ public class ForkJoinTask8Test extends J FailingAsyncFib f = new FailingAsyncFib(8); AsyncFib g = new AsyncFib(9); AsyncFib h = new AsyncFib(7); - ForkJoinTask[] tasks = { f, g, h }; - Collections.shuffle(Arrays.asList(tasks)); + ForkJoinTask[] tasks = { f, g, h }; + shuffle(tasks); try { invokeAll(Arrays.asList(tasks)); shouldThrow(); @@ -1155,43 +1166,39 @@ public class ForkJoinTask8Test extends J } // jdk9 - + /** * pollSubmission returns unexecuted submitted task, if present */ public void testPollSubmission() { final CountDownLatch done = new CountDownLatch(1); - final ForkJoinTask a = ForkJoinTask.adapt(awaiter(done)); - final ForkJoinTask b = ForkJoinTask.adapt(awaiter(done)); - final ForkJoinTask c = ForkJoinTask.adapt(awaiter(done)); + final ForkJoinTask a = ForkJoinTask.adapt(awaiter(done)); + final ForkJoinTask b = ForkJoinTask.adapt(awaiter(done)); + final ForkJoinTask c = ForkJoinTask.adapt(awaiter(done)); final ForkJoinPool p = singletonPool(); - Thread external = new Thread() { - public void run() { + try (PoolCleaner cleaner = cleaner(p, done)) { + Thread external = new Thread(new CheckedRunnable() { + public void realRun() { p.execute(a); p.execute(b); p.execute(c); - }}; - RecursiveAction s = new CheckedRecursiveAction() { + }}); + RecursiveAction s = new CheckedRecursiveAction() { protected void realCompute() { external.start(); try { external.join(); - } catch(Exception ex) { + } catch (Exception ex) { threadUnexpectedException(ex); } assertTrue(p.hasQueuedSubmissions()); assertTrue(Thread.currentThread() instanceof ForkJoinWorkerThread); - ForkJoinTask r = ForkJoinTask.pollSubmission(); + ForkJoinTask r = ForkJoinTask.pollSubmission(); assertTrue(r == a || r == b || r == c); assertFalse(r.isDone()); }}; - try { p.invoke(s); - } finally { - done.countDown(); - joinPool(p); } } - }