18 |
|
import java.util.concurrent.atomic.AtomicReference; |
19 |
|
|
20 |
|
/** |
21 |
< |
* An unbounded {@linkplain TransferQueue} based on linked nodes. |
21 |
> |
* An unbounded {@link TransferQueue} based on linked nodes. |
22 |
|
* This queue orders elements FIFO (first-in-first-out) with respect |
23 |
|
* to any given producer. The <em>head</em> of the queue is that |
24 |
|
* element that has been on the queue the longest time for some |
219 |
|
Node<E> t = tail.get(); |
220 |
|
Node<E> h = head.get(); |
221 |
|
|
222 |
< |
if (t != null && (t == h || t.isData == isData)) { |
222 |
> |
if (t == h || t.isData == isData) { |
223 |
|
if (s == null) |
224 |
|
s = new Node<E>(e, isData); |
225 |
|
Node<E> last = t.next; |
231 |
|
tail.compareAndSet(t, s); |
232 |
|
return awaitFulfill(t, s, e, mode, nanos); |
233 |
|
} |
234 |
< |
} |
235 |
< |
|
236 |
< |
else if (h != null) { |
234 |
> |
} else { |
235 |
|
Node<E> first = h.next; |
236 |
|
if (t == tail.get() && first != null && |
237 |
|
advanceHead(h, first)) { |
259 |
|
Node<E> t = tail.get(); |
260 |
|
Node<E> h = head.get(); |
261 |
|
|
262 |
< |
if (t != null && (t == h || t.isData == isData)) { |
262 |
> |
if (t == h || t.isData == isData) { |
263 |
|
Node<E> last = t.next; |
264 |
|
if (t == tail.get()) { |
265 |
|
if (last != null) |
267 |
|
else |
268 |
|
return null; |
269 |
|
} |
270 |
< |
} |
273 |
< |
else if (h != null) { |
270 |
> |
} else { |
271 |
|
Node<E> first = h.next; |
272 |
|
if (t == tail.get() && |
273 |
|
first != null && |
291 |
|
* @param e the comparison value for checking match |
292 |
|
* @param mode mode |
293 |
|
* @param nanos timeout value |
294 |
< |
* @return matched item, or s if cancelled |
294 |
> |
* @return matched item, or null if cancelled |
295 |
|
*/ |
296 |
|
private E awaitFulfill(Node<E> pred, Node<E> s, E e, |
297 |
|
int mode, long nanos) { |
329 |
|
} |
330 |
|
if (spins < 0) { |
331 |
|
Node<E> h = head.get(); // only spin if at head |
332 |
< |
spins = ((h != null && h.next == s) ? |
333 |
< |
((mode == TIMEOUT) ? |
334 |
< |
maxTimedSpins : maxUntimedSpins) : 0); |
332 |
> |
spins = ((h.next != s) ? 0 : |
333 |
> |
(mode == TIMEOUT) ? maxTimedSpins : |
334 |
> |
maxUntimedSpins); |
335 |
|
} |
336 |
|
if (spins > 0) |
337 |
|
--spins; |
357 |
|
for (;;) { |
358 |
|
Node<E> h = head.get(); |
359 |
|
Node<E> first = h.next; |
360 |
< |
if (first != null && first.next == first) { // help advance |
360 |
> |
if (first != null && first.get() == first) { // help advance |
361 |
|
advanceHead(h, first); |
362 |
|
continue; |
363 |
|
} |
519 |
|
} |
520 |
|
|
521 |
|
/** |
522 |
< |
* Transfers the specified element immediately if there exists a |
523 |
< |
* consumer already waiting to receive it (in {@link #take} or |
524 |
< |
* timed {@link #poll(long,TimeUnit) poll}), otherwise |
525 |
< |
* returning {@code false} without enqueuing the element. |
522 |
> |
* Transfers the element to a waiting consumer immediately, if possible. |
523 |
> |
* |
524 |
> |
* <p>More precisely, transfers the specified element immediately |
525 |
> |
* if there exists a consumer already waiting to receive it (in |
526 |
> |
* {@link #take} or timed {@link #poll(long,TimeUnit) poll}), |
527 |
> |
* otherwise returning {@code false} without enqueuing the element. |
528 |
|
* |
529 |
|
* @throws NullPointerException if the specified element is null |
530 |
|
*/ |
534 |
|
} |
535 |
|
|
536 |
|
/** |
537 |
< |
* Inserts the specified element at the tail of this queue, |
538 |
< |
* waiting if necessary for the element to be received by a |
539 |
< |
* consumer invoking {@code take} or {@code poll}. |
537 |
> |
* Transfers the element to a consumer, waiting if necessary to do so. |
538 |
> |
* |
539 |
> |
* <p>More precisely, transfers the specified element immediately |
540 |
> |
* if there exists a consumer already waiting to receive it (in |
541 |
> |
* {@link #take} or timed {@link #poll(long,TimeUnit) poll}), |
542 |
> |
* else inserts the specified element at the tail of this queue |
543 |
> |
* and waits until the element is received by a consumer. |
544 |
|
* |
545 |
|
* @throws NullPointerException if the specified element is null |
546 |
|
*/ |
553 |
|
} |
554 |
|
|
555 |
|
/** |
556 |
< |
* Inserts the specified element at the tail of this queue, |
557 |
< |
* waiting up to the specified wait time if necessary for the |
558 |
< |
* element to be received by a consumer invoking {@code take} or |
559 |
< |
* {@code poll}. |
556 |
> |
* Transfers the element to a consumer if it is possible to do so |
557 |
> |
* before the timeout elapses. |
558 |
> |
* |
559 |
> |
* <p>More precisely, transfers the specified element immediately |
560 |
> |
* if there exists a consumer already waiting to receive it (in |
561 |
> |
* {@link #take} or timed {@link #poll(long,TimeUnit) poll}), |
562 |
> |
* else inserts the specified element at the tail of this queue |
563 |
> |
* and waits until the element is received by a consumer, |
564 |
> |
* returning {@code false} if the specified wait time elapses |
565 |
> |
* before the element can be transferred. |
566 |
|
* |
567 |
|
* @throws NullPointerException if the specified element is null |
568 |
|
*/ |
640 |
|
for (;;) { |
641 |
|
Node<E> t = tail.get(); |
642 |
|
Node<E> h = head.get(); |
643 |
< |
if (h != null && t != null) { |
644 |
< |
Node<E> last = t.next; |
645 |
< |
Node<E> first = h.next; |
646 |
< |
if (t == tail.get()) { |
647 |
< |
if (last != null) |
648 |
< |
tail.compareAndSet(t, last); |
649 |
< |
else if (first != null) { |
650 |
< |
Object x = first.get(); |
651 |
< |
if (x == first) |
643 |
< |
advanceHead(h, first); |
644 |
< |
else |
645 |
< |
return h; |
646 |
< |
} |
643 |
> |
Node<E> last = t.next; |
644 |
> |
Node<E> first = h.next; |
645 |
> |
if (t == tail.get()) { |
646 |
> |
if (last != null) |
647 |
> |
tail.compareAndSet(t, last); |
648 |
> |
else if (first != null) { |
649 |
> |
Object x = first.get(); |
650 |
> |
if (x == first) |
651 |
> |
advanceHead(h, first); |
652 |
|
else |
653 |
|
return h; |
654 |
|
} |
655 |
+ |
else |
656 |
+ |
return h; |
657 |
|
} |
658 |
|
reclean(); |
659 |
|
} |
757 |
|
} |
758 |
|
} |
759 |
|
|
760 |
+ |
/** |
761 |
+ |
* Returns {@code true} if this queue contains no elements. |
762 |
+ |
* |
763 |
+ |
* @return {@code true} if this queue contains no elements |
764 |
+ |
*/ |
765 |
|
public boolean isEmpty() { |
766 |
|
for (;;) { |
767 |
|
Node<E> h = traversalHead(); |
843 |
|
} |
844 |
|
} |
845 |
|
|
846 |
+ |
/** |
847 |
+ |
* Removes a single instance of the specified element from this queue, |
848 |
+ |
* if it is present. More formally, removes an element {@code e} such |
849 |
+ |
* that {@code o.equals(e)}, if this queue contains one or more such |
850 |
+ |
* elements. |
851 |
+ |
* Returns {@code true} if this queue contained the specified element |
852 |
+ |
* (or equivalently, if this queue changed as a result of the call). |
853 |
+ |
* |
854 |
+ |
* @param o element to be removed from this queue, if present |
855 |
+ |
* @return {@code true} if this queue changed as a result of the call |
856 |
+ |
*/ |
857 |
|
public boolean remove(Object o) { |
858 |
|
if (o == null) |
859 |
|
return false; |