ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
Revision: 1.41
Committed: Tue Jan 20 17:02:26 2015 UTC (9 years, 3 months ago) by dl
Branch: MAIN
Changes since 1.40: +2 -0 lines
Log Message:
Fix race in testForkHelpQuiesce

File Contents

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