ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166y/CountedCompleter.java
(Generate patch)

Comparing jsr166/src/jsr166y/CountedCompleter.java (file contents):
Revision 1.21 by jsr166, Sun Nov 25 18:54:50 2012 UTC vs.
Revision 1.30 by jsr166, Thu Jan 10 07:54:22 2013 UTC

# Line 15 | Line 15 | package jsr166y;
15   * CountedCompleter are similar to those of other completion based
16   * components (such as {@link java.nio.channels.CompletionHandler})
17   * except that multiple <em>pending</em> completions may be necessary
18 < * to trigger the {@link #onCompletion} action, not just one. Unless
19 < * initialized otherwise, the {@link #getPendingCount pending count}
20 < * starts at zero, but may be (atomically) changed using methods
21 < * {@link #setPendingCount}, {@link #addToPendingCount}, and {@link
22 < * #compareAndSetPendingCount}. Upon invocation of {@link
18 > * to trigger the completion action {@link #onCompletion}, not just one.
19 > * Unless initialized otherwise, the {@linkplain #getPendingCount pending
20 > * count} starts at zero, but may be (atomically) changed using
21 > * methods {@link #setPendingCount}, {@link #addToPendingCount}, and
22 > * {@link #compareAndSetPendingCount}. Upon invocation of {@link
23   * #tryComplete}, if the pending action count is nonzero, it is
24   * decremented; otherwise, the completion action is performed, and if
25   * this completer itself has a completer, the process is continued
# Line 83 | Line 83 | package jsr166y;
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.
# Line 183 | Line 183 | package jsr166y;
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   *
# Line 223 | Line 224 | package jsr166y;
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
# Line 277 | Line 278 | package jsr166y;
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; }
# Line 388 | Line 389 | public abstract class CountedCompleter<T
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,
# Line 401 | Line 402 | public abstract class CountedCompleter<T
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;
# Line 422 | Line 423 | public abstract class CountedCompleter<T
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
# Line 450 | Line 451 | public abstract class CountedCompleter<T
451       * @param caller the task invoking this method (which may
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;
# Line 661 | Line 662 | public abstract class CountedCompleter<T
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;
# Line 671 | Line 672 | public abstract class CountedCompleter<T
672      }
673  
674      /**
675 <     * Implements execution conventions for CountedCompleters
675 >     * Implements execution conventions for CountedCompleters.
676       */
677      protected final boolean exec() {
678          compute();
# Line 703 | Line 704 | public abstract class CountedCompleter<T
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) {
# Line 721 | Line 722 | public abstract class CountedCompleter<T
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   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines