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

Comparing jsr166/src/jsr166y/ForkJoinTask.java (file contents):
Revision 1.86 by dl, Mon Feb 20 18:20:06 2012 UTC vs.
Revision 1.87 by dl, Sun Mar 4 15:52:45 2012 UTC

# Line 137 | Line 137 | import java.lang.reflect.Constructor;
137   * {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
138   * may be of use in constructing custom subclasses for problems that
139   * are not statically structured as DAGs. To support such usages a
140 < * ForkJoinTask may be atomically <em>marked</em> using {@link
141 < * #markForkJoinTask} and checked for marking using {@link
142 < * #isMarkedForkJoinTask}. The ForkJoinTask implementation does not
143 < * use these {@code protected} methods or marks for any purpose, but
140 > * ForkJoinTask may be atomically <em>tagged</em> with a {@code
141 > * short} value using {@link #setForkJoinTaskTag} or {@link
142 > * #compareAndSetForkJoinTaskTag} and checked using {@link
143 > * #getForkJoinTaskTag}. The ForkJoinTask implementation does not
144 > * use these {@code protected} methods or tags for any purpose, but
145   * they may be of use in the construction of specialized subclasses.
146   * For example, parallel graph traversals can use the supplied methods
147   * to avoid revisiting nodes/tasks that have already been processed.
148 < * Also, completion based designs can use them to record that one
149 < * subtask has completed. (Method names for marking are bulky in part
150 < * to encourage definition of methods that reflect their usage
150 < * patterns.)
148 > * Also, completion based designs can use them to record that subtasks
149 > * have completed. (Method names for tagging are bulky in part to
150 > * encourage definition of methods that reflect their usage patterns.)
151   *
152   * <p>Most base support methods are {@code final}, to prevent
153   * overriding of implementations that are intrinsically tied to the
# Line 213 | Line 213 | public abstract class ForkJoinTask<V> im
213       * thin-lock techniques, so use some odd coding idioms that tend
214       * to avoid them, mainly by arranging that every synchronized
215       * block performs a wait, notifyAll or both.
216 +     *
217 +     * These control bits occupy only (some of) the upper half (16
218 +     * bits) of status field. The lower bits are used for user-defined
219 +     * tags.
220       */
221  
222      /** The run status of this task */
# Line 221 | Line 225 | public abstract class ForkJoinTask<V> im
225      static final int NORMAL      = 0xf0000000;  // must be negative
226      static final int CANCELLED   = 0xc0000000;  // must be < NORMAL
227      static final int EXCEPTIONAL = 0x80000000;  // must be < CANCELLED
228 <    static final int SIGNAL      = 0x00000001;
229 <    static final int MARKED      = 0x00000002;
228 >    static final int SIGNAL      = 0x00010000;  // must be >= 1 << 16
229 >    static final int SMASK       = 0x0000ffff;  // short bits for tags
230  
231      /**
232       * Marks completion and wakes up threads waiting to join this
233 <     * task. A specialization for NORMAL completion is in method
230 <     * doExec.
233 >     * task.
234       *
235       * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
236       * @return completion status on exit
# Line 237 | Line 240 | public abstract class ForkJoinTask<V> im
240              if ((s = status) < 0)
241                  return s;
242              if (U.compareAndSwapInt(this, STATUS, s, s | completion)) {
243 <                if ((s & SIGNAL) != 0)
243 >                if ((s >>> 16) != 0)
244                      synchronized (this) { notifyAll(); }
245                  return completion;
246              }
# Line 259 | Line 262 | public abstract class ForkJoinTask<V> im
262              } catch (Throwable rex) {
263                  return setExceptionalCompletion(rex);
264              }
265 <            while ((s = status) >= 0 && completed) {
266 <                if (U.compareAndSwapInt(this, STATUS, s, s | NORMAL)) {
264 <                    if ((s & SIGNAL) != 0)
265 <                        synchronized (this) { notifyAll(); }
266 <                    return NORMAL;
267 <                }
268 <            }
265 >            if (completed)
266 >                s = setCompletion(NORMAL);
267          }
268          return s;
269      }
# Line 328 | Line 326 | public abstract class ForkJoinTask<V> im
326          return s;
327      }
328  
331
329      /**
330       * Implementation for join, get, quietlyJoin. Directly handles
331       * only cases of already-completed, external wait, and
# Line 907 | Line 904 | public abstract class ForkJoinTask<V> im
904      }
905  
906      /**
907 +     * Completes this task. The most recent value established by
908 +     * {@link #setRawResult} (or {@code null}) will be returned as the
909 +     * result of subsequent invocations of {@code join} and related
910 +     * operations. This method may be useful when processing sets of
911 +     * tasks when some do not otherwise complete normally. Its use in
912 +     * other situations is discouraged.
913 +     */
914 +    public final void quietlyComplete() {
915 +        setCompletion(NORMAL);
916 +    }
917 +
918 +    /**
919       * Waits if necessary for the computation to complete, and then
920       * retrieves its result.
921       *
# Line 1302 | Line 1311 | public abstract class ForkJoinTask<V> im
1311          return wt.pool.nextTaskFor(wt.workQueue);
1312      }
1313  
1314 <    // Mark-bit operations
1314 >    // tag operations
1315  
1316      /**
1317 <     * Returns true if this task is marked.
1317 >     * Returns the tag for this task.
1318       *
1319 <     * @return true if this task is marked
1319 >     * @return the tag for this task
1320       * @since 1.8
1321       */
1322 <    public final boolean isMarkedForkJoinTask() {
1323 <        return (status & MARKED) != 0;
1322 >    public final short getForkJoinTaskTag() {
1323 >        return (short)status;
1324      }
1325  
1326      /**
1327 <     * Atomically sets the mark on this task.
1327 >     * Atomically sets the tag value for this task.
1328       *
1329 <     * @return true if this task was previously unmarked
1329 >     * @param tag the tag value
1330 >     * @return the previous value of the tag
1331       * @since 1.8
1332       */
1333 <    public final boolean markForkJoinTask() {
1333 >    public final short setForkJoinTaskTag(short tag) {
1334          for (int s;;) {
1335 <            if (((s = status) & MARKED) != 0)
1336 <                return false;
1337 <            if (U.compareAndSwapInt(this, STATUS, s, s | MARKED))
1328 <                return true;
1335 >            if (U.compareAndSwapInt(this, STATUS, s = status,
1336 >                                    (s & ~SMASK) | (tag & SMASK)))
1337 >                return (short)s;
1338          }
1339      }
1340  
1341      /**
1342 <     * Atomically clears the mark on this task.
1342 >     * Atomically conditionally sets the tag value for this task.
1343 >     * Among other applications, tags can be used as visit markers
1344 >     * in tasks operating on graphs, as in mathods that check: {@code
1345 >     * if (task.compareAndSetForkJoinTaskTag((short)0, (short)1))}
1346 >     * before processing, otherwise exiting because the node has
1347 >     * already been visited.
1348       *
1349 <     * @return true if this task was previously marked
1349 >     * @param e the expected tag value
1350 >     * @param tag the new tag value
1351 >     * @return true if successful; i.e., the current value was
1352 >     * equal to e and is now tag.
1353       * @since 1.8
1354       */
1355 <    public final boolean unmarkForkJoinTask() {
1355 >    public final boolean compareAndSetForkJoinTaskTag(short e, short tag) {
1356          for (int s;;) {
1357 <            if (((s = status) & MARKED) == 0)
1357 >            if ((short)(s = status) != e)
1358                  return false;
1359 <            if (U.compareAndSwapInt(this, STATUS, s, s & ~MARKED))
1359 >            if (U.compareAndSwapInt(this, STATUS, s,
1360 >                                    (s & ~SMASK) | (tag & SMASK)))
1361                  return true;
1362          }
1363      }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines