ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
Revision: 1.53
Committed: Sun Jan 7 22:59:18 2018 UTC (6 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.52: +1 -2 lines
Log Message:
use <>

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