91 |
|
if (!UNSAFE.compareAndSwapInt(this, stateOffset, UNDECIDED, next)) |
92 |
|
return false; |
93 |
|
if (next == INTERRUPTING) { |
94 |
< |
Thread t = runner; // recheck to avoid leaked interrupt |
94 |
> |
// Must check after CAS to avoid missed interrupt |
95 |
> |
Thread t = runner; |
96 |
|
if (t != null) |
97 |
|
t.interrupt(); |
98 |
|
state = INTERRUPTED; |
160 |
|
|
161 |
|
public boolean cancel(boolean mayInterruptIfRunning) { |
162 |
|
return state == UNDECIDED && |
163 |
< |
setCompletion(null, (mayInterruptIfRunning && runner != null) ? |
164 |
< |
INTERRUPTING : CANCELLED); |
163 |
> |
setCompletion(null, |
164 |
> |
mayInterruptIfRunning ? INTERRUPTING : CANCELLED); |
165 |
|
} |
166 |
|
|
167 |
|
/** |
231 |
|
return; |
232 |
|
|
233 |
|
try { |
234 |
+ |
// Recheck to avoid missed interrupt. |
235 |
+ |
if (state != UNDECIDED) |
236 |
+ |
return; |
237 |
|
V result; |
238 |
|
try { |
239 |
|
result = callable.call(); |
269 |
|
return false; |
270 |
|
|
271 |
|
try { |
272 |
+ |
// Recheck to avoid missed interrupt. |
273 |
+ |
if (state != UNDECIDED) |
274 |
+ |
return false; |
275 |
|
try { |
276 |
|
callable.call(); // don't set result |
277 |
|
return (state == UNDECIDED); |