ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk7/java/util/concurrent/FutureTask.java
(Generate patch)

Comparing jsr166/src/jdk7/java/util/concurrent/FutureTask.java (file contents):
Revision 1.1 by dl, Sun Dec 16 20:55:16 2012 UTC vs.
Revision 1.2 by jsr166, Fri Oct 3 23:48:09 2014 UTC

# Line 134 | Line 134 | public class FutureTask<V> implements Ru
134  
135      public boolean cancel(boolean mayInterruptIfRunning) {
136          if (!(state == NEW &&
137 <              UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
137 >              U.compareAndSwapInt(this, STATE, NEW,
138                    mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
139              return false;
140          try {    // in case call to interrupt throws exception
# Line 144 | Line 144 | public class FutureTask<V> implements Ru
144                      if (t != null)
145                          t.interrupt();
146                  } finally { // final state
147 <                    UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
147 >                    U.putOrderedInt(this, STATE, INTERRUPTED);
148                  }
149              }
150          } finally {
# Line 198 | Line 198 | public class FutureTask<V> implements Ru
198       * @param v the value
199       */
200      protected void set(V v) {
201 <        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
201 >        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
202              outcome = v;
203 <            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
203 >            U.putOrderedInt(this, STATE, NORMAL); // final state
204              finishCompletion();
205          }
206      }
# Line 216 | Line 216 | public class FutureTask<V> implements Ru
216       * @param t the cause of failure
217       */
218      protected void setException(Throwable t) {
219 <        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
219 >        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
220              outcome = t;
221 <            UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
221 >            U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
222              finishCompletion();
223          }
224      }
225  
226      public void run() {
227          if (state != NEW ||
228 <            !UNSAFE.compareAndSwapObject(this, runnerOffset,
229 <                                         null, Thread.currentThread()))
228 >            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
229              return;
230          try {
231              Callable<V> c = callable;
# Line 263 | Line 262 | public class FutureTask<V> implements Ru
262       * designed for use with tasks that intrinsically execute more
263       * than once.
264       *
265 <     * @return true if successfully run and reset
265 >     * @return {@code true} if successfully run and reset
266       */
267      protected boolean runAndReset() {
268          if (state != NEW ||
269 <            !UNSAFE.compareAndSwapObject(this, runnerOffset,
271 <                                         null, Thread.currentThread()))
269 >            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
270              return false;
271          boolean ran = false;
272          int s = state;
# Line 335 | Line 333 | public class FutureTask<V> implements Ru
333      private void finishCompletion() {
334          // assert state > COMPLETING;
335          for (WaitNode q; (q = waiters) != null;) {
336 <            if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
336 >            if (U.compareAndSwapObject(this, WAITERS, q, null)) {
337                  for (;;) {
338                      Thread t = q.thread;
339                      if (t != null) {
# Line 362 | Line 360 | public class FutureTask<V> implements Ru
360       *
361       * @param timed true if use timed waits
362       * @param nanos time to wait, if timed
363 <     * @return state upon completion
363 >     * @return state upon completion or at timeout
364       */
365      private int awaitDone(boolean timed, long nanos)
366          throws InterruptedException {
367 <        final long deadline = timed ? System.nanoTime() + nanos : 0L;
367 >        // The code below is very delicate, to achieve these goals:
368 >        // - call nanoTime exactly once for each call to park
369 >        // - if nanos <= 0, return promptly without allocation or nanoTime
370 >        // - if nanos == Long.MIN_VALUE, don't underflow
371 >        // - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic
372 >        //   and we suffer a spurious wakeup, we will do no worse than
373 >        //   to park-spin for a while
374 >        long startTime = 0L;    // Special value 0L means not yet parked
375          WaitNode q = null;
376          boolean queued = false;
377          for (;;) {
# Line 383 | Line 388 | public class FutureTask<V> implements Ru
388              }
389              else if (s == COMPLETING) // cannot time out yet
390                  Thread.yield();
391 <            else if (q == null)
391 >            else if (q == null) {
392 >                if (timed && nanos <= 0L)
393 >                    return s;
394                  q = new WaitNode();
395 +            }
396              else if (!queued)
397 <                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
398 <                                                     q.next = waiters, q);
397 >                queued = U.compareAndSwapObject(this, WAITERS,
398 >                                                q.next = waiters, q);
399              else if (timed) {
400 <                nanos = deadline - System.nanoTime();
401 <                if (nanos <= 0L) {
402 <                    removeWaiter(q);
403 <                    return state;
400 >                final long parkNanos;
401 >                if (startTime == 0L) { // first time
402 >                    startTime = System.nanoTime();
403 >                    if (startTime == 0L)
404 >                        startTime = 1L;
405 >                    parkNanos = nanos;
406 >                } else {
407 >                    long elapsed = System.nanoTime() - startTime;
408 >                    if (elapsed >= nanos) {
409 >                        removeWaiter(q);
410 >                        return state;
411 >                    }
412 >                    parkNanos = nanos - elapsed;
413                  }
414 <                LockSupport.parkNanos(this, nanos);
414 >                LockSupport.parkNanos(this, parkNanos);
415              }
416              else
417                  LockSupport.park(this);
# Line 425 | Line 442 | public class FutureTask<V> implements Ru
442                          if (pred.thread == null) // check for race
443                              continue retry;
444                      }
445 <                    else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
429 <                                                          q, s))
445 >                    else if (!U.compareAndSwapObject(this, WAITERS, q, s))
446                          continue retry;
447                  }
448                  break;
# Line 435 | Line 451 | public class FutureTask<V> implements Ru
451      }
452  
453      // Unsafe mechanics
454 <    private static final sun.misc.Unsafe UNSAFE;
455 <    private static final long stateOffset;
456 <    private static final long runnerOffset;
457 <    private static final long waitersOffset;
454 >    private static final sun.misc.Unsafe U;
455 >    private static final long STATE;
456 >    private static final long RUNNER;
457 >    private static final long WAITERS;
458      static {
459          try {
460 <            UNSAFE = sun.misc.Unsafe.getUnsafe();
460 >            U = sun.misc.Unsafe.getUnsafe();
461              Class<?> k = FutureTask.class;
462 <            stateOffset = UNSAFE.objectFieldOffset
463 <                (k.getDeclaredField("state"));
464 <            runnerOffset = UNSAFE.objectFieldOffset
449 <                (k.getDeclaredField("runner"));
450 <            waitersOffset = UNSAFE.objectFieldOffset
451 <                (k.getDeclaredField("waiters"));
462 >            STATE   = U.objectFieldOffset(k.getDeclaredField("state"));
463 >            RUNNER  = U.objectFieldOffset(k.getDeclaredField("runner"));
464 >            WAITERS = U.objectFieldOffset(k.getDeclaredField("waiters"));
465          } catch (Exception e) {
466              throw new Error(e);
467          }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines