ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
Revision: 1.57
Committed: Wed Jan 27 01:57:24 2021 UTC (3 years, 3 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.56: +2 -2 lines
Log Message:
use diamond <> pervasively

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