4 |
|
* http://creativecommons.org/publicdomain/zero/1.0/ |
5 |
|
*/ |
6 |
|
|
7 |
< |
import static java.util.concurrent.TimeUnit.SECONDS; |
7 |
> |
import static java.util.concurrent.TimeUnit.MILLISECONDS; |
8 |
|
|
9 |
|
import java.util.Arrays; |
10 |
|
import java.util.HashSet; |
17 |
|
import java.util.concurrent.SynchronousQueue; |
18 |
|
import java.util.concurrent.ThreadLocalRandom; |
19 |
|
import java.util.concurrent.TimeoutException; |
20 |
– |
import java.util.concurrent.TimeUnit; |
20 |
|
|
21 |
|
import junit.framework.Test; |
22 |
|
import junit.framework.TestSuite; |
24 |
|
public class RecursiveActionTest extends JSR166TestCase { |
25 |
|
|
26 |
|
public static void main(String[] args) { |
27 |
< |
junit.textui.TestRunner.run(suite()); |
27 |
> |
main(suite(), args); |
28 |
|
} |
29 |
|
|
30 |
|
public static Test suite() { |
46 |
|
} |
47 |
|
|
48 |
|
private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) { |
49 |
< |
try { |
49 |
> |
try (PoolCleaner cleaner = cleaner(pool)) { |
50 |
|
checkNotDone(a); |
51 |
|
|
52 |
|
assertNull(pool.invoke(a)); |
53 |
|
|
54 |
|
checkCompletedNormally(a); |
56 |
– |
} finally { |
57 |
– |
joinPool(pool); |
55 |
|
} |
56 |
|
} |
57 |
|
|
73 |
|
|
74 |
|
Thread.currentThread().interrupt(); |
75 |
|
try { |
76 |
< |
a.get(5L, SECONDS); |
76 |
> |
a.get(randomTimeout(), randomTimeUnit()); |
77 |
|
shouldThrow(); |
78 |
|
} catch (InterruptedException success) { |
79 |
|
} catch (Throwable fail) { threadUnexpectedException(fail); } |
80 |
|
} |
81 |
|
|
82 |
|
try { |
83 |
< |
a.get(0L, SECONDS); |
83 |
> |
a.get(randomExpiredTimeout(), randomTimeUnit()); |
84 |
|
shouldThrow(); |
85 |
|
} catch (TimeoutException success) { |
86 |
|
} catch (Throwable fail) { threadUnexpectedException(fail); } |
98 |
|
assertFalse(a.cancel(true)); |
99 |
|
try { |
100 |
|
assertNull(a.get()); |
101 |
< |
} catch (Throwable fail) { threadUnexpectedException(fail); } |
105 |
< |
try { |
106 |
< |
assertNull(a.get(5L, SECONDS)); |
101 |
> |
assertNull(a.get(randomTimeout(), randomTimeUnit())); |
102 |
|
} catch (Throwable fail) { threadUnexpectedException(fail); } |
103 |
|
} |
104 |
|
|
123 |
|
} catch (Throwable fail) { threadUnexpectedException(fail); } |
124 |
|
|
125 |
|
try { |
126 |
< |
a.get(5L, SECONDS); |
126 |
> |
a.get(randomTimeout(), randomTimeUnit()); |
127 |
|
shouldThrow(); |
128 |
|
} catch (CancellationException success) { |
129 |
|
} catch (Throwable fail) { threadUnexpectedException(fail); } |
154 |
|
} catch (Throwable fail) { threadUnexpectedException(fail); } |
155 |
|
|
156 |
|
try { |
157 |
< |
a.get(5L, SECONDS); |
157 |
> |
a.get(randomTimeout(), randomTimeUnit()); |
158 |
|
shouldThrow(); |
159 |
|
} catch (ExecutionException success) { |
160 |
|
assertSame(t.getClass(), success.getCause().getClass()); |
166 |
|
public FJException(Throwable cause) { super(cause); } |
167 |
|
} |
168 |
|
|
169 |
< |
// A simple recursive action for testing |
169 |
> |
/** A simple recursive action for testing. */ |
170 |
|
final class FibAction extends CheckedRecursiveAction { |
171 |
|
final int number; |
172 |
|
int result; |
184 |
|
} |
185 |
|
} |
186 |
|
|
187 |
< |
// A recursive action failing in base case |
187 |
> |
/** A recursive action failing in base case. */ |
188 |
|
static final class FailingFibAction extends RecursiveAction { |
189 |
|
final int number; |
190 |
|
int result; |
256 |
|
RecursiveAction a = new CheckedRecursiveAction() { |
257 |
|
protected void realCompute() { |
258 |
|
FibAction f = new FibAction(8); |
259 |
< |
final Thread myself = Thread.currentThread(); |
259 |
> |
final Thread currentThread = Thread.currentThread(); |
260 |
|
|
261 |
|
// test join() |
262 |
|
assertSame(f, f.fork()); |
263 |
< |
myself.interrupt(); |
269 |
< |
assertTrue(myself.isInterrupted()); |
263 |
> |
currentThread.interrupt(); |
264 |
|
assertNull(f.join()); |
265 |
|
Thread.interrupted(); |
266 |
|
assertEquals(21, f.result); |
269 |
|
f = new FibAction(8); |
270 |
|
f.cancel(true); |
271 |
|
assertSame(f, f.fork()); |
272 |
< |
myself.interrupt(); |
279 |
< |
assertTrue(myself.isInterrupted()); |
272 |
> |
currentThread.interrupt(); |
273 |
|
try { |
274 |
|
f.join(); |
275 |
|
shouldThrow(); |
281 |
|
f = new FibAction(8); |
282 |
|
f.completeExceptionally(new FJException()); |
283 |
|
assertSame(f, f.fork()); |
284 |
< |
myself.interrupt(); |
292 |
< |
assertTrue(myself.isInterrupted()); |
284 |
> |
currentThread.interrupt(); |
285 |
|
try { |
286 |
|
f.join(); |
287 |
|
shouldThrow(); |
293 |
|
// test quietlyJoin() |
294 |
|
f = new FibAction(8); |
295 |
|
assertSame(f, f.fork()); |
296 |
< |
myself.interrupt(); |
305 |
< |
assertTrue(myself.isInterrupted()); |
296 |
> |
currentThread.interrupt(); |
297 |
|
f.quietlyJoin(); |
298 |
|
Thread.interrupted(); |
299 |
|
assertEquals(21, f.result); |
302 |
|
f = new FibAction(8); |
303 |
|
f.cancel(true); |
304 |
|
assertSame(f, f.fork()); |
305 |
< |
myself.interrupt(); |
315 |
< |
assertTrue(myself.isInterrupted()); |
305 |
> |
currentThread.interrupt(); |
306 |
|
f.quietlyJoin(); |
307 |
|
Thread.interrupted(); |
308 |
|
checkCancelled(f); |
310 |
|
f = new FibAction(8); |
311 |
|
f.completeExceptionally(new FJException()); |
312 |
|
assertSame(f, f.fork()); |
313 |
< |
myself.interrupt(); |
324 |
< |
assertTrue(myself.isInterrupted()); |
313 |
> |
currentThread.interrupt(); |
314 |
|
f.quietlyJoin(); |
315 |
|
Thread.interrupted(); |
316 |
|
checkCompletedAbnormally(f, f.getException()); |
325 |
|
* succeeds in the presence of interrupts |
326 |
|
*/ |
327 |
|
public void testJoinIgnoresInterruptsOutsideForkJoinPool() { |
328 |
< |
final SynchronousQueue<FibAction[]> sq = |
340 |
< |
new SynchronousQueue<FibAction[]>(); |
328 |
> |
final SynchronousQueue<FibAction[]> sq = new SynchronousQueue<>(); |
329 |
|
RecursiveAction a = new CheckedRecursiveAction() { |
330 |
|
protected void realCompute() throws InterruptedException { |
331 |
|
FibAction[] fibActions = new FibAction[6]; |
337 |
|
fibActions[4].cancel(true); |
338 |
|
fibActions[5].completeExceptionally(new FJException()); |
339 |
|
|
340 |
< |
for (int i = 0; i < fibActions.length; i++) |
341 |
< |
fibActions[i].fork(); |
340 |
> |
for (FibAction fibAction : fibActions) |
341 |
> |
fibAction.fork(); |
342 |
|
|
343 |
|
sq.put(fibActions); |
344 |
|
|
349 |
|
public void realRun() throws InterruptedException { |
350 |
|
FibAction[] fibActions = sq.take(); |
351 |
|
FibAction f; |
352 |
< |
final Thread myself = Thread.currentThread(); |
352 |
> |
final Thread currentThread = Thread.currentThread(); |
353 |
|
|
354 |
|
// test join() ------------ |
355 |
|
|
356 |
|
f = fibActions[0]; |
357 |
|
assertFalse(ForkJoinTask.inForkJoinPool()); |
358 |
< |
myself.interrupt(); |
371 |
< |
assertTrue(myself.isInterrupted()); |
358 |
> |
currentThread.interrupt(); |
359 |
|
assertNull(f.join()); |
360 |
|
assertTrue(Thread.interrupted()); |
361 |
|
assertEquals(21, f.result); |
362 |
|
checkCompletedNormally(f); |
363 |
|
|
364 |
|
f = fibActions[1]; |
365 |
< |
myself.interrupt(); |
379 |
< |
assertTrue(myself.isInterrupted()); |
365 |
> |
currentThread.interrupt(); |
366 |
|
try { |
367 |
|
f.join(); |
368 |
|
shouldThrow(); |
372 |
|
} |
373 |
|
|
374 |
|
f = fibActions[2]; |
375 |
< |
myself.interrupt(); |
390 |
< |
assertTrue(myself.isInterrupted()); |
375 |
> |
currentThread.interrupt(); |
376 |
|
try { |
377 |
|
f.join(); |
378 |
|
shouldThrow(); |
384 |
|
// test quietlyJoin() --------- |
385 |
|
|
386 |
|
f = fibActions[3]; |
387 |
< |
myself.interrupt(); |
403 |
< |
assertTrue(myself.isInterrupted()); |
387 |
> |
currentThread.interrupt(); |
388 |
|
f.quietlyJoin(); |
389 |
|
assertTrue(Thread.interrupted()); |
390 |
|
assertEquals(21, f.result); |
391 |
|
checkCompletedNormally(f); |
392 |
|
|
393 |
|
f = fibActions[4]; |
394 |
< |
myself.interrupt(); |
411 |
< |
assertTrue(myself.isInterrupted()); |
394 |
> |
currentThread.interrupt(); |
395 |
|
f.quietlyJoin(); |
396 |
|
assertTrue(Thread.interrupted()); |
397 |
|
checkCancelled(f); |
398 |
|
|
399 |
|
f = fibActions[5]; |
400 |
< |
myself.interrupt(); |
418 |
< |
assertTrue(myself.isInterrupted()); |
400 |
> |
currentThread.interrupt(); |
401 |
|
f.quietlyJoin(); |
402 |
|
assertTrue(Thread.interrupted()); |
403 |
|
assertTrue(f.getException() instanceof FJException); |
408 |
|
|
409 |
|
t = newStartedThread(r); |
410 |
|
testInvokeOnPool(mainPool(), a); |
411 |
< |
awaitTermination(t, LONG_DELAY_MS); |
411 |
> |
awaitTermination(t); |
412 |
|
|
413 |
|
a.reinitialize(); |
414 |
|
t = newStartedThread(r); |
415 |
|
testInvokeOnPool(singletonPool(), a); |
416 |
< |
awaitTermination(t, LONG_DELAY_MS); |
416 |
> |
awaitTermination(t); |
417 |
|
} |
418 |
|
|
419 |
|
/** |
439 |
|
protected void realCompute() throws Exception { |
440 |
|
FibAction f = new FibAction(8); |
441 |
|
assertSame(f, f.fork()); |
442 |
< |
assertNull(f.get(5L, SECONDS)); |
442 |
> |
assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); |
443 |
|
assertEquals(21, f.result); |
444 |
|
checkCompletedNormally(f); |
445 |
|
}}; |
455 |
|
FibAction f = new FibAction(8); |
456 |
|
assertSame(f, f.fork()); |
457 |
|
try { |
458 |
< |
f.get(5L, null); |
458 |
> |
f.get(randomTimeout(), null); |
459 |
|
shouldThrow(); |
460 |
|
} catch (NullPointerException success) {} |
461 |
|
}}; |
574 |
|
FailingFibAction f = new FailingFibAction(8); |
575 |
|
assertSame(f, f.fork()); |
576 |
|
try { |
577 |
< |
f.get(5L, TimeUnit.SECONDS); |
577 |
> |
f.get(LONG_DELAY_MS, MILLISECONDS); |
578 |
|
shouldThrow(); |
579 |
|
} catch (ExecutionException success) { |
580 |
|
Throwable cause = success.getCause(); |
666 |
|
assertTrue(f.cancel(true)); |
667 |
|
assertSame(f, f.fork()); |
668 |
|
try { |
669 |
< |
f.get(5L, SECONDS); |
669 |
> |
f.get(LONG_DELAY_MS, MILLISECONDS); |
670 |
|
shouldThrow(); |
671 |
|
} catch (CancellationException success) { |
672 |
|
checkCancelled(f); |