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

Comparing jsr166/src/jsr166e/CountedCompleter.java (file contents):
Revision 1.2 by dl, Thu Aug 16 12:24:58 2012 UTC vs.
Revision 1.6 by jsr166, Tue Oct 30 16:05:35 2012 UTC

# Line 5 | Line 5
5   */
6  
7   package jsr166e;
8
8   /**
9   * A {@link ForkJoinTask} with a completion action
10   * performed when triggered and there are no remaining pending
# Line 22 | Line 21 | package jsr166e;
21   * decremented; otherwise, the completion action is performed, and if
22   * this completer itself has a completer, the process is continued
23   * with its completer.  As is the case with related synchronization
24 < * components such as {@link Phaser} and {@link
25 < * java.util.concurrent.Semaphore} these methods affect only internal
26 < * counts; they do not establish any further internal bookkeeping. In
27 < * particular, the identities of pending tasks are not maintained. As
28 < * illustrated below, you can create subclasses that do record some or
29 < * all pended tasks or their results when needed.
24 > * components such as {@link java.util.concurrent.Phaser Phaser} and
25 > * {@link java.util.concurrent.Semaphore Semaphore}, these methods
26 > * affect only internal counts; they do not establish any further
27 > * internal bookkeeping. In particular, the identities of pending
28 > * tasks are not maintained. As illustrated below, you can create
29 > * subclasses that do record some or all pending tasks or their
30 > * results when needed.
31   *
32   * <p>A concrete CountedCompleter class must define method {@link
33   * #compute}, that should, in almost all use cases, invoke {@code
# Line 141 | Line 141 | package jsr166e;
141   *
142   * As a further improvement, notice that the left task need not even
143   * exist.  Instead of creating a new one, we can iterate using the
144 < * original task, and add a pending count for each fork:
144 > * original task, and add a pending count for each fork. Additionally,
145 > * this version uses {@code helpComplete} to streamline assistance in
146 > * the execution of forked tasks.
147   *
148   * <pre> {@code
149   * class ForEach<E> ...
# Line 155 | Line 157 | package jsr166e;
157   *         }
158   *         if (h > l)
159   *             op.apply(array[l]);
160 < *         tryComplete();
160 > *         helpComplete();
161   *     }
162   * }</pre>
163   *
# Line 377 | Line 379 | public abstract class CountedCompleter<T
379      }
380  
381      /**
382 +     * Returns the root of the current computation; i.e., this
383 +     * task if it has no completer, else its completer's root.
384 +     *
385 +     * @return the root of the current computation
386 +     */
387 +    public final CountedCompleter<?> getRoot() {
388 +        CountedCompleter<?> a = this, p;
389 +        while ((p = a.completer) != null)
390 +            a = p;
391 +        return a;
392 +    }
393 +
394 +    /**
395       * If the pending count is nonzero, decrements the count;
396       * otherwise invokes {@link #onCompletion} and then similarly
397       * tries to complete this task's completer, if one exists,
# Line 398 | Line 413 | public abstract class CountedCompleter<T
413      }
414  
415      /**
416 +     * Identical to {@link #tryComplete}, but may additionally execute
417 +     * other tasks within the current computation (i.e., those
418 +     * with the same {@link #getRoot}.
419 +     */
420 +    public final void helpComplete() {
421 +        CountedCompleter<?> a = this, s = a;
422 +        for (int c;;) {
423 +            if ((c = a.pending) == 0) {
424 +                a.onCompletion(s);
425 +                if ((a = (s = a).completer) == null) {
426 +                    s.quietlyComplete();
427 +                    return;
428 +                }
429 +            }
430 +            else if (U.compareAndSwapInt(a, PENDING, c, c - 1)) {
431 +                CountedCompleter<?> root = a.getRoot();
432 +                Thread thread = Thread.currentThread();
433 +                ForkJoinPool.WorkQueue wq =
434 +                    (thread instanceof ForkJoinWorkerThread) ?
435 +                    ((ForkJoinWorkerThread)thread).workQueue : null;
436 +                ForkJoinTask<?> t;
437 +                while ((t = (wq != null) ? wq.popCC(root) :
438 +                        ForkJoinPool.popCCFromCommonPool(root)) != null) {
439 +                    t.doExec();
440 +                    if (root.isDone())
441 +                        break;
442 +                }
443 +                return;
444 +            }
445 +        }
446 +    }
447 +
448 +    /**
449       * Regardless of pending count, invokes {@link #onCompletion},
450       * marks this task as complete and further triggers {@link
451       * #tryComplete} on this task's completer, if one exists. This
# Line 464 | Line 512 | public abstract class CountedCompleter<T
512          }
513      }
514  
467
515      /**
516       * Returns a sun.misc.Unsafe.  Suitable for use in a 3rd party package.
517       * Replace with a simple call to Unsafe.getUnsafe when integrating

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines