19 |
|
import java.util.Spliterators; |
20 |
|
import java.util.concurrent.locks.LockSupport; |
21 |
|
import java.util.function.Consumer; |
22 |
+ |
import java.util.function.Predicate; |
23 |
|
|
24 |
|
/** |
25 |
|
* An unbounded {@link TransferQueue} based on linked nodes. |
967 |
|
return e; |
968 |
|
} |
969 |
|
|
970 |
+ |
// Default implementation of forEachRemaining is "good enough". |
971 |
+ |
|
972 |
|
public final void remove() { |
973 |
|
final Node lastRet = this.lastRet; |
974 |
|
if (lastRet == null) |
1014 |
|
@SuppressWarnings("unchecked") |
1015 |
|
public void forEachRemaining(Consumer<? super E> action) { |
1016 |
|
Objects.requireNonNull(action); |
1017 |
< |
Node p; |
1017 |
> |
final Node p; |
1018 |
|
if ((p = current()) != null) { |
1019 |
|
current = null; |
1020 |
|
exhausted = true; |
1021 |
< |
do { |
1019 |
< |
final Object item = p.item; |
1020 |
< |
if (p.isData) { |
1021 |
< |
if (item != null) |
1022 |
< |
action.accept((E) item); |
1023 |
< |
} |
1024 |
< |
else if (item == null) |
1025 |
< |
break; |
1026 |
< |
if (p == (p = p.next)) |
1027 |
< |
p = head; |
1028 |
< |
} while (p != null); |
1021 |
> |
forEachFrom(action, p); |
1022 |
|
} |
1023 |
|
} |
1024 |
|
|
1521 |
|
} |
1522 |
|
} |
1523 |
|
|
1524 |
+ |
/** |
1525 |
+ |
* @throws NullPointerException {@inheritDoc} |
1526 |
+ |
*/ |
1527 |
+ |
public boolean removeIf(Predicate<? super E> filter) { |
1528 |
+ |
Objects.requireNonNull(filter); |
1529 |
+ |
return bulkRemove(filter); |
1530 |
+ |
} |
1531 |
+ |
|
1532 |
+ |
/** |
1533 |
+ |
* @throws NullPointerException {@inheritDoc} |
1534 |
+ |
*/ |
1535 |
+ |
public boolean removeAll(Collection<?> c) { |
1536 |
+ |
Objects.requireNonNull(c); |
1537 |
+ |
return bulkRemove(e -> c.contains(e)); |
1538 |
+ |
} |
1539 |
+ |
|
1540 |
+ |
/** |
1541 |
+ |
* @throws NullPointerException {@inheritDoc} |
1542 |
+ |
*/ |
1543 |
+ |
public boolean retainAll(Collection<?> c) { |
1544 |
+ |
Objects.requireNonNull(c); |
1545 |
+ |
return bulkRemove(e -> !c.contains(e)); |
1546 |
+ |
} |
1547 |
+ |
|
1548 |
+ |
/** Implementation of bulk remove methods. */ |
1549 |
+ |
@SuppressWarnings("unchecked") |
1550 |
+ |
private boolean bulkRemove(Predicate<? super E> filter) { |
1551 |
+ |
boolean removed = false; |
1552 |
+ |
restartFromHead: for (;;) { |
1553 |
+ |
for (Node pred = null, p = head; p != null; ) { |
1554 |
+ |
final Object item = p.item; |
1555 |
+ |
if (p.isData) { |
1556 |
+ |
if (item != null |
1557 |
+ |
&& filter.test((E)item) |
1558 |
+ |
&& p.tryMatchData()) { |
1559 |
+ |
removed = true; |
1560 |
+ |
unsplice(pred, p); |
1561 |
+ |
p = p.next; |
1562 |
+ |
continue; |
1563 |
+ |
} |
1564 |
+ |
} |
1565 |
+ |
else if (item == null) |
1566 |
+ |
break; |
1567 |
+ |
if ((pred = p) == (p = p.next)) |
1568 |
+ |
continue restartFromHead; |
1569 |
+ |
} |
1570 |
+ |
return removed; |
1571 |
+ |
} |
1572 |
+ |
} |
1573 |
+ |
|
1574 |
+ |
/** |
1575 |
+ |
* Runs action on each element found during a traversal starting at p. |
1576 |
+ |
* If p is null, traversal starts at head. |
1577 |
+ |
*/ |
1578 |
+ |
@SuppressWarnings("unchecked") |
1579 |
+ |
void forEachFrom(Consumer<? super E> action, Node p) { |
1580 |
+ |
while (p != null) { |
1581 |
+ |
final Object item = p.item; |
1582 |
+ |
if (p.isData) { |
1583 |
+ |
if (item != null) |
1584 |
+ |
action.accept((E) item); |
1585 |
+ |
} |
1586 |
+ |
else if (item == null) |
1587 |
+ |
break; |
1588 |
+ |
if (p == (p = p.next)) |
1589 |
+ |
p = head; |
1590 |
+ |
} |
1591 |
+ |
} |
1592 |
+ |
|
1593 |
+ |
/** |
1594 |
+ |
* @throws NullPointerException {@inheritDoc} |
1595 |
+ |
*/ |
1596 |
+ |
public void forEach(Consumer<? super E> action) { |
1597 |
+ |
Objects.requireNonNull(action); |
1598 |
+ |
forEachFrom(action, head); |
1599 |
+ |
} |
1600 |
+ |
|
1601 |
|
// VarHandle mechanics |
1602 |
|
private static final VarHandle HEAD; |
1603 |
|
private static final VarHandle TAIL; |