142 |
|
* |
143 |
|
* As a further improvement, notice that the left task need not even |
144 |
|
* exist. Instead of creating a new one, we can iterate using the |
145 |
< |
* original task, and add a pending count for each fork. Additionally, |
146 |
< |
* this version uses {@code helpComplete} to streamline assistance in |
147 |
< |
* the execution of forked tasks. |
145 |
> |
* original task, and add a pending count for each fork. |
146 |
|
* |
147 |
|
* <pre> {@code |
148 |
|
* class ForEach<E> ... |
156 |
|
* } |
157 |
|
* if (h > l) |
158 |
|
* op.apply(array[l]); |
159 |
< |
* helpComplete(); |
159 |
> |
* tryComplete(); |
160 |
|
* } |
161 |
|
* }</pre> |
162 |
|
* |
412 |
|
} |
413 |
|
|
414 |
|
/** |
417 |
– |
* Identical to {@link #tryComplete}, but may additionally execute |
418 |
– |
* other tasks within the current computation (i.e., those |
419 |
– |
* with the same {@link #getRoot}. |
420 |
– |
*/ |
421 |
– |
public final void helpComplete() { |
422 |
– |
CountedCompleter<?> a = this, s = a; |
423 |
– |
for (int c;;) { |
424 |
– |
if ((c = a.pending) == 0) { |
425 |
– |
a.onCompletion(s); |
426 |
– |
if ((a = (s = a).completer) == null) { |
427 |
– |
s.quietlyComplete(); |
428 |
– |
return; |
429 |
– |
} |
430 |
– |
} |
431 |
– |
else if (U.compareAndSwapInt(a, PENDING, c, c - 1)) { |
432 |
– |
if (!(Thread.currentThread() instanceof ForkJoinWorkerThread)) |
433 |
– |
ForkJoinPool.popAndExecCCFromCommonPool(a); |
434 |
– |
return; |
435 |
– |
} |
436 |
– |
} |
437 |
– |
} |
438 |
– |
|
439 |
– |
/** |
415 |
|
* Regardless of pending count, invokes {@link #onCompletion}, |
416 |
|
* marks this task as complete and further triggers {@link |
417 |
|
* #tryComplete} on this task's completer, if one exists. This |
477 |
|
throw new Error(e); |
478 |
|
} |
479 |
|
} |
505 |
– |
|
480 |
|
/** |
481 |
|
* Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. |
482 |
|
* Replace with a simple call to Unsafe.getUnsafe when integrating |