ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
Revision: 1.40
Committed: Wed Dec 31 19:05:43 2014 UTC (9 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.39: +9 -6 lines
Log Message:
no wildcard imports

File Contents

# Content
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/publicdomain/zero/1.0/
5 */
6
7 import static java.util.concurrent.TimeUnit.SECONDS;
8
9 import java.util.Arrays;
10 import java.util.HashSet;
11 import java.util.concurrent.CancellationException;
12 import java.util.concurrent.ExecutionException;
13 import java.util.concurrent.ForkJoinPool;
14 import java.util.concurrent.ForkJoinTask;
15 import java.util.concurrent.ForkJoinWorkerThread;
16 import java.util.concurrent.RecursiveAction;
17 import java.util.concurrent.SynchronousQueue;
18 import java.util.concurrent.ThreadLocalRandom;
19 import java.util.concurrent.TimeoutException;
20 import java.util.concurrent.TimeUnit;
21
22 import junit.framework.Test;
23 import junit.framework.TestSuite;
24
25 public class RecursiveActionTest extends JSR166TestCase {
26
27 public static void main(String[] args) {
28 junit.textui.TestRunner.run(suite());
29 }
30
31 public static Test suite() {
32 return new TestSuite(RecursiveActionTest.class);
33 }
34
35 private static ForkJoinPool mainPool() {
36 return new ForkJoinPool();
37 }
38
39 private static ForkJoinPool singletonPool() {
40 return new ForkJoinPool(1);
41 }
42
43 private static ForkJoinPool asyncSingletonPool() {
44 return new ForkJoinPool(1,
45 ForkJoinPool.defaultForkJoinWorkerThreadFactory,
46 null, true);
47 }
48
49 private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) {
50 try {
51 checkNotDone(a);
52
53 assertNull(pool.invoke(a));
54
55 checkCompletedNormally(a);
56 } finally {
57 joinPool(pool);
58 }
59 }
60
61 void checkNotDone(RecursiveAction a) {
62 assertFalse(a.isDone());
63 assertFalse(a.isCompletedNormally());
64 assertFalse(a.isCompletedAbnormally());
65 assertFalse(a.isCancelled());
66 assertNull(a.getException());
67 assertNull(a.getRawResult());
68
69 if (! ForkJoinTask.inForkJoinPool()) {
70 Thread.currentThread().interrupt();
71 try {
72 a.get();
73 shouldThrow();
74 } catch (InterruptedException success) {
75 } catch (Throwable fail) { threadUnexpectedException(fail); }
76
77 Thread.currentThread().interrupt();
78 try {
79 a.get(5L, SECONDS);
80 shouldThrow();
81 } catch (InterruptedException success) {
82 } catch (Throwable fail) { threadUnexpectedException(fail); }
83 }
84
85 try {
86 a.get(0L, SECONDS);
87 shouldThrow();
88 } catch (TimeoutException success) {
89 } catch (Throwable fail) { threadUnexpectedException(fail); }
90 }
91
92 void checkCompletedNormally(RecursiveAction a) {
93 assertTrue(a.isDone());
94 assertFalse(a.isCancelled());
95 assertTrue(a.isCompletedNormally());
96 assertFalse(a.isCompletedAbnormally());
97 assertNull(a.getException());
98 assertNull(a.getRawResult());
99 assertNull(a.join());
100 assertFalse(a.cancel(false));
101 assertFalse(a.cancel(true));
102 try {
103 assertNull(a.get());
104 } catch (Throwable fail) { threadUnexpectedException(fail); }
105 try {
106 assertNull(a.get(5L, SECONDS));
107 } catch (Throwable fail) { threadUnexpectedException(fail); }
108 }
109
110 void checkCancelled(RecursiveAction a) {
111 assertTrue(a.isDone());
112 assertTrue(a.isCancelled());
113 assertFalse(a.isCompletedNormally());
114 assertTrue(a.isCompletedAbnormally());
115 assertTrue(a.getException() instanceof CancellationException);
116 assertNull(a.getRawResult());
117
118 try {
119 a.join();
120 shouldThrow();
121 } catch (CancellationException success) {
122 } catch (Throwable fail) { threadUnexpectedException(fail); }
123
124 try {
125 a.get();
126 shouldThrow();
127 } catch (CancellationException success) {
128 } catch (Throwable fail) { threadUnexpectedException(fail); }
129
130 try {
131 a.get(5L, SECONDS);
132 shouldThrow();
133 } catch (CancellationException success) {
134 } catch (Throwable fail) { threadUnexpectedException(fail); }
135 }
136
137 void checkCompletedAbnormally(RecursiveAction a, Throwable t) {
138 assertTrue(a.isDone());
139 assertFalse(a.isCancelled());
140 assertFalse(a.isCompletedNormally());
141 assertTrue(a.isCompletedAbnormally());
142 assertSame(t.getClass(), a.getException().getClass());
143 assertNull(a.getRawResult());
144 assertFalse(a.cancel(false));
145 assertFalse(a.cancel(true));
146
147 try {
148 a.join();
149 shouldThrow();
150 } catch (Throwable expected) {
151 assertSame(expected.getClass(), t.getClass());
152 }
153
154 try {
155 a.get();
156 shouldThrow();
157 } catch (ExecutionException success) {
158 assertSame(t.getClass(), success.getCause().getClass());
159 } catch (Throwable fail) { threadUnexpectedException(fail); }
160
161 try {
162 a.get(5L, SECONDS);
163 shouldThrow();
164 } catch (ExecutionException success) {
165 assertSame(t.getClass(), success.getCause().getClass());
166 } catch (Throwable fail) { threadUnexpectedException(fail); }
167 }
168
169 public static final class FJException extends RuntimeException {
170 public FJException() { super(); }
171 public FJException(Throwable cause) { super(cause); }
172 }
173
174 // A simple recursive action for testing
175 final class FibAction extends CheckedRecursiveAction {
176 final int number;
177 int result;
178 FibAction(int n) { number = n; }
179 protected void realCompute() {
180 int n = number;
181 if (n <= 1)
182 result = n;
183 else {
184 FibAction f1 = new FibAction(n - 1);
185 FibAction f2 = new FibAction(n - 2);
186 invokeAll(f1, f2);
187 result = f1.result + f2.result;
188 }
189 }
190 }
191
192 // A recursive action failing in base case
193 static final class FailingFibAction extends RecursiveAction {
194 final int number;
195 int result;
196 FailingFibAction(int n) { number = n; }
197 public void compute() {
198 int n = number;
199 if (n <= 1)
200 throw new FJException();
201 else {
202 FailingFibAction f1 = new FailingFibAction(n - 1);
203 FailingFibAction f2 = new FailingFibAction(n - 2);
204 invokeAll(f1, f2);
205 result = f1.result + f2.result;
206 }
207 }
208 }
209
210 /**
211 * invoke returns when task completes normally.
212 * isCompletedAbnormally and isCancelled return false for normally
213 * completed tasks. getRawResult of a RecursiveAction returns null;
214 */
215 public void testInvoke() {
216 RecursiveAction a = new CheckedRecursiveAction() {
217 protected void realCompute() {
218 FibAction f = new FibAction(8);
219 assertNull(f.invoke());
220 assertEquals(21, f.result);
221 checkCompletedNormally(f);
222 }};
223 testInvokeOnPool(mainPool(), a);
224 }
225
226 /**
227 * quietlyInvoke task returns when task completes normally.
228 * isCompletedAbnormally and isCancelled return false for normally
229 * completed tasks
230 */
231 public void testQuietlyInvoke() {
232 RecursiveAction a = new CheckedRecursiveAction() {
233 protected void realCompute() {
234 FibAction f = new FibAction(8);
235 f.quietlyInvoke();
236 assertEquals(21, f.result);
237 checkCompletedNormally(f);
238 }};
239 testInvokeOnPool(mainPool(), a);
240 }
241
242 /**
243 * join of a forked task returns when task completes
244 */
245 public void testForkJoin() {
246 RecursiveAction a = new CheckedRecursiveAction() {
247 protected void realCompute() {
248 FibAction f = new FibAction(8);
249 assertSame(f, f.fork());
250 assertNull(f.join());
251 assertEquals(21, f.result);
252 checkCompletedNormally(f);
253 }};
254 testInvokeOnPool(mainPool(), a);
255 }
256
257 /**
258 * join/quietlyJoin of a forked task succeeds in the presence of interrupts
259 */
260 public void testJoinIgnoresInterrupts() {
261 RecursiveAction a = new CheckedRecursiveAction() {
262 protected void realCompute() {
263 FibAction f = new FibAction(8);
264 final Thread myself = Thread.currentThread();
265
266 // test join()
267 assertSame(f, f.fork());
268 myself.interrupt();
269 assertTrue(myself.isInterrupted());
270 assertNull(f.join());
271 Thread.interrupted();
272 assertEquals(21, f.result);
273 checkCompletedNormally(f);
274
275 f = new FibAction(8);
276 f.cancel(true);
277 assertSame(f, f.fork());
278 myself.interrupt();
279 assertTrue(myself.isInterrupted());
280 try {
281 f.join();
282 shouldThrow();
283 } catch (CancellationException success) {
284 Thread.interrupted();
285 checkCancelled(f);
286 }
287
288 f = new FibAction(8);
289 f.completeExceptionally(new FJException());
290 assertSame(f, f.fork());
291 myself.interrupt();
292 assertTrue(myself.isInterrupted());
293 try {
294 f.join();
295 shouldThrow();
296 } catch (FJException success) {
297 Thread.interrupted();
298 checkCompletedAbnormally(f, success);
299 }
300
301 // test quietlyJoin()
302 f = new FibAction(8);
303 assertSame(f, f.fork());
304 myself.interrupt();
305 assertTrue(myself.isInterrupted());
306 f.quietlyJoin();
307 Thread.interrupted();
308 assertEquals(21, f.result);
309 checkCompletedNormally(f);
310
311 f = new FibAction(8);
312 f.cancel(true);
313 assertSame(f, f.fork());
314 myself.interrupt();
315 assertTrue(myself.isInterrupted());
316 f.quietlyJoin();
317 Thread.interrupted();
318 checkCancelled(f);
319
320 f = new FibAction(8);
321 f.completeExceptionally(new FJException());
322 assertSame(f, f.fork());
323 myself.interrupt();
324 assertTrue(myself.isInterrupted());
325 f.quietlyJoin();
326 Thread.interrupted();
327 checkCompletedAbnormally(f, f.getException());
328 }};
329 testInvokeOnPool(mainPool(), a);
330 a.reinitialize();
331 testInvokeOnPool(singletonPool(), a);
332 }
333
334 /**
335 * join/quietlyJoin of a forked task when not in ForkJoinPool
336 * succeeds in the presence of interrupts
337 */
338 public void testJoinIgnoresInterruptsOutsideForkJoinPool() {
339 final SynchronousQueue<FibAction[]> sq =
340 new SynchronousQueue<FibAction[]>();
341 RecursiveAction a = new CheckedRecursiveAction() {
342 protected void realCompute() throws InterruptedException {
343 FibAction[] fibActions = new FibAction[6];
344 for (int i = 0; i < fibActions.length; i++)
345 fibActions[i] = new FibAction(8);
346
347 fibActions[1].cancel(false);
348 fibActions[2].completeExceptionally(new FJException());
349 fibActions[4].cancel(true);
350 fibActions[5].completeExceptionally(new FJException());
351
352 for (int i = 0; i < fibActions.length; i++)
353 fibActions[i].fork();
354
355 sq.put(fibActions);
356
357 helpQuiesce();
358 }};
359
360 Runnable r = new CheckedRunnable() {
361 public void realRun() throws InterruptedException {
362 FibAction[] fibActions = sq.take();
363 FibAction f;
364 final Thread myself = Thread.currentThread();
365
366 // test join() ------------
367
368 f = fibActions[0];
369 assertFalse(ForkJoinTask.inForkJoinPool());
370 myself.interrupt();
371 assertTrue(myself.isInterrupted());
372 assertNull(f.join());
373 assertTrue(Thread.interrupted());
374 assertEquals(21, f.result);
375 checkCompletedNormally(f);
376
377 f = fibActions[1];
378 myself.interrupt();
379 assertTrue(myself.isInterrupted());
380 try {
381 f.join();
382 shouldThrow();
383 } catch (CancellationException success) {
384 assertTrue(Thread.interrupted());
385 checkCancelled(f);
386 }
387
388 f = fibActions[2];
389 myself.interrupt();
390 assertTrue(myself.isInterrupted());
391 try {
392 f.join();
393 shouldThrow();
394 } catch (FJException success) {
395 assertTrue(Thread.interrupted());
396 checkCompletedAbnormally(f, success);
397 }
398
399 // test quietlyJoin() ---------
400
401 f = fibActions[3];
402 myself.interrupt();
403 assertTrue(myself.isInterrupted());
404 f.quietlyJoin();
405 assertTrue(Thread.interrupted());
406 assertEquals(21, f.result);
407 checkCompletedNormally(f);
408
409 f = fibActions[4];
410 myself.interrupt();
411 assertTrue(myself.isInterrupted());
412 f.quietlyJoin();
413 assertTrue(Thread.interrupted());
414 checkCancelled(f);
415
416 f = fibActions[5];
417 myself.interrupt();
418 assertTrue(myself.isInterrupted());
419 f.quietlyJoin();
420 assertTrue(Thread.interrupted());
421 assertTrue(f.getException() instanceof FJException);
422 checkCompletedAbnormally(f, f.getException());
423 }};
424
425 Thread t;
426
427 t = newStartedThread(r);
428 testInvokeOnPool(mainPool(), a);
429 awaitTermination(t, LONG_DELAY_MS);
430
431 a.reinitialize();
432 t = newStartedThread(r);
433 testInvokeOnPool(singletonPool(), a);
434 awaitTermination(t, LONG_DELAY_MS);
435 }
436
437 /**
438 * get of a forked task returns when task completes
439 */
440 public void testForkGet() {
441 RecursiveAction a = new CheckedRecursiveAction() {
442 protected void realCompute() throws Exception {
443 FibAction f = new FibAction(8);
444 assertSame(f, f.fork());
445 assertNull(f.get());
446 assertEquals(21, f.result);
447 checkCompletedNormally(f);
448 }};
449 testInvokeOnPool(mainPool(), a);
450 }
451
452 /**
453 * timed get of a forked task returns when task completes
454 */
455 public void testForkTimedGet() {
456 RecursiveAction a = new CheckedRecursiveAction() {
457 protected void realCompute() throws Exception {
458 FibAction f = new FibAction(8);
459 assertSame(f, f.fork());
460 assertNull(f.get(5L, SECONDS));
461 assertEquals(21, f.result);
462 checkCompletedNormally(f);
463 }};
464 testInvokeOnPool(mainPool(), a);
465 }
466
467 /**
468 * timed get with null time unit throws NPE
469 */
470 public void testForkTimedGetNPE() {
471 RecursiveAction a = new CheckedRecursiveAction() {
472 protected void realCompute() throws Exception {
473 FibAction f = new FibAction(8);
474 assertSame(f, f.fork());
475 try {
476 f.get(5L, null);
477 shouldThrow();
478 } catch (NullPointerException success) {}
479 }};
480 testInvokeOnPool(mainPool(), a);
481 }
482
483 /**
484 * quietlyJoin of a forked task returns when task completes
485 */
486 public void testForkQuietlyJoin() {
487 RecursiveAction a = new CheckedRecursiveAction() {
488 protected void realCompute() {
489 FibAction f = new FibAction(8);
490 assertSame(f, f.fork());
491 f.quietlyJoin();
492 assertEquals(21, f.result);
493 checkCompletedNormally(f);
494 }};
495 testInvokeOnPool(mainPool(), a);
496 }
497
498 /**
499 * helpQuiesce returns when tasks are complete.
500 * getQueuedTaskCount returns 0 when quiescent
501 */
502 public void testForkHelpQuiesce() {
503 RecursiveAction a = new CheckedRecursiveAction() {
504 protected void realCompute() {
505 FibAction f = new FibAction(8);
506 assertSame(f, f.fork());
507 helpQuiesce();
508 assertEquals(21, f.result);
509 assertEquals(0, getQueuedTaskCount());
510 checkCompletedNormally(f);
511 }};
512 testInvokeOnPool(mainPool(), a);
513 }
514
515 /**
516 * invoke task throws exception when task completes abnormally
517 */
518 public void testAbnormalInvoke() {
519 RecursiveAction a = new CheckedRecursiveAction() {
520 protected void realCompute() {
521 FailingFibAction f = new FailingFibAction(8);
522 try {
523 f.invoke();
524 shouldThrow();
525 } catch (FJException success) {
526 checkCompletedAbnormally(f, success);
527 }
528 }};
529 testInvokeOnPool(mainPool(), a);
530 }
531
532 /**
533 * quietlyInvoke task returns when task completes abnormally
534 */
535 public void testAbnormalQuietlyInvoke() {
536 RecursiveAction a = new CheckedRecursiveAction() {
537 protected void realCompute() {
538 FailingFibAction f = new FailingFibAction(8);
539 f.quietlyInvoke();
540 assertTrue(f.getException() instanceof FJException);
541 checkCompletedAbnormally(f, f.getException());
542 }};
543 testInvokeOnPool(mainPool(), a);
544 }
545
546 /**
547 * join of a forked task throws exception when task completes abnormally
548 */
549 public void testAbnormalForkJoin() {
550 RecursiveAction a = new CheckedRecursiveAction() {
551 protected void realCompute() {
552 FailingFibAction f = new FailingFibAction(8);
553 assertSame(f, f.fork());
554 try {
555 f.join();
556 shouldThrow();
557 } catch (FJException success) {
558 checkCompletedAbnormally(f, success);
559 }
560 }};
561 testInvokeOnPool(mainPool(), a);
562 }
563
564 /**
565 * get of a forked task throws exception when task completes abnormally
566 */
567 public void testAbnormalForkGet() {
568 RecursiveAction a = new CheckedRecursiveAction() {
569 protected void realCompute() throws Exception {
570 FailingFibAction f = new FailingFibAction(8);
571 assertSame(f, f.fork());
572 try {
573 f.get();
574 shouldThrow();
575 } catch (ExecutionException success) {
576 Throwable cause = success.getCause();
577 assertTrue(cause instanceof FJException);
578 checkCompletedAbnormally(f, cause);
579 }
580 }};
581 testInvokeOnPool(mainPool(), a);
582 }
583
584 /**
585 * timed get of a forked task throws exception when task completes abnormally
586 */
587 public void testAbnormalForkTimedGet() {
588 RecursiveAction a = new CheckedRecursiveAction() {
589 protected void realCompute() throws Exception {
590 FailingFibAction f = new FailingFibAction(8);
591 assertSame(f, f.fork());
592 try {
593 f.get(5L, TimeUnit.SECONDS);
594 shouldThrow();
595 } catch (ExecutionException success) {
596 Throwable cause = success.getCause();
597 assertTrue(cause instanceof FJException);
598 checkCompletedAbnormally(f, cause);
599 }
600 }};
601 testInvokeOnPool(mainPool(), a);
602 }
603
604 /**
605 * quietlyJoin of a forked task returns when task completes abnormally
606 */
607 public void testAbnormalForkQuietlyJoin() {
608 RecursiveAction a = new CheckedRecursiveAction() {
609 protected void realCompute() {
610 FailingFibAction f = new FailingFibAction(8);
611 assertSame(f, f.fork());
612 f.quietlyJoin();
613 assertTrue(f.getException() instanceof FJException);
614 checkCompletedAbnormally(f, f.getException());
615 }};
616 testInvokeOnPool(mainPool(), a);
617 }
618
619 /**
620 * invoke task throws exception when task cancelled
621 */
622 public void testCancelledInvoke() {
623 RecursiveAction a = new CheckedRecursiveAction() {
624 protected void realCompute() {
625 FibAction f = new FibAction(8);
626 assertTrue(f.cancel(true));
627 try {
628 f.invoke();
629 shouldThrow();
630 } catch (CancellationException success) {
631 checkCancelled(f);
632 }
633 }};
634 testInvokeOnPool(mainPool(), a);
635 }
636
637 /**
638 * join of a forked task throws exception when task cancelled
639 */
640 public void testCancelledForkJoin() {
641 RecursiveAction a = new CheckedRecursiveAction() {
642 protected void realCompute() {
643 FibAction f = new FibAction(8);
644 assertTrue(f.cancel(true));
645 assertSame(f, f.fork());
646 try {
647 f.join();
648 shouldThrow();
649 } catch (CancellationException success) {
650 checkCancelled(f);
651 }
652 }};
653 testInvokeOnPool(mainPool(), a);
654 }
655
656 /**
657 * get of a forked task throws exception when task cancelled
658 */
659 public void testCancelledForkGet() {
660 RecursiveAction a = new CheckedRecursiveAction() {
661 protected void realCompute() throws Exception {
662 FibAction f = new FibAction(8);
663 assertTrue(f.cancel(true));
664 assertSame(f, f.fork());
665 try {
666 f.get();
667 shouldThrow();
668 } catch (CancellationException success) {
669 checkCancelled(f);
670 }
671 }};
672 testInvokeOnPool(mainPool(), a);
673 }
674
675 /**
676 * timed get of a forked task throws exception when task cancelled
677 */
678 public void testCancelledForkTimedGet() {
679 RecursiveAction a = new CheckedRecursiveAction() {
680 protected void realCompute() throws Exception {
681 FibAction f = new FibAction(8);
682 assertTrue(f.cancel(true));
683 assertSame(f, f.fork());
684 try {
685 f.get(5L, SECONDS);
686 shouldThrow();
687 } catch (CancellationException success) {
688 checkCancelled(f);
689 }
690 }};
691 testInvokeOnPool(mainPool(), a);
692 }
693
694 /**
695 * quietlyJoin of a forked task returns when task cancelled
696 */
697 public void testCancelledForkQuietlyJoin() {
698 RecursiveAction a = new CheckedRecursiveAction() {
699 protected void realCompute() {
700 FibAction f = new FibAction(8);
701 assertTrue(f.cancel(true));
702 assertSame(f, f.fork());
703 f.quietlyJoin();
704 checkCancelled(f);
705 }};
706 testInvokeOnPool(mainPool(), a);
707 }
708
709 /**
710 * getPool of executing task returns its pool
711 */
712 public void testGetPool() {
713 final ForkJoinPool mainPool = mainPool();
714 RecursiveAction a = new CheckedRecursiveAction() {
715 protected void realCompute() {
716 assertSame(mainPool, getPool());
717 }};
718 testInvokeOnPool(mainPool, a);
719 }
720
721 /**
722 * getPool of non-FJ task returns null
723 */
724 public void testGetPool2() {
725 RecursiveAction a = new CheckedRecursiveAction() {
726 protected void realCompute() {
727 assertNull(getPool());
728 }};
729 assertNull(a.invoke());
730 }
731
732 /**
733 * inForkJoinPool of executing task returns true
734 */
735 public void testInForkJoinPool() {
736 RecursiveAction a = new CheckedRecursiveAction() {
737 protected void realCompute() {
738 assertTrue(inForkJoinPool());
739 }};
740 testInvokeOnPool(mainPool(), a);
741 }
742
743 /**
744 * inForkJoinPool of non-FJ task returns false
745 */
746 public void testInForkJoinPool2() {
747 RecursiveAction a = new CheckedRecursiveAction() {
748 protected void realCompute() {
749 assertFalse(inForkJoinPool());
750 }};
751 assertNull(a.invoke());
752 }
753
754 /**
755 * getPool of current thread in pool returns its pool
756 */
757 public void testWorkerGetPool() {
758 final ForkJoinPool mainPool = mainPool();
759 RecursiveAction a = new CheckedRecursiveAction() {
760 protected void realCompute() {
761 ForkJoinWorkerThread w =
762 (ForkJoinWorkerThread) Thread.currentThread();
763 assertSame(mainPool, w.getPool());
764 }};
765 testInvokeOnPool(mainPool, a);
766 }
767
768 /**
769 * getPoolIndex of current thread in pool returns 0 <= value < poolSize
770 */
771 public void testWorkerGetPoolIndex() {
772 final ForkJoinPool mainPool = mainPool();
773 RecursiveAction a = new CheckedRecursiveAction() {
774 protected void realCompute() {
775 ForkJoinWorkerThread w =
776 (ForkJoinWorkerThread) Thread.currentThread();
777 assertTrue(w.getPoolIndex() >= 0);
778 // pool size can shrink after assigning index, so cannot check
779 // assertTrue(w.getPoolIndex() < mainPool.getPoolSize());
780 }};
781 testInvokeOnPool(mainPool, a);
782 }
783
784 /**
785 * setRawResult(null) succeeds
786 */
787 public void testSetRawResult() {
788 RecursiveAction a = new CheckedRecursiveAction() {
789 protected void realCompute() {
790 setRawResult(null);
791 assertNull(getRawResult());
792 }};
793 assertNull(a.invoke());
794 }
795
796 /**
797 * A reinitialized normally completed task may be re-invoked
798 */
799 public void testReinitialize() {
800 RecursiveAction a = new CheckedRecursiveAction() {
801 protected void realCompute() {
802 FibAction f = new FibAction(8);
803 checkNotDone(f);
804
805 for (int i = 0; i < 3; i++) {
806 assertNull(f.invoke());
807 assertEquals(21, f.result);
808 checkCompletedNormally(f);
809 f.reinitialize();
810 checkNotDone(f);
811 }
812 }};
813 testInvokeOnPool(mainPool(), a);
814 }
815
816 /**
817 * A reinitialized abnormally completed task may be re-invoked
818 */
819 public void testReinitializeAbnormal() {
820 RecursiveAction a = new CheckedRecursiveAction() {
821 protected void realCompute() {
822 FailingFibAction f = new FailingFibAction(8);
823 checkNotDone(f);
824
825 for (int i = 0; i < 3; i++) {
826 try {
827 f.invoke();
828 shouldThrow();
829 } catch (FJException success) {
830 checkCompletedAbnormally(f, success);
831 }
832 f.reinitialize();
833 checkNotDone(f);
834 }
835 }};
836 testInvokeOnPool(mainPool(), a);
837 }
838
839 /**
840 * invoke task throws exception after invoking completeExceptionally
841 */
842 public void testCompleteExceptionally() {
843 RecursiveAction a = new CheckedRecursiveAction() {
844 protected void realCompute() {
845 FibAction f = new FibAction(8);
846 f.completeExceptionally(new FJException());
847 try {
848 f.invoke();
849 shouldThrow();
850 } catch (FJException success) {
851 checkCompletedAbnormally(f, success);
852 }
853 }};
854 testInvokeOnPool(mainPool(), a);
855 }
856
857 /**
858 * invoke task suppresses execution invoking complete
859 */
860 public void testComplete() {
861 RecursiveAction a = new CheckedRecursiveAction() {
862 protected void realCompute() {
863 FibAction f = new FibAction(8);
864 f.complete(null);
865 assertNull(f.invoke());
866 assertEquals(0, f.result);
867 checkCompletedNormally(f);
868 }};
869 testInvokeOnPool(mainPool(), a);
870 }
871
872 /**
873 * invokeAll(t1, t2) invokes all task arguments
874 */
875 public void testInvokeAll2() {
876 RecursiveAction a = new CheckedRecursiveAction() {
877 protected void realCompute() {
878 FibAction f = new FibAction(8);
879 FibAction g = new FibAction(9);
880 invokeAll(f, g);
881 checkCompletedNormally(f);
882 assertEquals(21, f.result);
883 checkCompletedNormally(g);
884 assertEquals(34, g.result);
885 }};
886 testInvokeOnPool(mainPool(), a);
887 }
888
889 /**
890 * invokeAll(tasks) with 1 argument invokes task
891 */
892 public void testInvokeAll1() {
893 RecursiveAction a = new CheckedRecursiveAction() {
894 protected void realCompute() {
895 FibAction f = new FibAction(8);
896 invokeAll(f);
897 checkCompletedNormally(f);
898 assertEquals(21, f.result);
899 }};
900 testInvokeOnPool(mainPool(), a);
901 }
902
903 /**
904 * invokeAll(tasks) with > 2 argument invokes tasks
905 */
906 public void testInvokeAll3() {
907 RecursiveAction a = new CheckedRecursiveAction() {
908 protected void realCompute() {
909 FibAction f = new FibAction(8);
910 FibAction g = new FibAction(9);
911 FibAction h = new FibAction(7);
912 invokeAll(f, g, h);
913 assertTrue(f.isDone());
914 assertTrue(g.isDone());
915 assertTrue(h.isDone());
916 checkCompletedNormally(f);
917 assertEquals(21, f.result);
918 checkCompletedNormally(g);
919 assertEquals(34, g.result);
920 checkCompletedNormally(g);
921 assertEquals(13, h.result);
922 }};
923 testInvokeOnPool(mainPool(), a);
924 }
925
926 /**
927 * invokeAll(collection) invokes all tasks in the collection
928 */
929 public void testInvokeAllCollection() {
930 RecursiveAction a = new CheckedRecursiveAction() {
931 protected void realCompute() {
932 FibAction f = new FibAction(8);
933 FibAction g = new FibAction(9);
934 FibAction h = new FibAction(7);
935 HashSet set = new HashSet();
936 set.add(f);
937 set.add(g);
938 set.add(h);
939 invokeAll(set);
940 assertTrue(f.isDone());
941 assertTrue(g.isDone());
942 assertTrue(h.isDone());
943 checkCompletedNormally(f);
944 assertEquals(21, f.result);
945 checkCompletedNormally(g);
946 assertEquals(34, g.result);
947 checkCompletedNormally(g);
948 assertEquals(13, h.result);
949 }};
950 testInvokeOnPool(mainPool(), a);
951 }
952
953 /**
954 * invokeAll(tasks) with any null task throws NPE
955 */
956 public void testInvokeAllNPE() {
957 RecursiveAction a = new CheckedRecursiveAction() {
958 protected void realCompute() {
959 FibAction f = new FibAction(8);
960 FibAction g = new FibAction(9);
961 FibAction h = null;
962 try {
963 invokeAll(f, g, h);
964 shouldThrow();
965 } catch (NullPointerException success) {}
966 }};
967 testInvokeOnPool(mainPool(), a);
968 }
969
970 /**
971 * invokeAll(t1, t2) throw exception if any task does
972 */
973 public void testAbnormalInvokeAll2() {
974 RecursiveAction a = new CheckedRecursiveAction() {
975 protected void realCompute() {
976 FibAction f = new FibAction(8);
977 FailingFibAction g = new FailingFibAction(9);
978 try {
979 invokeAll(f, g);
980 shouldThrow();
981 } catch (FJException success) {
982 checkCompletedAbnormally(g, success);
983 }
984 }};
985 testInvokeOnPool(mainPool(), a);
986 }
987
988 /**
989 * invokeAll(tasks) with 1 argument throws exception if task does
990 */
991 public void testAbnormalInvokeAll1() {
992 RecursiveAction a = new CheckedRecursiveAction() {
993 protected void realCompute() {
994 FailingFibAction g = new FailingFibAction(9);
995 try {
996 invokeAll(g);
997 shouldThrow();
998 } catch (FJException success) {
999 checkCompletedAbnormally(g, success);
1000 }
1001 }};
1002 testInvokeOnPool(mainPool(), a);
1003 }
1004
1005 /**
1006 * invokeAll(tasks) with > 2 argument throws exception if any task does
1007 */
1008 public void testAbnormalInvokeAll3() {
1009 RecursiveAction a = new CheckedRecursiveAction() {
1010 protected void realCompute() {
1011 FibAction f = new FibAction(8);
1012 FailingFibAction g = new FailingFibAction(9);
1013 FibAction h = new FibAction(7);
1014 try {
1015 invokeAll(f, g, h);
1016 shouldThrow();
1017 } catch (FJException success) {
1018 checkCompletedAbnormally(g, success);
1019 }
1020 }};
1021 testInvokeOnPool(mainPool(), a);
1022 }
1023
1024 /**
1025 * invokeAll(collection) throws exception if any task does
1026 */
1027 public void testAbnormalInvokeAllCollection() {
1028 RecursiveAction a = new CheckedRecursiveAction() {
1029 protected void realCompute() {
1030 FailingFibAction f = new FailingFibAction(8);
1031 FibAction g = new FibAction(9);
1032 FibAction h = new FibAction(7);
1033 HashSet set = new HashSet();
1034 set.add(f);
1035 set.add(g);
1036 set.add(h);
1037 try {
1038 invokeAll(set);
1039 shouldThrow();
1040 } catch (FJException success) {
1041 checkCompletedAbnormally(f, success);
1042 }
1043 }};
1044 testInvokeOnPool(mainPool(), a);
1045 }
1046
1047 /**
1048 * tryUnfork returns true for most recent unexecuted task,
1049 * and suppresses execution
1050 */
1051 public void testTryUnfork() {
1052 RecursiveAction a = new CheckedRecursiveAction() {
1053 protected void realCompute() {
1054 FibAction g = new FibAction(9);
1055 assertSame(g, g.fork());
1056 FibAction f = new FibAction(8);
1057 assertSame(f, f.fork());
1058 assertTrue(f.tryUnfork());
1059 helpQuiesce();
1060 checkNotDone(f);
1061 checkCompletedNormally(g);
1062 }};
1063 testInvokeOnPool(singletonPool(), a);
1064 }
1065
1066 /**
1067 * getSurplusQueuedTaskCount returns > 0 when
1068 * there are more tasks than threads
1069 */
1070 public void testGetSurplusQueuedTaskCount() {
1071 RecursiveAction a = new CheckedRecursiveAction() {
1072 protected void realCompute() {
1073 FibAction h = new FibAction(7);
1074 assertSame(h, h.fork());
1075 FibAction g = new FibAction(9);
1076 assertSame(g, g.fork());
1077 FibAction f = new FibAction(8);
1078 assertSame(f, f.fork());
1079 assertTrue(getSurplusQueuedTaskCount() > 0);
1080 helpQuiesce();
1081 assertEquals(0, getSurplusQueuedTaskCount());
1082 checkCompletedNormally(f);
1083 checkCompletedNormally(g);
1084 checkCompletedNormally(h);
1085 }};
1086 testInvokeOnPool(singletonPool(), a);
1087 }
1088
1089 /**
1090 * peekNextLocalTask returns most recent unexecuted task.
1091 */
1092 public void testPeekNextLocalTask() {
1093 RecursiveAction a = new CheckedRecursiveAction() {
1094 protected void realCompute() {
1095 FibAction g = new FibAction(9);
1096 assertSame(g, g.fork());
1097 FibAction f = new FibAction(8);
1098 assertSame(f, f.fork());
1099 assertSame(f, peekNextLocalTask());
1100 assertNull(f.join());
1101 checkCompletedNormally(f);
1102 helpQuiesce();
1103 checkCompletedNormally(f);
1104 checkCompletedNormally(g);
1105 }};
1106 testInvokeOnPool(singletonPool(), a);
1107 }
1108
1109 /**
1110 * pollNextLocalTask returns most recent unexecuted task
1111 * without executing it
1112 */
1113 public void testPollNextLocalTask() {
1114 RecursiveAction a = new CheckedRecursiveAction() {
1115 protected void realCompute() {
1116 FibAction g = new FibAction(9);
1117 assertSame(g, g.fork());
1118 FibAction f = new FibAction(8);
1119 assertSame(f, f.fork());
1120 assertSame(f, pollNextLocalTask());
1121 helpQuiesce();
1122 checkNotDone(f);
1123 checkCompletedNormally(g);
1124 }};
1125 testInvokeOnPool(singletonPool(), a);
1126 }
1127
1128 /**
1129 * pollTask returns an unexecuted task without executing it
1130 */
1131 public void testPollTask() {
1132 RecursiveAction a = new CheckedRecursiveAction() {
1133 protected void realCompute() {
1134 FibAction g = new FibAction(9);
1135 assertSame(g, g.fork());
1136 FibAction f = new FibAction(8);
1137 assertSame(f, f.fork());
1138 assertSame(f, pollTask());
1139 helpQuiesce();
1140 checkNotDone(f);
1141 checkCompletedNormally(g);
1142 }};
1143 testInvokeOnPool(singletonPool(), a);
1144 }
1145
1146 /**
1147 * peekNextLocalTask returns least recent unexecuted task in async mode
1148 */
1149 public void testPeekNextLocalTaskAsync() {
1150 RecursiveAction a = new CheckedRecursiveAction() {
1151 protected void realCompute() {
1152 FibAction g = new FibAction(9);
1153 assertSame(g, g.fork());
1154 FibAction f = new FibAction(8);
1155 assertSame(f, f.fork());
1156 assertSame(g, peekNextLocalTask());
1157 assertNull(f.join());
1158 helpQuiesce();
1159 checkCompletedNormally(f);
1160 checkCompletedNormally(g);
1161 }};
1162 testInvokeOnPool(asyncSingletonPool(), a);
1163 }
1164
1165 /**
1166 * pollNextLocalTask returns least recent unexecuted task without
1167 * executing it, in async mode
1168 */
1169 public void testPollNextLocalTaskAsync() {
1170 RecursiveAction a = new CheckedRecursiveAction() {
1171 protected void realCompute() {
1172 FibAction g = new FibAction(9);
1173 assertSame(g, g.fork());
1174 FibAction f = new FibAction(8);
1175 assertSame(f, f.fork());
1176 assertSame(g, pollNextLocalTask());
1177 helpQuiesce();
1178 checkCompletedNormally(f);
1179 checkNotDone(g);
1180 }};
1181 testInvokeOnPool(asyncSingletonPool(), a);
1182 }
1183
1184 /**
1185 * pollTask returns an unexecuted task without executing it, in
1186 * async mode
1187 */
1188 public void testPollTaskAsync() {
1189 RecursiveAction a = new CheckedRecursiveAction() {
1190 protected void realCompute() {
1191 FibAction g = new FibAction(9);
1192 assertSame(g, g.fork());
1193 FibAction f = new FibAction(8);
1194 assertSame(f, f.fork());
1195 assertSame(g, pollTask());
1196 helpQuiesce();
1197 checkCompletedNormally(f);
1198 checkNotDone(g);
1199 }};
1200 testInvokeOnPool(asyncSingletonPool(), a);
1201 }
1202
1203 /** Demo from RecursiveAction javadoc */
1204 static class SortTask extends RecursiveAction {
1205 final long[] array; final int lo, hi;
1206 SortTask(long[] array, int lo, int hi) {
1207 this.array = array; this.lo = lo; this.hi = hi;
1208 }
1209 SortTask(long[] array) { this(array, 0, array.length); }
1210 protected void compute() {
1211 if (hi - lo < THRESHOLD)
1212 sortSequentially(lo, hi);
1213 else {
1214 int mid = (lo + hi) >>> 1;
1215 invokeAll(new SortTask(array, lo, mid),
1216 new SortTask(array, mid, hi));
1217 merge(lo, mid, hi);
1218 }
1219 }
1220 // implementation details follow:
1221 static final int THRESHOLD = 100;
1222 void sortSequentially(int lo, int hi) {
1223 Arrays.sort(array, lo, hi);
1224 }
1225 void merge(int lo, int mid, int hi) {
1226 long[] buf = Arrays.copyOfRange(array, lo, mid);
1227 for (int i = 0, j = lo, k = mid; i < buf.length; j++)
1228 array[j] = (k == hi || buf[i] < array[k]) ?
1229 buf[i++] : array[k++];
1230 }
1231 }
1232
1233 /**
1234 * SortTask demo works as advertised
1235 */
1236 public void testSortTaskDemo() {
1237 ThreadLocalRandom rnd = ThreadLocalRandom.current();
1238 long[] array = new long[1007];
1239 for (int i = 0; i < array.length; i++)
1240 array[i] = rnd.nextLong();
1241 long[] arrayClone = array.clone();
1242 testInvokeOnPool(mainPool(), new SortTask(array));
1243 Arrays.sort(arrayClone);
1244 assertTrue(Arrays.equals(array, arrayClone));
1245 }
1246 }