267 |
|
* side of possibly making the queue appear nonempty when a push, |
268 |
|
* pop, or poll have not fully committed, or making it appear |
269 |
|
* empty when an update of top or base has not yet been seen. |
270 |
< |
* Method isEmpty() provides a more accurate test by checking both |
271 |
< |
* indices and slots. Similarly, the check in push for the queue |
272 |
< |
* array being full may trigger when not completely full, causing |
273 |
< |
* a resize earlier than required. |
270 |
> |
* Similarly, the check in push for the queue array being full may |
271 |
> |
* trigger when not completely full, causing a resize earlier than |
272 |
> |
* required. |
273 |
|
* |
274 |
|
* Mainly because of these potential inconsistencies among slots |
275 |
|
* vs indices, the poll operation, considered individually, is not |
1587 |
|
private int awaitWork(WorkQueue w) { |
1588 |
|
if (w == null) |
1589 |
|
return -1; // already terminated |
1590 |
< |
int phase, ac, md, rc; // advance phase |
1591 |
< |
w.phase = (phase = w.phase + SS_SEQ) | UNSIGNALLED; |
1590 |
> |
int phase = (w.phase + SS_SEQ) & ~UNSIGNALLED; |
1591 |
> |
w.phase = phase | UNSIGNALLED; // advance phase |
1592 |
|
long prevCtl = ctl, c; // enqueue |
1593 |
|
do { |
1594 |
|
w.stackPred = (int)prevCtl; |
1596 |
|
} while (prevCtl != (prevCtl = compareAndExchangeCtl(prevCtl, c))); |
1597 |
|
|
1598 |
|
LockSupport.setCurrentBlocker(this); // prepare to block (exit also OK) |
1599 |
< |
long deadline = 0L; // use timed wait if nonzero |
1600 |
< |
if ((rc = (ac = (int)(c >> RC_SHIFT)) + ((md = mode) & SMASK)) <= 0) { |
1599 |
> |
long deadline = 0L; // nonzero if possibly quiescent |
1600 |
> |
int ac, md; |
1601 |
> |
if ((ac = (int)(c >> RC_SHIFT)) + ((md = mode) & SMASK) <= 0) { |
1602 |
|
if ((deadline = System.currentTimeMillis() + keepAlive) == 0L) |
1603 |
|
deadline = 1L; // avoid zero |
1604 |
|
WorkQueue[] qs = queues; // check for racing submission |
1608 |
|
if ((q = qs[i]) != null && (a = q.array) != null && |
1609 |
|
(cap = a.length) > 0 && a[(cap - 1) & q.base] != null) { |
1610 |
|
if (ctl == c && compareAndSetCtl(c, prevCtl)) |
1611 |
< |
w.phase &= ~UNSIGNALLED; // self-signal |
1611 |
> |
w.phase = phase; // self-signal |
1612 |
|
break; |
1613 |
|
} |
1614 |
|
} |
1622 |
|
} |
1623 |
|
else if ((int)(ctl >> RC_SHIFT) > ac) |
1624 |
|
Thread.onSpinWait(); // signal in progress |
1625 |
< |
else if (rc <= 0 && (md & SHUTDOWN) != 0 && |
1625 |
> |
else if ((md & SHUTDOWN) != 0 && deadline != 0L && |
1626 |
|
tryTerminate(false, false)) |
1627 |
|
return -1; // trigger quiescent termination |
1628 |
|
else { |
1629 |
< |
if (rc <= 0) |
1629 |
> |
if (deadline != 0L) |
1630 |
|
LockSupport.parkUntil(deadline); |
1631 |
|
else |
1632 |
|
LockSupport.park(); |
1633 |
|
if ((int)(ctl >> RC_SHIFT) <= ac && |
1634 |
< |
!Thread.interrupted() && rc <= 0 && |
1634 |
> |
!Thread.interrupted() && deadline != 0L && |
1635 |
|
deadline - System.currentTimeMillis() <= TIMEOUT_SLOP && |
1636 |
|
compareAndSetCtl(c, ((UC_MASK & (c - TC_UNIT)) | |
1637 |
|
(w.stackPred & SP_MASK)))) { |