83 |
|
* subdivided) to each element of an array or collection; especially |
84 |
|
* when the operation takes a significantly different amount of time |
85 |
|
* to complete for some elements than others, either because of |
86 |
< |
* intrinsic variation (for example IO) or auxiliary effects such as |
86 |
> |
* intrinsic variation (for example I/O) or auxiliary effects such as |
87 |
|
* garbage collection. Because CountedCompleters provide their own |
88 |
|
* continuations, other threads need not block waiting to perform |
89 |
|
* them. |
183 |
|
* |
184 |
|
* <p><b>Searching.</b> A tree of CountedCompleters can search for a |
185 |
|
* value or property in different parts of a data structure, and |
186 |
< |
* report a result in an {@link java.util.concurrent.AtomicReference} |
187 |
< |
* as soon as one is found. The others can poll the result to avoid |
188 |
< |
* unnecessary work. (You could additionally {@link #cancel} other |
189 |
< |
* tasks, but it is usually simpler and more efficient to just let |
190 |
< |
* them notice that the result is set and if so skip further |
191 |
< |
* processing.) Illustrating again with an array using full |
186 |
> |
* report a result in an {@link |
187 |
> |
* java.util.concurrent.atomic.AtomicReference AtomicReference} as |
188 |
> |
* soon as one is found. The others can poll the result to avoid |
189 |
> |
* unnecessary work. (You could additionally {@linkplain #cancel |
190 |
> |
* cancel} other tasks, but it is usually simpler and more efficient |
191 |
> |
* to just let them notice that the result is set and if so skip |
192 |
> |
* further processing.) Illustrating again with an array using full |
193 |
|
* partitioning (again, in practice, leaf tasks will almost always |
194 |
|
* process more than one element): |
195 |
|
* |
224 |
|
* public static <E> E search(E[] array) { |
225 |
|
* return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke(); |
226 |
|
* } |
227 |
< |
*}}</pre> |
227 |
> |
* }}</pre> |
228 |
|
* |
229 |
|
* In this example, as well as others in which tasks have no other |
230 |
|
* effects except to compareAndSet a common result, the trailing |
278 |
|
* } |
279 |
|
* public void onCompletion(CountedCompleter<?> caller) { |
280 |
|
* if (caller != this) { |
281 |
< |
* MapReducer<E> child = (MapReducer<E>)caller; |
282 |
< |
* MapReducer<E> sib = child.sibling; |
283 |
< |
* if (sib == null || sib.result == null) |
284 |
< |
* result = child.result; |
285 |
< |
* else |
286 |
< |
* result = reducer.apply(child.result, sib.result); |
281 |
> |
* MapReducer<E> child = (MapReducer<E>)caller; |
282 |
> |
* MapReducer<E> sib = child.sibling; |
283 |
> |
* if (sib == null || sib.result == null) |
284 |
> |
* result = child.result; |
285 |
> |
* else |
286 |
> |
* result = reducer.apply(child.result, sib.result); |
287 |
|
* } |
288 |
|
* } |
289 |
|
* public E getRawResult() { return result; } |
389 |
|
* Creates a new CountedCompleter with the given completer |
390 |
|
* and initial pending count. |
391 |
|
* |
392 |
< |
* @param completer this tasks completer, or {@code null} if none |
392 |
> |
* @param completer this task's completer, or {@code null} if none |
393 |
|
* @param initialPendingCount the initial pending count |
394 |
|
*/ |
395 |
|
protected CountedCompleter(CountedCompleter<?> completer, |
402 |
|
* Creates a new CountedCompleter with the given completer |
403 |
|
* and an initial pending count of zero. |
404 |
|
* |
405 |
< |
* @param completer this tasks completer, or {@code null} if none |
405 |
> |
* @param completer this task's completer, or {@code null} if none |
406 |
|
*/ |
407 |
|
protected CountedCompleter(CountedCompleter<?> completer) { |
408 |
|
this.completer = completer; |
423 |
|
|
424 |
|
/** |
425 |
|
* Performs an action when method {@link #tryComplete} is invoked |
426 |
< |
* and there are no pending counts, or when the unconditional |
426 |
> |
* and the pending count is zero, or when the unconditional |
427 |
|
* method {@link #complete} is invoked. By default, this method |
428 |
|
* does nothing. You can distinguish cases by checking the |
429 |
|
* identity of the given caller argument. If not equal to {@code |
431 |
|
* (and/or links to other results) to combine. |
432 |
|
* |
433 |
|
* @param caller the task invoking this method (which may |
434 |
< |
* be this task itself). |
434 |
> |
* be this task itself) |
435 |
|
*/ |
436 |
|
public void onCompletion(CountedCompleter<?> caller) { |
437 |
|
} |
449 |
|
* |
450 |
|
* @param ex the exception |
451 |
|
* @param caller the task invoking this method (which may |
452 |
< |
* be this task itself). |
452 |
> |
* be this task itself) |
453 |
|
* @return true if this exception should be propagated to this |
454 |
< |
* tasks completer, if one exists. |
454 |
> |
* task's completer, if one exists |
455 |
|
*/ |
456 |
|
public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller) { |
457 |
|
return true; |
662 |
|
} |
663 |
|
|
664 |
|
/** |
665 |
< |
* Support for FJT exception propagation |
665 |
> |
* Supports ForkJoinTask exception propagation. |
666 |
|
*/ |
667 |
|
void internalPropagateException(Throwable ex) { |
668 |
|
CountedCompleter<?> a = this, s = a; |
672 |
|
} |
673 |
|
|
674 |
|
/** |
675 |
< |
* Implements execution conventions for CountedCompleters |
675 |
> |
* Implements execution conventions for CountedCompleters. |
676 |
|
*/ |
677 |
|
protected final boolean exec() { |
678 |
|
compute(); |
704 |
|
private static final long PENDING; |
705 |
|
static { |
706 |
|
try { |
707 |
< |
U = sun.misc.Unsafe.getUnsafe(); |
707 |
> |
U = getUnsafe(); |
708 |
|
PENDING = U.objectFieldOffset |
709 |
|
(CountedCompleter.class.getDeclaredField("pending")); |
710 |
|
} catch (Exception e) { |
722 |
|
private static sun.misc.Unsafe getUnsafe() { |
723 |
|
try { |
724 |
|
return sun.misc.Unsafe.getUnsafe(); |
725 |
< |
} catch (SecurityException se) { |
726 |
< |
try { |
727 |
< |
return java.security.AccessController.doPrivileged |
728 |
< |
(new java.security |
729 |
< |
.PrivilegedExceptionAction<sun.misc.Unsafe>() { |
730 |
< |
public sun.misc.Unsafe run() throws Exception { |
731 |
< |
java.lang.reflect.Field f = sun.misc |
732 |
< |
.Unsafe.class.getDeclaredField("theUnsafe"); |
733 |
< |
f.setAccessible(true); |
734 |
< |
return (sun.misc.Unsafe) f.get(null); |
735 |
< |
}}); |
736 |
< |
} catch (java.security.PrivilegedActionException e) { |
737 |
< |
throw new RuntimeException("Could not initialize intrinsics", |
738 |
< |
e.getCause()); |
739 |
< |
} |
725 |
> |
} catch (SecurityException tryReflectionInstead) {} |
726 |
> |
try { |
727 |
> |
return java.security.AccessController.doPrivileged |
728 |
> |
(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() { |
729 |
> |
public sun.misc.Unsafe run() throws Exception { |
730 |
> |
Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class; |
731 |
> |
for (java.lang.reflect.Field f : k.getDeclaredFields()) { |
732 |
> |
f.setAccessible(true); |
733 |
> |
Object x = f.get(null); |
734 |
> |
if (k.isInstance(x)) |
735 |
> |
return k.cast(x); |
736 |
> |
} |
737 |
> |
throw new NoSuchFieldError("the Unsafe"); |
738 |
> |
}}); |
739 |
> |
} catch (java.security.PrivilegedActionException e) { |
740 |
> |
throw new RuntimeException("Could not initialize intrinsics", |
741 |
> |
e.getCause()); |
742 |
|
} |
743 |
|
} |
744 |
|
} |