src/java.base/share/classes/java/util/concurrent/FutureTask.java
Print this page
*** 161,181 ****
return state != NEW;
}
public boolean cancel(boolean mayInterruptIfRunning) {
if (!(state == NEW &&
! UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally { // final state
! UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
--- 161,181 ----
return state != NEW;
}
public boolean cancel(boolean mayInterruptIfRunning) {
if (!(state == NEW &&
! U.compareAndSwapInt(this, STATE, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally { // final state
! U.putOrderedInt(this, STATE, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
*** 225,237 ****
* upon successful completion of the computation.
*
* @param v the value
*/
protected void set(V v) {
! if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
! UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
/**
--- 225,237 ----
* upon successful completion of the computation.
*
* @param v the value
*/
protected void set(V v) {
! if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = v;
! U.putOrderedInt(this, STATE, NORMAL); // final state
finishCompletion();
}
}
/**
*** 243,263 ****
* upon failure of the computation.
*
* @param t the cause of failure
*/
protected void setException(Throwable t) {
! if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = t;
! UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
finishCompletion();
}
}
public void run() {
if (state != NEW ||
! !UNSAFE.compareAndSwapObject(this, runnerOffset,
! null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
--- 243,262 ----
* upon failure of the computation.
*
* @param t the cause of failure
*/
protected void setException(Throwable t) {
! if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = t;
! U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
finishCompletion();
}
}
public void run() {
if (state != NEW ||
! !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
*** 294,305 ****
*
* @return {@code true} if successfully run and reset
*/
protected boolean runAndReset() {
if (state != NEW ||
! !UNSAFE.compareAndSwapObject(this, runnerOffset,
! null, Thread.currentThread()))
return false;
boolean ran = false;
int s = state;
try {
Callable<V> c = callable;
--- 293,303 ----
*
* @return {@code true} if successfully run and reset
*/
protected boolean runAndReset() {
if (state != NEW ||
! !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return false;
boolean ran = false;
int s = state;
try {
Callable<V> c = callable;
*** 362,372 ****
* nulls out callable.
*/
private void finishCompletion() {
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {
! if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
for (;;) {
Thread t = q.thread;
if (t != null) {
q.thread = null;
LockSupport.unpark(t);
--- 360,370 ----
* nulls out callable.
*/
private void finishCompletion() {
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {
! if (U.compareAndSwapObject(this, WAITERS, q, null)) {
for (;;) {
Thread t = q.thread;
if (t != null) {
q.thread = null;
LockSupport.unpark(t);
*** 389,403 ****
/**
* Awaits completion or aborts on interrupt or timeout.
*
* @param timed true if use timed waits
* @param nanos time to wait, if timed
! * @return state upon completion
*/
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
! final long deadline = timed ? System.nanoTime() + nanos : 0L;
WaitNode q = null;
boolean queued = false;
for (;;) {
if (Thread.interrupted()) {
removeWaiter(q);
--- 387,408 ----
/**
* Awaits completion or aborts on interrupt or timeout.
*
* @param timed true if use timed waits
* @param nanos time to wait, if timed
! * @return state upon completion or at timeout
*/
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
! // The code below is very delicate, to achieve these goals:
! // - call nanoTime exactly once for each call to park
! // - if nanos <= 0, return promptly without allocation or nanoTime
! // - if nanos == Long.MIN_VALUE, don't underflow
! // - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic
! // and we suffer a spurious wakeup, we will do no worse than
! // to park-spin for a while
! long startTime = 0L; // Special value 0L means not yet parked
WaitNode q = null;
boolean queued = false;
for (;;) {
if (Thread.interrupted()) {
removeWaiter(q);
*** 410,431 ****
q.thread = null;
return s;
}
else if (s == COMPLETING) // cannot time out yet
Thread.yield();
! else if (q == null)
q = new WaitNode();
else if (!queued)
! queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
q.next = waiters, q);
else if (timed) {
! nanos = deadline - System.nanoTime();
! if (nanos <= 0L) {
removeWaiter(q);
return state;
}
! LockSupport.parkNanos(this, nanos);
}
else
LockSupport.park(this);
}
}
--- 415,448 ----
q.thread = null;
return s;
}
else if (s == COMPLETING) // cannot time out yet
Thread.yield();
! else if (q == null) {
! if (timed && nanos <= 0L)
! return s;
q = new WaitNode();
+ }
else if (!queued)
! queued = U.compareAndSwapObject(this, WAITERS,
q.next = waiters, q);
else if (timed) {
! final long parkNanos;
! if (startTime == 0L) { // first time
! startTime = System.nanoTime();
! if (startTime == 0L)
! startTime = 1L;
! parkNanos = nanos;
! } else {
! long elapsed = System.nanoTime() - startTime;
! if (elapsed >= nanos) {
removeWaiter(q);
return state;
}
! parkNanos = nanos - elapsed;
! }
! LockSupport.parkNanos(this, parkNanos);
}
else
LockSupport.park(this);
}
}
*** 452,485 ****
else if (pred != null) {
pred.next = s;
if (pred.thread == null) // check for race
continue retry;
}
! else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
! q, s))
continue retry;
}
break;
}
}
}
// Unsafe mechanics
! private static final sun.misc.Unsafe UNSAFE;
! private static final long stateOffset;
! private static final long runnerOffset;
! private static final long waitersOffset;
static {
try {
! UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> k = FutureTask.class;
! stateOffset = UNSAFE.objectFieldOffset
! (k.getDeclaredField("state"));
! runnerOffset = UNSAFE.objectFieldOffset
! (k.getDeclaredField("runner"));
! waitersOffset = UNSAFE.objectFieldOffset
! (k.getDeclaredField("waiters"));
} catch (Exception e) {
throw new Error(e);
}
}
--- 469,498 ----
else if (pred != null) {
pred.next = s;
if (pred.thread == null) // check for race
continue retry;
}
! else if (!U.compareAndSwapObject(this, WAITERS, q, s))
continue retry;
}
break;
}
}
}
// Unsafe mechanics
! private static final sun.misc.Unsafe U;
! private static final long STATE;
! private static final long RUNNER;
! private static final long WAITERS;
static {
try {
! U = sun.misc.Unsafe.getUnsafe();
Class<?> k = FutureTask.class;
! STATE = U.objectFieldOffset(k.getDeclaredField("state"));
! RUNNER = U.objectFieldOffset(k.getDeclaredField("runner"));
! WAITERS = U.objectFieldOffset(k.getDeclaredField("waiters"));
} catch (Exception e) {
throw new Error(e);
}
}