--- jsr166/src/test/tck/RecursiveActionTest.java 2010/11/23 06:33:26 1.25 +++ jsr166/src/test/tck/RecursiveActionTest.java 2011/05/27 19:13:51 1.31 @@ -1,13 +1,15 @@ /* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/licenses/publicdomain + * http://creativecommons.org/publicdomain/zero/1.0/ */ import junit.framework.*; import java.util.concurrent.CancellationException; +import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.RecursiveAction; import java.util.concurrent.TimeUnit; @@ -59,7 +61,7 @@ public class RecursiveActionTest extends assertNull(a.getException()); assertNull(a.getRawResult()); - if (! (Thread.currentThread() instanceof ForkJoinWorkerThread)) { + if (! ForkJoinTask.inForkJoinPool()) { Thread.currentThread().interrupt(); try { a.get(); @@ -132,7 +134,7 @@ public class RecursiveActionTest extends assertFalse(a.isCancelled()); assertFalse(a.isCompletedNormally()); assertTrue(a.isCompletedAbnormally()); - assertSame(t, a.getException()); + assertSame(t.getClass(), a.getException().getClass()); assertNull(a.getRawResult()); assertFalse(a.cancel(false)); assertFalse(a.cancel(true)); @@ -141,26 +143,27 @@ public class RecursiveActionTest extends a.join(); shouldThrow(); } catch (Throwable expected) { - assertSame(t, expected); + assertSame(expected.getClass(), t.getClass()); } try { a.get(); shouldThrow(); } catch (ExecutionException success) { - assertSame(t, success.getCause()); + assertSame(t.getClass(), success.getCause().getClass()); } catch (Throwable fail) { threadUnexpectedException(fail); } try { a.get(5L, SECONDS); shouldThrow(); } catch (ExecutionException success) { - assertSame(t, success.getCause()); + assertSame(t.getClass(), success.getCause().getClass()); } catch (Throwable fail) { threadUnexpectedException(fail); } } - static final class FJException extends RuntimeException { - FJException() { super(); } + public static final class FJException extends RuntimeException { + public FJException() { super(); } + public FJException(Throwable cause) { super(cause); } } // A simple recursive action for testing @@ -253,10 +256,12 @@ public class RecursiveActionTest extends RecursiveAction a = new CheckedRecursiveAction() { public void realCompute() { FibAction f = new FibAction(8); + final Thread myself = Thread.currentThread(); // test join() assertSame(f, f.fork()); - Thread.currentThread().interrupt(); + myself.interrupt(); + assertTrue(myself.isInterrupted()); assertNull(f.join()); Thread.interrupted(); assertEquals(21, f.result); @@ -265,7 +270,8 @@ public class RecursiveActionTest extends f.reinitialize(); f.cancel(true); assertSame(f, f.fork()); - Thread.currentThread().interrupt(); + myself.interrupt(); + assertTrue(myself.isInterrupted()); try { f.join(); shouldThrow(); @@ -277,7 +283,8 @@ public class RecursiveActionTest extends f.reinitialize(); f.completeExceptionally(new FJException()); assertSame(f, f.fork()); - Thread.currentThread().interrupt(); + myself.interrupt(); + assertTrue(myself.isInterrupted()); try { f.join(); shouldThrow(); @@ -289,7 +296,8 @@ public class RecursiveActionTest extends // test quietlyJoin() f.reinitialize(); assertSame(f, f.fork()); - Thread.currentThread().interrupt(); + myself.interrupt(); + assertTrue(myself.isInterrupted()); f.quietlyJoin(); Thread.interrupted(); assertEquals(21, f.result); @@ -298,7 +306,8 @@ public class RecursiveActionTest extends f.reinitialize(); f.cancel(true); assertSame(f, f.fork()); - Thread.currentThread().interrupt(); + myself.interrupt(); + assertTrue(myself.isInterrupted()); f.quietlyJoin(); Thread.interrupted(); checkCancelled(f); @@ -306,7 +315,8 @@ public class RecursiveActionTest extends f.reinitialize(); f.completeExceptionally(new FJException()); assertSame(f, f.fork()); - Thread.currentThread().interrupt(); + myself.interrupt(); + assertTrue(myself.isInterrupted()); f.quietlyJoin(); Thread.interrupted(); checkCompletedAbnormally(f, f.getException()); @@ -317,6 +327,109 @@ public class RecursiveActionTest extends } /** + * join/quietlyJoin of a forked task when not in ForkJoinPool + * succeeds in the presence of interrupts + */ + public void testJoinIgnoresInterruptsOutsideForkJoinPool() { + final SynchronousQueue sq = + new SynchronousQueue(); + RecursiveAction a = new CheckedRecursiveAction() { + public void realCompute() throws InterruptedException { + FibAction[] fibActions = new FibAction[6]; + for (int i = 0; i < fibActions.length; i++) + fibActions[i] = new FibAction(8); + + fibActions[1].cancel(false); + fibActions[2].completeExceptionally(new FJException()); + fibActions[4].cancel(true); + fibActions[5].completeExceptionally(new FJException()); + + for (int i = 0; i < fibActions.length; i++) + fibActions[i].fork(); + + sq.put(fibActions); + + helpQuiesce(); + }}; + + Runnable r = new CheckedRunnable() { + public void realRun() throws InterruptedException { + FibAction[] fibActions = sq.take(); + FibAction f; + final Thread myself = Thread.currentThread(); + + // test join() ------------ + + f = fibActions[0]; + assertFalse(ForkJoinTask.inForkJoinPool()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + assertNull(f.join()); + assertTrue(Thread.interrupted()); + assertEquals(21, f.result); + checkCompletedNormally(f); + + f = fibActions[1]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + assertTrue(Thread.interrupted()); + checkCancelled(f); + } + + f = fibActions[2]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + assertTrue(Thread.interrupted()); + checkCompletedAbnormally(f, success); + } + + // test quietlyJoin() --------- + + f = fibActions[3]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + assertTrue(Thread.interrupted()); + assertEquals(21, f.result); + checkCompletedNormally(f); + + f = fibActions[4]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + assertTrue(Thread.interrupted()); + checkCancelled(f); + + f = fibActions[5]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + assertTrue(Thread.interrupted()); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + + Thread t; + + t = newStartedThread(r); + testInvokeOnPool(mainPool(), a); + awaitTermination(t, LONG_DELAY_MS); + + a.reinitialize(); + t = newStartedThread(r); + testInvokeOnPool(singletonPool(), a); + awaitTermination(t, LONG_DELAY_MS); + } + + /** * get of a forked task returns when task completes */ public void testForkGet() { @@ -377,7 +490,6 @@ public class RecursiveActionTest extends testInvokeOnPool(mainPool(), a); } - /** * helpQuiesce returns when tasks are complete. * getQueuedTaskCount returns 0 when quiescent @@ -387,7 +499,7 @@ public class RecursiveActionTest extends public void realCompute() { FibAction f = new FibAction(8); assertSame(f, f.fork()); - f.helpQuiesce(); + helpQuiesce(); assertEquals(21, f.result); assertEquals(0, getQueuedTaskCount()); checkCompletedNormally(f); @@ -395,7 +507,6 @@ public class RecursiveActionTest extends testInvokeOnPool(mainPool(), a); } - /** * invoke task throws exception when task completes abnormally */ @@ -657,14 +768,14 @@ public class RecursiveActionTest extends RecursiveAction a = new CheckedRecursiveAction() { public void realCompute() { ForkJoinWorkerThread w = - (ForkJoinWorkerThread)(Thread.currentThread()); + (ForkJoinWorkerThread) Thread.currentThread(); assertTrue(w.getPoolIndex() >= 0); - assertTrue(w.getPoolIndex() < mainPool.getPoolSize()); + // pool size can shrink after assigning index, so cannot check + // assertTrue(w.getPoolIndex() < mainPool.getPoolSize()); }}; testInvokeOnPool(mainPool, a); } - /** * setRawResult(null) succeeds */ @@ -811,7 +922,6 @@ public class RecursiveActionTest extends testInvokeOnPool(mainPool(), a); } - /** * invokeAll(tasks) with any null task throws NPE */