ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
(Generate patch)

Comparing jsr166/src/test/tck/RecursiveActionTest.java (file contents):
Revision 1.24 by jsr166, Mon Nov 22 20:19:47 2010 UTC vs.
Revision 1.36 by jsr166, Sun Jun 26 06:50:19 2011 UTC

# Line 1 | Line 1
1   /*
2   * Written by Doug Lea with assistance from members of JCP JSR-166
3   * Expert Group and released to the public domain, as explained at
4 < * http://creativecommons.org/licenses/publicdomain
4 > * http://creativecommons.org/publicdomain/zero/1.0/
5   */
6  
7   import junit.framework.*;
8   import java.util.concurrent.CancellationException;
9 + import java.util.concurrent.SynchronousQueue;
10   import java.util.concurrent.ExecutionException;
11   import java.util.concurrent.ForkJoinPool;
12 + import java.util.concurrent.ForkJoinTask;
13   import java.util.concurrent.ForkJoinWorkerThread;
14   import java.util.concurrent.RecursiveAction;
15 + import java.util.concurrent.ThreadLocalRandom;
16   import java.util.concurrent.TimeUnit;
17   import java.util.concurrent.TimeoutException;
18   import static java.util.concurrent.TimeUnit.SECONDS;
19 + import java.util.Arrays;
20   import java.util.HashSet;
21  
22   public class RecursiveActionTest extends JSR166TestCase {
# Line 59 | Line 63 | public class RecursiveActionTest extends
63          assertNull(a.getException());
64          assertNull(a.getRawResult());
65  
66 <        if (! (Thread.currentThread() instanceof ForkJoinWorkerThread)) {
66 >        if (! ForkJoinTask.inForkJoinPool()) {
67              Thread.currentThread().interrupt();
68              try {
69                  a.get();
# Line 132 | Line 136 | public class RecursiveActionTest extends
136          assertFalse(a.isCancelled());
137          assertFalse(a.isCompletedNormally());
138          assertTrue(a.isCompletedAbnormally());
139 <        assertSame(t, a.getException());
139 >        assertSame(t.getClass(), a.getException().getClass());
140          assertNull(a.getRawResult());
141          assertFalse(a.cancel(false));
142          assertFalse(a.cancel(true));
# Line 141 | Line 145 | public class RecursiveActionTest extends
145              a.join();
146              shouldThrow();
147          } catch (Throwable expected) {
148 <            assertSame(t, expected);
148 >            assertSame(expected.getClass(), t.getClass());
149          }
150  
151          try {
152              a.get();
153              shouldThrow();
154          } catch (ExecutionException success) {
155 <            assertSame(t, success.getCause());
155 >            assertSame(t.getClass(), success.getCause().getClass());
156          } catch (Throwable fail) { threadUnexpectedException(fail); }
157  
158          try {
159              a.get(5L, SECONDS);
160              shouldThrow();
161          } catch (ExecutionException success) {
162 <            assertSame(t, success.getCause());
162 >            assertSame(t.getClass(), success.getCause().getClass());
163          } catch (Throwable fail) { threadUnexpectedException(fail); }
164      }
165  
166 <    static final class FJException extends RuntimeException {
167 <        FJException() { super(); }
166 >    public static final class FJException extends RuntimeException {
167 >        public FJException() { super(); }
168 >        public FJException(Throwable cause) { super(cause); }
169      }
170  
171      // A simple recursive action for testing
# Line 247 | Line 252 | public class RecursiveActionTest extends
252      }
253  
254      /**
255 <     * join/quietlyJoin of a forked task ignores interrupts
255 >     * join/quietlyJoin of a forked task succeeds in the presence of interrupts
256       */
257      public void testJoinIgnoresInterrupts() {
258          RecursiveAction a = new CheckedRecursiveAction() {
259              public void realCompute() {
260                  FibAction f = new FibAction(8);
261 +                final Thread myself = Thread.currentThread();
262  
263                  // test join()
264                  assertSame(f, f.fork());
265 <                Thread.currentThread().interrupt();
265 >                myself.interrupt();
266 >                assertTrue(myself.isInterrupted());
267                  assertNull(f.join());
268 <                assertTrue(Thread.interrupted());
268 >                Thread.interrupted();
269                  assertEquals(21, f.result);
270                  checkCompletedNormally(f);
271  
272 <                f.reinitialize();
272 >                f = new FibAction(8);
273                  f.cancel(true);
274                  assertSame(f, f.fork());
275 <                Thread.currentThread().interrupt();
275 >                myself.interrupt();
276 >                assertTrue(myself.isInterrupted());
277                  try {
278                      f.join();
279                      shouldThrow();
280                  } catch (CancellationException success) {
281 <                    assertTrue(Thread.interrupted());
281 >                    Thread.interrupted();
282                      checkCancelled(f);
283                  }
284  
285 <                f.reinitialize();
285 >                f = new FibAction(8);
286                  f.completeExceptionally(new FJException());
287                  assertSame(f, f.fork());
288 <                Thread.currentThread().interrupt();
288 >                myself.interrupt();
289 >                assertTrue(myself.isInterrupted());
290                  try {
291                      f.join();
292                      shouldThrow();
293                  } catch (FJException success) {
294 <                    assertTrue(Thread.interrupted());
294 >                    Thread.interrupted();
295                      checkCompletedAbnormally(f, success);
296                  }
297  
298                  // test quietlyJoin()
299 <                f.reinitialize();
299 >                f = new FibAction(8);
300                  assertSame(f, f.fork());
301 <                Thread.currentThread().interrupt();
301 >                myself.interrupt();
302 >                assertTrue(myself.isInterrupted());
303                  f.quietlyJoin();
304 <                assertTrue(Thread.interrupted());
304 >                Thread.interrupted();
305                  assertEquals(21, f.result);
306                  checkCompletedNormally(f);
307  
308 <                f.reinitialize();
308 >                f = new FibAction(8);
309                  f.cancel(true);
310                  assertSame(f, f.fork());
311 <                Thread.currentThread().interrupt();
311 >                myself.interrupt();
312 >                assertTrue(myself.isInterrupted());
313                  f.quietlyJoin();
314 <                assertTrue(Thread.interrupted());
314 >                Thread.interrupted();
315                  checkCancelled(f);
316  
317 <                f.reinitialize();
317 >                f = new FibAction(8);
318                  f.completeExceptionally(new FJException());
319                  assertSame(f, f.fork());
320 <                Thread.currentThread().interrupt();
320 >                myself.interrupt();
321 >                assertTrue(myself.isInterrupted());
322 >                f.quietlyJoin();
323 >                Thread.interrupted();
324 >                checkCompletedAbnormally(f, f.getException());
325 >            }};
326 >        testInvokeOnPool(mainPool(), a);
327 >        a.reinitialize();
328 >        testInvokeOnPool(singletonPool(), a);
329 >    }
330 >
331 >    /**
332 >     * join/quietlyJoin of a forked task when not in ForkJoinPool
333 >     * succeeds in the presence of interrupts
334 >     */
335 >    public void testJoinIgnoresInterruptsOutsideForkJoinPool() {
336 >        final SynchronousQueue<FibAction[]> sq =
337 >            new SynchronousQueue<FibAction[]>();
338 >        RecursiveAction a = new CheckedRecursiveAction() {
339 >            public void realCompute() throws InterruptedException {
340 >                FibAction[] fibActions = new FibAction[6];
341 >                for (int i = 0; i < fibActions.length; i++)
342 >                    fibActions[i] = new FibAction(8);
343 >
344 >                fibActions[1].cancel(false);
345 >                fibActions[2].completeExceptionally(new FJException());
346 >                fibActions[4].cancel(true);
347 >                fibActions[5].completeExceptionally(new FJException());
348 >
349 >                for (int i = 0; i < fibActions.length; i++)
350 >                    fibActions[i].fork();
351 >
352 >                sq.put(fibActions);
353 >
354 >                helpQuiesce();
355 >            }};
356 >
357 >        Runnable r = new CheckedRunnable() {
358 >            public void realRun() throws InterruptedException {
359 >                FibAction[] fibActions = sq.take();
360 >                FibAction f;
361 >                final Thread myself = Thread.currentThread();
362 >
363 >                // test join() ------------
364 >
365 >                f = fibActions[0];
366 >                assertFalse(ForkJoinTask.inForkJoinPool());
367 >                myself.interrupt();
368 >                assertTrue(myself.isInterrupted());
369 >                assertNull(f.join());
370 >                assertTrue(Thread.interrupted());
371 >                assertEquals(21, f.result);
372 >                checkCompletedNormally(f);
373 >
374 >                f = fibActions[1];
375 >                myself.interrupt();
376 >                assertTrue(myself.isInterrupted());
377 >                try {
378 >                    f.join();
379 >                    shouldThrow();
380 >                } catch (CancellationException success) {
381 >                    assertTrue(Thread.interrupted());
382 >                    checkCancelled(f);
383 >                }
384 >
385 >                f = fibActions[2];
386 >                myself.interrupt();
387 >                assertTrue(myself.isInterrupted());
388 >                try {
389 >                    f.join();
390 >                    shouldThrow();
391 >                } catch (FJException success) {
392 >                    assertTrue(Thread.interrupted());
393 >                    checkCompletedAbnormally(f, success);
394 >                }
395 >
396 >                // test quietlyJoin() ---------
397 >
398 >                f = fibActions[3];
399 >                myself.interrupt();
400 >                assertTrue(myself.isInterrupted());
401 >                f.quietlyJoin();
402 >                assertTrue(Thread.interrupted());
403 >                assertEquals(21, f.result);
404 >                checkCompletedNormally(f);
405 >
406 >                f = fibActions[4];
407 >                myself.interrupt();
408 >                assertTrue(myself.isInterrupted());
409                  f.quietlyJoin();
410                  assertTrue(Thread.interrupted());
411 +                checkCancelled(f);
412 +
413 +                f = fibActions[5];
414 +                myself.interrupt();
415 +                assertTrue(myself.isInterrupted());
416 +                f.quietlyJoin();
417 +                assertTrue(Thread.interrupted());
418 +                assertTrue(f.getException() instanceof FJException);
419                  checkCompletedAbnormally(f, f.getException());
420              }};
421 +
422 +        Thread t;
423 +
424 +        t = newStartedThread(r);
425          testInvokeOnPool(mainPool(), a);
426 +        awaitTermination(t, LONG_DELAY_MS);
427 +
428          a.reinitialize();
429 +        t = newStartedThread(r);
430          testInvokeOnPool(singletonPool(), a);
431 +        awaitTermination(t, LONG_DELAY_MS);
432      }
433  
434      /**
# Line 377 | Line 492 | public class RecursiveActionTest extends
492          testInvokeOnPool(mainPool(), a);
493      }
494  
380
495      /**
496       * helpQuiesce returns when tasks are complete.
497       * getQueuedTaskCount returns 0 when quiescent
# Line 387 | Line 501 | public class RecursiveActionTest extends
501              public void realCompute() {
502                  FibAction f = new FibAction(8);
503                  assertSame(f, f.fork());
504 <                f.helpQuiesce();
504 >                helpQuiesce();
505                  assertEquals(21, f.result);
506                  assertEquals(0, getQueuedTaskCount());
507                  checkCompletedNormally(f);
# Line 395 | Line 509 | public class RecursiveActionTest extends
509          testInvokeOnPool(mainPool(), a);
510      }
511  
398
512      /**
513       * invoke task throws exception when task completes abnormally
514       */
# Line 657 | Line 770 | public class RecursiveActionTest extends
770          RecursiveAction a = new CheckedRecursiveAction() {
771              public void realCompute() {
772                  ForkJoinWorkerThread w =
773 <                    (ForkJoinWorkerThread)(Thread.currentThread());
773 >                    (ForkJoinWorkerThread) Thread.currentThread();
774                  assertTrue(w.getPoolIndex() >= 0);
775 <                assertTrue(w.getPoolIndex() < mainPool.getPoolSize());
775 >                // pool size can shrink after assigning index, so cannot check
776 >                // assertTrue(w.getPoolIndex() < mainPool.getPoolSize());
777              }};
778          testInvokeOnPool(mainPool, a);
779      }
780  
667
781      /**
782       * setRawResult(null) succeeds
783       */
# Line 678 | Line 791 | public class RecursiveActionTest extends
791      }
792  
793      /**
794 <     * A reinitialized task may be re-invoked
794 >     * A reinitialized normally completed task may be re-invoked
795       */
796      public void testReinitialize() {
797          RecursiveAction a = new CheckedRecursiveAction() {
# Line 698 | Line 811 | public class RecursiveActionTest extends
811      }
812  
813      /**
814 +     * A reinitialized abnormally completed task may be re-invoked
815 +     */
816 +    public void testReinitializeAbnormal() {
817 +        RecursiveAction a = new CheckedRecursiveAction() {
818 +            public void realCompute() {
819 +                FailingFibAction f = new FailingFibAction(8);
820 +                checkNotDone(f);
821 +
822 +                for (int i = 0; i < 3; i++) {
823 +                    try {
824 +                        f.invoke();
825 +                        shouldThrow();
826 +                    } catch (FJException success) {
827 +                        checkCompletedAbnormally(f, success);
828 +                    }
829 +                    f.reinitialize();
830 +                    checkNotDone(f);
831 +                }
832 +            }};
833 +        testInvokeOnPool(mainPool(), a);
834 +    }
835 +
836 +    /**
837       * invoke task throws exception after invoking completeExceptionally
838       */
839      public void testCompleteExceptionally() {
# Line 811 | Line 947 | public class RecursiveActionTest extends
947          testInvokeOnPool(mainPool(), a);
948      }
949  
814
950      /**
951       * invokeAll(tasks) with any null task throws NPE
952       */
# Line 1062 | Line 1197 | public class RecursiveActionTest extends
1197          testInvokeOnPool(asyncSingletonPool(), a);
1198      }
1199  
1200 +    static class SortTask extends RecursiveAction {
1201 +        final long[] array; final int lo, hi;
1202 +        SortTask(long[] array, int lo, int hi) {
1203 +            this.array = array; this.lo = lo; this.hi = hi;
1204 +        }
1205 +        final static int THRESHOLD = 100;
1206 +        protected void compute() {
1207 +            if (hi - lo < THRESHOLD)
1208 +                sequentiallySort(array, lo, hi);
1209 +            else {
1210 +                int mid = (lo + hi) >>> 1;
1211 +                invokeAll(new SortTask(array, lo, mid),
1212 +                          new SortTask(array, mid, hi));
1213 +                merge(array, lo, mid, hi);
1214 +            }
1215 +        }
1216 +        static void sequentiallySort(long[] array, int lo, int hi) {
1217 +            Arrays.sort(array, lo, hi);
1218 +        }
1219 +        static void merge(long[] array, int lo, int mid, int hi) {
1220 +            long[] buf = Arrays.copyOfRange(array, lo, mid);
1221 +            for (int i = 0, j = lo, k = mid; i < buf.length; j++)
1222 +                array[j] = (k == hi || buf[i] < array[k]) ?
1223 +                    buf[i++] : array[k++];
1224 +        }
1225 +    }
1226 +
1227 +    /**
1228 +     * SortTask demo works as advertised
1229 +     */
1230 +    public void testSortTaskDemo() {
1231 +        ThreadLocalRandom rnd = ThreadLocalRandom.current();
1232 +        long[] array = new long[1007];
1233 +        for (int i = 0; i < array.length; i++)
1234 +            array[i] = rnd.nextLong();
1235 +        long[] arrayClone = array.clone();
1236 +        testInvokeOnPool(mainPool(),
1237 +                         new SortTask(array, 0, array.length));
1238 +        Arrays.sort(arrayClone);
1239 +        assertTrue(Arrays.equals(array, arrayClone));
1240 +    }
1241   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines