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