ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
Revision: 1.36
Committed: Sun Jun 26 06:50:19 2011 UTC (12 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.35: +4 -7 lines
Log Message:
use only n/2 space overhead in SortTask.merge

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