5 |
|
*/ |
6 |
|
|
7 |
|
package java.util.concurrent; |
8 |
+ |
|
9 |
|
import java.util.concurrent.locks.LockSupport; |
10 |
|
|
11 |
|
/** |
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 |
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 { |
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 |
|
} |
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; |
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; |
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) { |
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); |
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; |
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 |
|
} |