15 |
|
import java.util.NoSuchElementException; |
16 |
|
import java.util.Queue; |
17 |
|
import java.util.concurrent.locks.LockSupport; |
18 |
+ |
|
19 |
|
/** |
20 |
|
* An unbounded {@link TransferQueue} based on linked nodes. |
21 |
|
* This queue orders elements FIFO (first-in-first-out) with respect |
322 |
|
* situations in which we cannot guarantee to make node s |
323 |
|
* unreachable in this way: (1) If s is the trailing node of list |
324 |
|
* (i.e., with null next), then it is pinned as the target node |
325 |
< |
* for appends, so can only be removed later when other nodes are |
325 |
> |
* for appends, so can only be removed later after other nodes are |
326 |
|
* appended. (2) We cannot necessarily unlink s given a |
327 |
|
* predecessor node that is matched (including the case of being |
328 |
|
* cancelled): the predecessor may already be unspliced, in which |
344 |
|
* When these cases arise, rather than always retraversing the |
345 |
|
* entire list to find an actual predecessor to unlink (which |
346 |
|
* won't help for case (1) anyway), we record a conservative |
347 |
< |
* estimate of possible unsplice failures (in "sweepVotes"). We |
348 |
< |
* trigger a full sweep when the estimate exceeds a threshold |
349 |
< |
* indicating the maximum number of estimated removal failures to |
350 |
< |
* tolerate before sweeping through, unlinking cancelled nodes |
351 |
< |
* that were not unlinked upon initial removal. We perform sweeps |
352 |
< |
* by the thread hitting threshold (rather than background threads |
353 |
< |
* or by spreading work to other threads) because in the main |
354 |
< |
* contexts in which removal occurs, the caller is already |
355 |
< |
* timed-out, cancelled, or performing a potentially O(n) |
356 |
< |
* operation (i.e., remove(x)), none of which are time-critical |
357 |
< |
* enough to warrant the overhead that alternatives would impose |
358 |
< |
* on other threads. |
347 |
> |
* estimate of possible unsplice failures (in "sweepVotes"). |
348 |
> |
* We trigger a full sweep when the estimate exceeds a threshold |
349 |
> |
* ("SWEEP_THRESHOLD") indicating the maximum number of estimated |
350 |
> |
* removal failures to tolerate before sweeping through, unlinking |
351 |
> |
* cancelled nodes that were not unlinked upon initial removal. |
352 |
> |
* We perform sweeps by the thread hitting threshold (rather than |
353 |
> |
* background threads or by spreading work to other threads) |
354 |
> |
* because in the main contexts in which removal occurs, the |
355 |
> |
* caller is already timed-out, cancelled, or performing a |
356 |
> |
* potentially O(n) operation (e.g. remove(x)), none of which are |
357 |
> |
* time-critical enough to warrant the overhead that alternatives |
358 |
> |
* would impose on other threads. |
359 |
|
* |
360 |
|
* Because the sweepVotes estimate is conservative, and because |
361 |
|
* nodes become unlinked "naturally" as they fall off the head of |
423 |
|
} |
424 |
|
|
425 |
|
final boolean casItem(Object cmp, Object val) { |
426 |
< |
assert cmp == null || cmp.getClass() != Node.class; |
426 |
> |
// assert cmp == null || cmp.getClass() != Node.class; |
427 |
|
return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); |
428 |
|
} |
429 |
|
|
430 |
|
/** |
431 |
< |
* Creates a new node. Uses relaxed write because item can only |
432 |
< |
* be seen if followed by CAS. |
431 |
> |
* Constructs a new node. Uses relaxed write because item can |
432 |
> |
* only be seen after publication via casNext. |
433 |
|
*/ |
434 |
|
Node(Object item, boolean isData) { |
435 |
|
UNSAFE.putObject(this, itemOffset, item); // relaxed write |
447 |
|
/** |
448 |
|
* Sets item to self and waiter to null, to avoid garbage |
449 |
|
* retention after matching or cancelling. Uses relaxed writes |
450 |
< |
* bacause order is already constrained in the only calling |
450 |
> |
* because order is already constrained in the only calling |
451 |
|
* contexts: item is forgotten only after volatile/atomic |
452 |
|
* mechanics that extract items. Similarly, clearing waiter |
453 |
|
* follows either CAS or return from park (if ever parked; |
489 |
|
* Tries to artificially match a data node -- used by remove. |
490 |
|
*/ |
491 |
|
final boolean tryMatchData() { |
492 |
< |
assert isData; |
492 |
> |
// assert isData; |
493 |
|
Object x = item; |
494 |
|
if (x != null && x != this && casItem(x, null)) { |
495 |
|
LockSupport.unpark(waiter); |
542 |
|
|
543 |
|
@SuppressWarnings("unchecked") |
544 |
|
static <E> E cast(Object item) { |
545 |
< |
assert item == null || item.getClass() != Node.class; |
545 |
> |
// assert item == null || item.getClass() != Node.class; |
546 |
|
return (E) item; |
547 |
|
} |
548 |
|
|
657 |
|
for (;;) { |
658 |
|
Object item = s.item; |
659 |
|
if (item != e) { // matched |
660 |
< |
assert item != s; |
660 |
> |
// assert item != s; |
661 |
|
s.forgetContents(); // avoid garbage |
662 |
|
return this.<E>cast(item); |
663 |
|
} |