ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
Revision: 1.48
Committed: Tue Aug 16 23:17:13 2016 UTC (7 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.47: +0 -12 lines
Log Message:
stop checking that Thread.interrupt() works

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