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