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 |
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 { |
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 |
|
} |
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; |
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; |
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) { |
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 (;;) { |
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); |
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; |
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 |
|
} |