--- jsr166/src/jsr166y/Phaser.java 2009/08/24 12:15:46 1.39 +++ jsr166/src/jsr166y/Phaser.java 2010/10/24 21:45:39 1.48 @@ -97,18 +97,21 @@ import java.util.concurrent.locks.LockSu *

Monitoring. While synchronization methods may be invoked * only by registered parties, the current state of a phaser may be * monitored by any caller. At any given moment there are {@link - * #getRegisteredParties}, where {@link #getArrivedParties} have - * arrived at the current phase ({@link #getPhase}). When the - * remaining {@link #getUnarrivedParties}) arrive, the phase - * advances. Method {@link #toString} returns snapshots of these state - * queries in a form convenient for informal monitoring. + * #getRegisteredParties} parties in total, of which {@link + * #getArrivedParties} have arrived at the current phase ({@link + * #getPhase}). When the remaining ({@link #getUnarrivedParties}) + * parties arrive, the phase advances. The values returned by these + * methods may reflect transient states and so are not in general + * useful for synchronization control. Method {@link #toString} + * returns snapshots of these state queries in a form convenient for + * informal monitoring. * *

Sample usages: * *

A {@code Phaser} may be used instead of a {@code CountDownLatch} - * to control a one-shot action serving a variable number of - * parties. The typical idiom is for the method setting this up to - * first register, then start the actions, then deregister, as in: + * to control a one-shot action serving a variable number of parties. + * The typical idiom is for the method setting this up to first + * register, then start the actions, then deregister, as in: * *

 {@code
  * void runTasks(List tasks) {
@@ -139,14 +142,14 @@ import java.util.concurrent.locks.LockSu
  *     }
  *   };
  *   phaser.register();
- *   for (Runnable task : tasks) {
+ *   for (final Runnable task : tasks) {
  *     phaser.register();
  *     new Thread() {
  *       public void run() {
  *         do {
  *           task.run();
  *           phaser.arriveAndAwaitAdvance();
- *         } while(!phaser.isTerminated();
+ *         } while (!phaser.isTerminated());
  *       }
  *     }.start();
  *   }
@@ -155,49 +158,45 @@ import java.util.concurrent.locks.LockSu
  *
  * If the main task must later await termination, it
  * may re-register and then execute a similar loop:
- * 
 {@code
+ *  
 {@code
  *   // ...
  *   phaser.register();
  *   while (!phaser.isTerminated())
- *     phaser.arriveAndAwaitAdvance();
- * }
+ * phaser.arriveAndAwaitAdvance();}
* - * Related constructions may be used to await particular phase numbers + *

Related constructions may be used to await particular phase numbers * in contexts where you are sure that the phase will never wrap around * {@code Integer.MAX_VALUE}. For example: * - *

 {@code
- *   void awaitPhase(Phaser phaser, int phase) {
- *     int p = phaser.register(); // assumes caller not already registered
- *     while (p < phase) {
- *       if (phaser.isTerminated())
- *         // ... deal with unexpected termination
- *       else
- *         p = phaser.arriveAndAwaitAdvance();
- *     }
- *     phaser.arriveAndDeregister();
+ *  
 {@code
+ * void awaitPhase(Phaser phaser, int phase) {
+ *   int p = phaser.register(); // assumes caller not already registered
+ *   while (p < phase) {
+ *     if (phaser.isTerminated())
+ *       // ... deal with unexpected termination
+ *     else
+ *       p = phaser.arriveAndAwaitAdvance();
  *   }
- * }
+ * phaser.arriveAndDeregister(); + * }}
* * *

To create a set of tasks using a tree of phasers, * you could use code of the following form, assuming a * Task class with a constructor accepting a phaser that - * it registers for upon construction: + * it registers with upon construction: + * *

 {@code
- * void build(Task[] actions, int lo, int hi, Phaser b) {
- *   int step = (hi - lo) / TASKS_PER_PHASER;
- *   if (step > 1) {
- *     int i = lo;
- *     while (i < hi) {
- *       int r = Math.min(i + step, hi);
- *       build(actions, i, r, new Phaser(b));
- *       i = r;
+ * void build(Task[] actions, int lo, int hi, Phaser ph) {
+ *   if (hi - lo > TASKS_PER_PHASER) {
+ *     for (int i = lo; i < hi; i += TASKS_PER_PHASER) {
+ *       int j = Math.min(i + TASKS_PER_PHASER, hi);
+ *       build(actions, i, j, new Phaser(ph));
  *     }
  *   } else {
  *     for (int i = lo; i < hi; ++i)
- *       actions[i] = new Task(b);
- *       // assumes new Task(b) performs b.register()
+ *       actions[i] = new Task(ph);
+ *       // assumes new Task(ph) performs ph.register()
  *   }
  * }
  * // .. initially called, for n tasks via
@@ -208,8 +207,6 @@ import java.util.concurrent.locks.LockSu
  * be appropriate for extremely small per-barrier task bodies (thus
  * high rates), or up to hundreds for extremely large ones.
  *
- * 
- * *

Implementation notes: This implementation restricts the * maximum number of parties to 65535. Attempts to register additional * parties result in {@code IllegalStateException}. However, you can and @@ -246,7 +243,6 @@ public class Phaser { */ private volatile long state; - private static final int ushortBits = 16; private static final int ushortMask = 0xffff; private static final int phaseMask = 0x7fffffff; @@ -350,7 +346,7 @@ public class Phaser { } /** - * Creates a new phaser with the given numbers of registered + * Creates a new phaser with the given number of registered * unarrived parties, initial phase number 0, and no parent. * * @param parties the number of parties required to trip barrier @@ -382,7 +378,7 @@ public class Phaser { } /** - * Creates a new phaser with the given parent and numbers of + * Creates a new phaser with the given parent and number of * registered unarrived parties. If parent is non-null, this phaser * is registered with the parent and its initial phase number is * the same as that of parent phaser. @@ -420,10 +416,11 @@ public class Phaser { /** * Adds the given number of new unarrived parties to this phaser. * - * @param parties the number of parties required to trip barrier + * @param parties the number of additional parties required to trip barrier * @return the arrival phase number to which this registration applied * @throws IllegalStateException if attempting to register more * than the maximum supported number of parties + * @throws IllegalArgumentException if {@code parties < 0} */ public int bulkRegister(int parties) { if (parties < 0) @@ -565,10 +562,10 @@ public class Phaser { * Arrives at the barrier and awaits others. Equivalent in effect * to {@code awaitAdvance(arrive())}. If you need to await with * interruption or timeout, you can arrange this with an analogous - * construction using one of the other forms of the awaitAdvance - * method. If instead you need to deregister upon arrival use - * {@code arriveAndDeregister}. It is an unenforced usage error - * for an unregistered party to invoke this method. + * construction using one of the other forms of the {@code + * awaitAdvance} method. If instead you need to deregister upon + * arrival, use {@link #arriveAndDeregister}. It is an unenforced + * usage error for an unregistered party to invoke this method. * * @return the arrival phase number, or a negative number if terminated * @throws IllegalStateException if not terminated and the number @@ -760,13 +757,22 @@ public class Phaser { } /** - * Overridable method to perform an action upon phase advance, and - * to control termination. This method is invoked whenever the - * barrier is tripped (and thus all other waiting parties are - * dormant). If it returns {@code true}, then, rather than advance - * the phase number, this barrier will be set to a final - * termination state, and subsequent calls to {@link #isTerminated} - * will return true. + * Overridable method to perform an action upon impending phase + * advance, and to control termination. This method is invoked + * upon arrival of the party tripping the barrier (when all other + * waiting parties are dormant). If this method returns {@code + * true}, then, rather than advance the phase number, this barrier + * will be set to a final termination state, and subsequent calls + * to {@link #isTerminated} will return true. Any (unchecked) + * Exception or Error thrown by an invocation of this method is + * propagated to the party attempting to trip the barrier, in + * which case no advance occurs. + * + *

The arguments to this method provide the state of the phaser + * prevailing for the current transition. (When called from within + * an implementation of {@code onAdvance} the values returned by + * methods such as {@code getPhase} may or may not reliably + * indicate the state to which this transition applies.) * *

The default version returns {@code true} when the number of * registered parties is zero. Normally, overrides that arrange @@ -774,11 +780,13 @@ public class Phaser { * property. * *

You may override this method to perform an action with side - * effects visible to participating tasks, but it is in general - * only sensible to do so in designs where all parties register - * before any arrive, and all {@link #awaitAdvance} at each phase. + * effects visible to participating tasks, but it is only sensible + * to do so in designs where all parties register before any + * arrive, and all {@link #awaitAdvance} at each phase. * Otherwise, you cannot ensure lack of interference from other - * parties during the invocation of this method. + * parties during the invocation of this method. Additionally, + * method {@code onAdvance} may be invoked more than once per + * transition if registrations are intermixed with arrivals. * * @param phase the phase number on entering the barrier * @param registeredParties the current number of registered parties @@ -820,6 +828,7 @@ public class Phaser { volatile boolean wasInterrupted = false; volatile Thread thread; // nulled to cancel wait QNode next; + QNode(Phaser phaser, int phase, boolean interruptible, boolean timed, long startTime, long nanos) { this.phaser = phaser; @@ -830,12 +839,14 @@ public class Phaser { this.nanos = nanos; thread = Thread.currentThread(); } + public boolean isReleasable() { return (thread == null || phaser.getPhase() != phase || (interruptible && wasInterrupted) || (timed && (nanos - (System.nanoTime() - startTime)) <= 0)); } + public boolean block() { if (Thread.interrupted()) { wasInterrupted = true; @@ -852,6 +863,7 @@ public class Phaser { } return isReleasable(); } + void signal() { Thread t = thread; if (t != null) { @@ -859,16 +871,17 @@ public class Phaser { LockSupport.unpark(t); } } + boolean doWait() { if (thread != null) { try { - ForkJoinPool.managedBlock(this, false); + ForkJoinPool.managedBlock(this); } catch (InterruptedException ie) { + wasInterrupted = true; // can't currently happen } } return wasInterrupted; } - } /** @@ -910,8 +923,8 @@ public class Phaser { node = new QNode(this, phase, false, false, 0, 0); else if (!queued) queued = tryEnqueue(node); - else - interrupted = node.doWait(); + else if (node.doWait()) + interrupted = true; } if (node != null) node.thread = null; @@ -937,8 +950,8 @@ public class Phaser { node = new QNode(this, phase, true, false, 0, 0); else if (!queued) queued = tryEnqueue(node); - else - interrupted = node.doWait(); + else if (node.doWait()) + interrupted = true; } if (node != null) node.thread = null; @@ -969,8 +982,8 @@ public class Phaser { node = new QNode(this, phase, true, true, startTime, nanos); else if (!queued) queued = tryEnqueue(node); - else - interrupted = node.doWait(); + else if (node.doWait()) + interrupted = true; } if (node != null) node.thread = null;