147 |
|
* in a way that flows well in javadocs. |
148 |
|
*/ |
149 |
|
|
150 |
< |
/** |
151 |
< |
* Run control status bits packed into a single int to minimize |
152 |
< |
* footprint and to ensure atomicity (via CAS). Status is |
153 |
< |
* initially zero, and takes on nonnegative values until |
154 |
< |
* completed, upon which status holds value COMPLETED. CANCELLED, |
155 |
< |
* or EXCEPTIONAL. Tasks undergoing blocking waits by other |
156 |
< |
* threads have the SIGNAL bit set. Completion of a stolen task |
157 |
< |
* with SIGNAL set awakens any waiters via notifyAll. Even though |
158 |
< |
* suboptimal for some purposes, we use basic builtin wait/notify |
159 |
< |
* to take advantage of "monitor inflation" in JVMs that we would |
160 |
< |
* otherwise need to emulate to avoid adding further per-task |
161 |
< |
* bookkeeping overhead. We want these monitors to be "fat", |
162 |
< |
* i.e., not use biasing or thin-lock techniques, so use some odd |
163 |
< |
* coding idioms that tend to avoid them. |
150 |
> |
/* |
151 |
> |
* The status field holds run control status bits packed into a |
152 |
> |
* single int to minimize footprint and to ensure atomicity (via |
153 |
> |
* CAS). Status is initially zero, and takes on nonnegative |
154 |
> |
* values until completed, upon which status holds value |
155 |
> |
* COMPLETED. CANCELLED, or EXCEPTIONAL. Tasks undergoing blocking |
156 |
> |
* waits by other threads have the SIGNAL bit set. Completion of |
157 |
> |
* a stolen task with SIGNAL set awakens any waiters via |
158 |
> |
* notifyAll. Even though suboptimal for some purposes, we use |
159 |
> |
* basic builtin wait/notify to take advantage of "monitor |
160 |
> |
* inflation" in JVMs that we would otherwise need to emulate to |
161 |
> |
* avoid adding further per-task bookkeeping overhead. We want |
162 |
> |
* these monitors to be "fat", i.e., not use biasing or thin-lock |
163 |
> |
* techniques, so use some odd coding idioms that tend to avoid |
164 |
> |
* them. |
165 |
|
*/ |
166 |
+ |
|
167 |
+ |
/** Run status of this task */ |
168 |
|
volatile int status; // accessed directly by pool and workers |
169 |
|
|
170 |
|
private static final int NORMAL = -1; |
217 |
|
/** |
218 |
|
* Blocks a worker thread until completion. Called only by pool. |
219 |
|
*/ |
220 |
< |
final int internalAwaitDone() { |
221 |
< |
int s; |
220 |
> |
final void internalAwaitDone() { |
221 |
> |
int s; // the odd construction reduces lock bias effects |
222 |
|
while ((s = status) >= 0) { |
223 |
< |
synchronized(this) { |
224 |
< |
if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)) { |
225 |
< |
do { |
226 |
< |
try { |
224 |
< |
wait(); |
225 |
< |
} catch (InterruptedException ie) { |
226 |
< |
cancelIfTerminating(); |
227 |
< |
} |
228 |
< |
} while ((s = status) >= 0); |
229 |
< |
break; |
223 |
> |
try { |
224 |
> |
synchronized(this) { |
225 |
> |
if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL)) |
226 |
> |
wait(); |
227 |
|
} |
228 |
+ |
} catch (InterruptedException ie) { |
229 |
+ |
cancelIfTerminating(); |
230 |
|
} |
231 |
|
} |
233 |
– |
return s; |
232 |
|
} |
233 |
|
|
234 |
|
/** |
241 |
|
synchronized(this) { |
242 |
|
if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)){ |
243 |
|
boolean interrupted = false; |
244 |
< |
do { |
244 |
> |
while ((s = status) >= 0) { |
245 |
|
try { |
246 |
|
wait(); |
247 |
|
} catch (InterruptedException ie) { |
248 |
|
interrupted = true; |
249 |
|
} |
250 |
< |
} while ((s = status) >= 0); |
250 |
> |
} |
251 |
|
if (interrupted) |
252 |
|
Thread.currentThread().interrupt(); |
253 |
|
break; |
295 |
|
if (completed) |
296 |
|
return setCompletion(NORMAL); |
297 |
|
} |
298 |
< |
w.joinTask(this); |
301 |
< |
return status; |
298 |
> |
return w.joinTask(this); |
299 |
|
} |
300 |
|
return externalAwaitDone(); |
301 |
|
} |
314 |
|
} catch (Throwable rex) { |
315 |
|
return setExceptionalCompletion(rex); |
316 |
|
} |
317 |
< |
if (completed) |
321 |
< |
stat = setCompletion(NORMAL); |
322 |
< |
else |
323 |
< |
stat = doJoin(); |
317 |
> |
stat = completed ? setCompletion(NORMAL) : doJoin(); |
318 |
|
} |
319 |
|
return stat; |
320 |
|
} |
532 |
|
* @return {@code true} if this task is now cancelled |
533 |
|
*/ |
534 |
|
public boolean cancel(boolean mayInterruptIfRunning) { |
535 |
< |
setCompletion(CANCELLED); |
542 |
< |
return status == CANCELLED; |
535 |
> |
return setCompletion(CANCELLED) == CANCELLED; |
536 |
|
} |
537 |
|
|
538 |
|
/** |
549 |
|
/** |
550 |
|
* Cancels ignoring exceptions if worker is terminating |
551 |
|
*/ |
552 |
< |
private void cancelIfTerminating() { |
552 |
> |
final void cancelIfTerminating() { |
553 |
|
Thread t = Thread.currentThread(); |
554 |
|
if ((t instanceof ForkJoinWorkerThread) && |
555 |
|
((ForkJoinWorkerThread) t).isTerminating()) { |
1096 |
|
Object ex = s.readObject(); |
1097 |
|
if (ex != null) |
1098 |
|
setExceptionalCompletion((Throwable) ex); |
1106 |
– |
if (status < 0) |
1107 |
– |
synchronized (this) { notifyAll(); } |
1099 |
|
} |
1100 |
|
|
1101 |
|
// Unsafe mechanics |