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.5 by jsr166, Mon Mar 23 18:56:40 2015 UTC

# Line 5 | Line 5
5   */
6  
7   package java.util.concurrent;
8 +
9   import java.util.concurrent.locks.LockSupport;
10  
11   /**
# Line 134 | Line 135 | public class FutureTask<V> implements Ru
135  
136      public boolean cancel(boolean mayInterruptIfRunning) {
137          if (!(state == NEW &&
138 <              UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
138 >              U.compareAndSwapInt(this, STATE, NEW,
139                    mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
140              return false;
141          try {    // in case call to interrupt throws exception
# Line 144 | Line 145 | public class FutureTask<V> implements Ru
145                      if (t != null)
146                          t.interrupt();
147                  } finally { // final state
148 <                    UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
148 >                    U.putOrderedInt(this, STATE, INTERRUPTED);
149                  }
150              }
151          } finally {
# Line 198 | Line 199 | public class FutureTask<V> implements Ru
199       * @param v the value
200       */
201      protected void set(V v) {
202 <        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
202 >        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
203              outcome = v;
204 <            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
204 >            U.putOrderedInt(this, STATE, NORMAL); // final state
205              finishCompletion();
206          }
207      }
# Line 216 | Line 217 | public class FutureTask<V> implements Ru
217       * @param t the cause of failure
218       */
219      protected void setException(Throwable t) {
220 <        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
220 >        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
221              outcome = t;
222 <            UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
222 >            U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
223              finishCompletion();
224          }
225      }
226  
227      public void run() {
228          if (state != NEW ||
229 <            !UNSAFE.compareAndSwapObject(this, runnerOffset,
229 <                                         null, Thread.currentThread()))
229 >            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
230              return;
231          try {
232              Callable<V> c = callable;
# Line 263 | Line 263 | public class FutureTask<V> implements Ru
263       * designed for use with tasks that intrinsically execute more
264       * than once.
265       *
266 <     * @return true if successfully run and reset
266 >     * @return {@code true} if successfully run and reset
267       */
268      protected boolean runAndReset() {
269          if (state != NEW ||
270 <            !UNSAFE.compareAndSwapObject(this, runnerOffset,
271 <                                         null, Thread.currentThread()))
270 >            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
271              return false;
272          boolean ran = false;
273          int s = state;
# Line 335 | Line 334 | public class FutureTask<V> implements Ru
334      private void finishCompletion() {
335          // assert state > COMPLETING;
336          for (WaitNode q; (q = waiters) != null;) {
337 <            if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
337 >            if (U.compareAndSwapObject(this, WAITERS, q, null)) {
338                  for (;;) {
339                      Thread t = q.thread;
340                      if (t != null) {
# Line 362 | Line 361 | public class FutureTask<V> implements Ru
361       *
362       * @param timed true if use timed waits
363       * @param nanos time to wait, if timed
364 <     * @return state upon completion
364 >     * @return state upon completion or at timeout
365       */
366      private int awaitDone(boolean timed, long nanos)
367          throws InterruptedException {
368 <        final long deadline = timed ? System.nanoTime() + nanos : 0L;
368 >        // The code below is very delicate, to achieve these goals:
369 >        // - call nanoTime exactly once for each call to park
370 >        // - if nanos <= 0, return promptly without allocation or nanoTime
371 >        // - if nanos == Long.MIN_VALUE, don't underflow
372 >        // - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic
373 >        //   and we suffer a spurious wakeup, we will do no worse than
374 >        //   to park-spin for a while
375 >        long startTime = 0L;    // Special value 0L means not yet parked
376          WaitNode q = null;
377          boolean queued = false;
378          for (;;) {
373            if (Thread.interrupted()) {
374                removeWaiter(q);
375                throw new InterruptedException();
376            }
377
379              int s = state;
380              if (s > COMPLETING) {
381                  if (q != null)
382                      q.thread = null;
383                  return s;
384              }
385 <            else if (s == COMPLETING) // cannot time out yet
385 >            else if (s == COMPLETING)
386 >                // We may have already promised (via isDone) that we are done
387 >                // so never return empty-handed or throw InterruptedException
388                  Thread.yield();
389 <            else if (q == null)
389 >            else if (Thread.interrupted()) {
390 >                removeWaiter(q);
391 >                throw new InterruptedException();
392 >            }
393 >            else if (q == null) {
394 >                if (timed && nanos <= 0L)
395 >                    return s;
396                  q = new WaitNode();
397 +            }
398              else if (!queued)
399 <                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
400 <                                                     q.next = waiters, q);
399 >                queued = U.compareAndSwapObject(this, WAITERS,
400 >                                                q.next = waiters, q);
401              else if (timed) {
402 <                nanos = deadline - System.nanoTime();
403 <                if (nanos <= 0L) {
404 <                    removeWaiter(q);
405 <                    return state;
402 >                final long parkNanos;
403 >                if (startTime == 0L) { // first time
404 >                    startTime = System.nanoTime();
405 >                    if (startTime == 0L)
406 >                        startTime = 1L;
407 >                    parkNanos = nanos;
408 >                } else {
409 >                    long elapsed = System.nanoTime() - startTime;
410 >                    if (elapsed >= nanos) {
411 >                        removeWaiter(q);
412 >                        return state;
413 >                    }
414 >                    parkNanos = nanos - elapsed;
415                  }
416 <                LockSupport.parkNanos(this, nanos);
416 >                // nanoTime may be slow; recheck before parking
417 >                if (state < COMPLETING)
418 >                    LockSupport.parkNanos(this, parkNanos);
419              }
420              else
421                  LockSupport.park(this);
# Line 425 | Line 446 | public class FutureTask<V> implements Ru
446                          if (pred.thread == null) // check for race
447                              continue retry;
448                      }
449 <                    else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
429 <                                                          q, s))
449 >                    else if (!U.compareAndSwapObject(this, WAITERS, q, s))
450                          continue retry;
451                  }
452                  break;
# Line 435 | Line 455 | public class FutureTask<V> implements Ru
455      }
456  
457      // Unsafe mechanics
458 <    private static final sun.misc.Unsafe UNSAFE;
459 <    private static final long stateOffset;
460 <    private static final long runnerOffset;
461 <    private static final long waitersOffset;
458 >    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
459 >    private static final long STATE;
460 >    private static final long RUNNER;
461 >    private static final long WAITERS;
462      static {
463          try {
464 <            UNSAFE = sun.misc.Unsafe.getUnsafe();
465 <            Class<?> k = FutureTask.class;
466 <            stateOffset = UNSAFE.objectFieldOffset
467 <                (k.getDeclaredField("state"));
468 <            runnerOffset = UNSAFE.objectFieldOffset
469 <                (k.getDeclaredField("runner"));
450 <            waitersOffset = UNSAFE.objectFieldOffset
451 <                (k.getDeclaredField("waiters"));
464 >            STATE = U.objectFieldOffset
465 >                (FutureTask.class.getDeclaredField("state"));
466 >            RUNNER = U.objectFieldOffset
467 >                (FutureTask.class.getDeclaredField("runner"));
468 >            WAITERS = U.objectFieldOffset
469 >                (FutureTask.class.getDeclaredField("waiters"));
470          } catch (Exception e) {
471              throw new Error(e);
472          }
473 +
474 +        // Reduce the risk of rare disastrous classloading in first call to
475 +        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
476 +        Class<?> ensureLoaded = LockSupport.class;
477      }
478  
479   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines