--- jsr166/src/test/tck/RecursiveActionTest.java 2010/12/01 22:37:51 1.28 +++ jsr166/src/test/tck/RecursiveActionTest.java 2011/06/26 06:50:19 1.36 @@ -1,7 +1,7 @@ /* * 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.*; @@ -12,9 +12,11 @@ import java.util.concurrent.ForkJoinPool import java.util.concurrent.ForkJoinTask; import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.RecursiveAction; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static java.util.concurrent.TimeUnit.SECONDS; +import java.util.Arrays; import java.util.HashSet; public class RecursiveActionTest extends JSR166TestCase { @@ -134,7 +136,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)); @@ -143,26 +145,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 @@ -266,7 +269,7 @@ public class RecursiveActionTest extends assertEquals(21, f.result); checkCompletedNormally(f); - f.reinitialize(); + f = new FibAction(8); f.cancel(true); assertSame(f, f.fork()); myself.interrupt(); @@ -279,7 +282,7 @@ public class RecursiveActionTest extends checkCancelled(f); } - f.reinitialize(); + f = new FibAction(8); f.completeExceptionally(new FJException()); assertSame(f, f.fork()); myself.interrupt(); @@ -293,7 +296,7 @@ public class RecursiveActionTest extends } // test quietlyJoin() - f.reinitialize(); + f = new FibAction(8); assertSame(f, f.fork()); myself.interrupt(); assertTrue(myself.isInterrupted()); @@ -302,7 +305,7 @@ public class RecursiveActionTest extends assertEquals(21, f.result); checkCompletedNormally(f); - f.reinitialize(); + f = new FibAction(8); f.cancel(true); assertSame(f, f.fork()); myself.interrupt(); @@ -311,7 +314,7 @@ public class RecursiveActionTest extends Thread.interrupted(); checkCancelled(f); - f.reinitialize(); + f = new FibAction(8); f.completeExceptionally(new FJException()); assertSame(f, f.fork()); myself.interrupt(); @@ -489,7 +492,6 @@ public class RecursiveActionTest extends testInvokeOnPool(mainPool(), a); } - /** * helpQuiesce returns when tasks are complete. * getQueuedTaskCount returns 0 when quiescent @@ -499,7 +501,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); @@ -507,7 +509,6 @@ public class RecursiveActionTest extends testInvokeOnPool(mainPool(), a); } - /** * invoke task throws exception when task completes abnormally */ @@ -771,12 +772,12 @@ public class RecursiveActionTest extends ForkJoinWorkerThread w = (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 */ @@ -790,7 +791,7 @@ public class RecursiveActionTest extends } /** - * A reinitialized task may be re-invoked + * A reinitialized normally completed task may be re-invoked */ public void testReinitialize() { RecursiveAction a = new CheckedRecursiveAction() { @@ -810,6 +811,29 @@ public class RecursiveActionTest extends } /** + * A reinitialized abnormally completed task may be re-invoked + */ + public void testReinitializeAbnormal() { + RecursiveAction a = new CheckedRecursiveAction() { + public void realCompute() { + FailingFibAction f = new FailingFibAction(8); + checkNotDone(f); + + for (int i = 0; i < 3; i++) { + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + f.reinitialize(); + checkNotDone(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** * invoke task throws exception after invoking completeExceptionally */ public void testCompleteExceptionally() { @@ -923,7 +947,6 @@ public class RecursiveActionTest extends testInvokeOnPool(mainPool(), a); } - /** * invokeAll(tasks) with any null task throws NPE */ @@ -1174,4 +1197,45 @@ public class RecursiveActionTest extends testInvokeOnPool(asyncSingletonPool(), a); } + static class SortTask extends RecursiveAction { + final long[] array; final int lo, hi; + SortTask(long[] array, int lo, int hi) { + this.array = array; this.lo = lo; this.hi = hi; + } + final static int THRESHOLD = 100; + protected void compute() { + if (hi - lo < THRESHOLD) + sequentiallySort(array, lo, hi); + else { + int mid = (lo + hi) >>> 1; + invokeAll(new SortTask(array, lo, mid), + new SortTask(array, mid, hi)); + merge(array, lo, mid, hi); + } + } + static void sequentiallySort(long[] array, int lo, int hi) { + Arrays.sort(array, lo, hi); + } + static void merge(long[] array, int lo, int mid, int hi) { + long[] buf = Arrays.copyOfRange(array, lo, mid); + for (int i = 0, j = lo, k = mid; i < buf.length; j++) + array[j] = (k == hi || buf[i] < array[k]) ? + buf[i++] : array[k++]; + } + } + + /** + * SortTask demo works as advertised + */ + public void testSortTaskDemo() { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + long[] array = new long[1007]; + for (int i = 0; i < array.length; i++) + array[i] = rnd.nextLong(); + long[] arrayClone = array.clone(); + testInvokeOnPool(mainPool(), + new SortTask(array, 0, array.length)); + Arrays.sort(arrayClone); + assertTrue(Arrays.equals(array, arrayClone)); + } }