71 |
|
* encountering the exception; minimally only the latter. |
72 |
|
* |
73 |
|
* <p>It is possible to define and use ForkJoinTasks that may block, |
74 |
< |
* but doing do requires three further considerations: (1) Completion |
74 |
> |
* but doing so requires three further considerations: (1) Completion |
75 |
|
* of few if any <em>other</em> tasks should be dependent on a task |
76 |
|
* that blocks on external synchronization or I/O. Event-style async |
77 |
|
* tasks that are never joined (for example, those subclassing {@link |
134 |
|
* (DAG). Otherwise, executions may encounter a form of deadlock as |
135 |
|
* tasks cyclically wait for each other. However, this framework |
136 |
|
* supports other methods and techniques (for example the use of |
137 |
< |
* {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that |
137 |
> |
* {@link java.util.concurrent.Phaser Phaser}, {@link #helpQuiesce}, and {@link #complete}) that |
138 |
|
* may be of use in constructing custom subclasses for problems that |
139 |
|
* are not statically structured as DAGs. To support such usages, a |
140 |
|
* ForkJoinTask may be atomically <em>tagged</em> with a {@code short} |
411 |
|
final Throwable ex; |
412 |
|
ExceptionNode next; |
413 |
|
final long thrower; // use id not ref to avoid weak cycles |
414 |
+ |
final int hashCode; // store task hashCode before weak ref disappears |
415 |
|
ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next) { |
416 |
|
super(task, exceptionTableRefQueue); |
417 |
|
this.ex = ex; |
418 |
|
this.next = next; |
419 |
|
this.thrower = Thread.currentThread().getId(); |
420 |
+ |
this.hashCode = System.identityHashCode(task); |
421 |
|
} |
422 |
|
} |
423 |
|
|
576 |
|
/** |
577 |
|
* Poll stale refs and remove them. Call only while holding lock. |
578 |
|
*/ |
579 |
+ |
/** |
580 |
+ |
* Poll stale refs and remove them. Call only while holding lock. |
581 |
+ |
*/ |
582 |
|
private static void expungeStaleExceptions() { |
583 |
|
for (Object x; (x = exceptionTableRefQueue.poll()) != null;) { |
584 |
|
if (x instanceof ExceptionNode) { |
585 |
< |
ForkJoinTask<?> key = ((ExceptionNode)x).get(); |
585 |
> |
int hashCode = ((ExceptionNode)x).hashCode; |
586 |
|
ExceptionNode[] t = exceptionTable; |
587 |
< |
int i = System.identityHashCode(key) & (t.length - 1); |
587 |
> |
int i = hashCode & (t.length - 1); |
588 |
|
ExceptionNode e = t[i]; |
589 |
|
ExceptionNode pred = null; |
590 |
|
while (e != null) { |
787 |
|
* unprocessed. |
788 |
|
* |
789 |
|
* @param tasks the collection of tasks |
790 |
+ |
* @param <T> the type of the values returned from the tasks |
791 |
|
* @return the tasks argument, to simplify usage |
792 |
|
* @throws NullPointerException if tasks or any element are null |
793 |
|
*/ |
1086 |
|
|
1087 |
|
/** |
1088 |
|
* Possibly executes tasks until the pool hosting the current task |
1089 |
< |
* {@link ForkJoinPool#isQuiescent is quiescent}. This method may |
1090 |
< |
* be of use in designs in which many tasks are forked, but none |
1091 |
< |
* are explicitly joined, instead executing them until all are |
1092 |
< |
* processed. |
1089 |
> |
* {@linkplain ForkJoinPool#isQuiescent is quiescent}. This |
1090 |
> |
* method may be of use in designs in which many tasks are forked, |
1091 |
> |
* but none are explicitly joined, instead executing them until |
1092 |
> |
* all are processed. |
1093 |
|
*/ |
1094 |
|
public static void helpQuiesce() { |
1095 |
|
Thread t; |
1347 |
|
} |
1348 |
|
|
1349 |
|
/** |
1350 |
< |
* Adaptor for Runnables. This implements RunnableFuture |
1350 |
> |
* Adapter for Runnables. This implements RunnableFuture |
1351 |
|
* to be compliant with AbstractExecutorService constraints |
1352 |
|
* when used in ForkJoinPool. |
1353 |
|
*/ |
1368 |
|
} |
1369 |
|
|
1370 |
|
/** |
1371 |
< |
* Adaptor for Runnables without results |
1371 |
> |
* Adapter for Runnables without results |
1372 |
|
*/ |
1373 |
|
static final class AdaptedRunnableAction extends ForkJoinTask<Void> |
1374 |
|
implements RunnableFuture<Void> { |
1385 |
|
} |
1386 |
|
|
1387 |
|
/** |
1388 |
< |
* Adaptor for Runnables in which failure forces worker exception |
1388 |
> |
* Adapter for Runnables in which failure forces worker exception |
1389 |
|
*/ |
1390 |
|
static final class RunnableExecuteAction extends ForkJoinTask<Void> { |
1391 |
|
final Runnable runnable; |
1403 |
|
} |
1404 |
|
|
1405 |
|
/** |
1406 |
< |
* Adaptor for Callables |
1406 |
> |
* Adapter for Callables |
1407 |
|
*/ |
1408 |
|
static final class AdaptedCallable<T> extends ForkJoinTask<T> |
1409 |
|
implements RunnableFuture<T> { |
1450 |
|
* |
1451 |
|
* @param runnable the runnable action |
1452 |
|
* @param result the result upon completion |
1453 |
+ |
* @param <T> the type of the result |
1454 |
|
* @return the task |
1455 |
|
*/ |
1456 |
|
public static <T> ForkJoinTask<T> adapt(Runnable runnable, T result) { |
1464 |
|
* encountered into {@code RuntimeException}. |
1465 |
|
* |
1466 |
|
* @param callable the callable action |
1467 |
+ |
* @param <T> the type of the callable's result |
1468 |
|
* @return the task |
1469 |
|
*/ |
1470 |
|
public static <T> ForkJoinTask<T> adapt(Callable<? extends T> callable) { |
1478 |
|
/** |
1479 |
|
* Saves this task to a stream (that is, serializes it). |
1480 |
|
* |
1481 |
+ |
* @param s the stream |
1482 |
+ |
* @throws java.io.IOException if an I/O error occurs |
1483 |
|
* @serialData the current run status and the exception thrown |
1484 |
|
* during execution, or {@code null} if none |
1485 |
|
*/ |
1491 |
|
|
1492 |
|
/** |
1493 |
|
* Reconstitutes this task from a stream (that is, deserializes it). |
1494 |
+ |
* @param s the stream |
1495 |
+ |
* @throws ClassNotFoundException if the class of a serialized object |
1496 |
+ |
* could not be found |
1497 |
+ |
* @throws java.io.IOException if an I/O error occurs |
1498 |
|
*/ |
1499 |
|
private void readObject(java.io.ObjectInputStream s) |
1500 |
|
throws java.io.IOException, ClassNotFoundException { |