82 |
|
* @return true if this call caused transition from UNDECIDED to completed |
83 |
|
*/ |
84 |
|
private boolean setCompletion(Object x, int mode) { |
85 |
– |
Thread r = runner; |
86 |
– |
if (r == Thread.currentThread()) // null out runner on completion |
87 |
– |
UNSAFE.putObject(this, runnerOffset, r = null); // nonvolatile OK |
85 |
|
int next = ((mode == INTERRUPTING) ? // set up transient states |
86 |
< |
(r != null) ? INTERRUPTING : CANCELLED : |
86 |
> |
(runner != null) ? INTERRUPTING : CANCELLED : |
87 |
|
(x != null) ? COMPLETING : mode); |
88 |
< |
for (;;) { |
89 |
< |
int s = state; |
90 |
< |
if (s == UNDECIDED) { |
91 |
< |
if (UNSAFE.compareAndSwapInt(this, stateOffset, |
92 |
< |
UNDECIDED, next)) { |
93 |
< |
if (next == INTERRUPTING) { |
94 |
< |
Thread t = runner; // recheck |
95 |
< |
if (t != null) |
96 |
< |
t.interrupt(); |
97 |
< |
state = CANCELLED; |
98 |
< |
} |
99 |
< |
else if (next == COMPLETING) { |
103 |
< |
outcome = x; |
104 |
< |
state = mode; |
105 |
< |
} |
106 |
< |
if (waiters != null) |
107 |
< |
releaseAll(); |
108 |
< |
done(); |
109 |
< |
return true; |
110 |
< |
} |
111 |
< |
} |
112 |
< |
else if (s == INTERRUPTING) |
113 |
< |
Thread.yield(); // wait out pending cancellation interrupt |
114 |
< |
else |
115 |
< |
return false; |
88 |
> |
if (!UNSAFE.compareAndSwapInt(this, stateOffset, |
89 |
> |
UNDECIDED, next)) |
90 |
> |
return false; |
91 |
> |
if (next == INTERRUPTING) { |
92 |
> |
Thread t = runner; // recheck |
93 |
> |
if (t != null) |
94 |
> |
t.interrupt(); |
95 |
> |
state = CANCELLED; |
96 |
> |
} |
97 |
> |
else if (next == COMPLETING) { |
98 |
> |
outcome = x; |
99 |
> |
state = mode; |
100 |
|
} |
101 |
+ |
if (waiters != null) |
102 |
+ |
releaseAll(); |
103 |
+ |
done(); |
104 |
+ |
return true; |
105 |
|
} |
106 |
|
|
107 |
|
/** |
222 |
|
} |
223 |
|
|
224 |
|
public void run() { |
225 |
< |
if (state == UNDECIDED && |
226 |
< |
UNSAFE.compareAndSwapObject(this, runnerOffset, |
227 |
< |
null, Thread.currentThread())) { |
225 |
> |
if (state != UNDECIDED || |
226 |
> |
!UNSAFE.compareAndSwapObject(this, runnerOffset, |
227 |
> |
null, Thread.currentThread())) |
228 |
> |
return; |
229 |
> |
|
230 |
> |
try { |
231 |
|
V result; |
232 |
|
try { |
233 |
|
result = callable.call(); |
236 |
|
return; |
237 |
|
} |
238 |
|
set(result); |
239 |
+ |
} finally { |
240 |
+ |
runner = null; |
241 |
+ |
while (state == INTERRUPTING) |
242 |
+ |
Thread.yield(); // wait out pending cancellation interrupt |
243 |
|
} |
244 |
|
} |
245 |
|
|
257 |
|
!UNSAFE.compareAndSwapObject(this, runnerOffset, |
258 |
|
null, Thread.currentThread())) |
259 |
|
return false; |
260 |
+ |
|
261 |
|
try { |
262 |
< |
callable.call(); // don't set result |
263 |
< |
} catch (Throwable ex) { |
264 |
< |
setException(ex); |
265 |
< |
return false; |
266 |
< |
} |
271 |
< |
runner = null; |
272 |
< |
for (;;) { |
273 |
< |
int s = state; |
274 |
< |
if (s == UNDECIDED) |
275 |
< |
return true; |
276 |
< |
if (s != INTERRUPTING) |
262 |
> |
try { |
263 |
> |
callable.call(); // don't set result |
264 |
> |
return (state == UNDECIDED); |
265 |
> |
} catch (Throwable ex) { |
266 |
> |
setException(ex); |
267 |
|
return false; |
268 |
< |
Thread.yield(); // wait out pending cancellation interrupt |
268 |
> |
} |
269 |
> |
} finally { |
270 |
> |
runner = null; |
271 |
> |
while (state == INTERRUPTING) |
272 |
> |
Thread.yield(); // wait out pending cancellation interrupt |
273 |
|
} |
274 |
|
} |
275 |
|
|