126 |
|
* this is merely an optimization. |
127 |
|
* |
128 |
|
* When constructing a Node (before enqueuing it) we avoid paying |
129 |
< |
* for a volatile write to item by using lazySet instead of a |
130 |
< |
* normal write. This allows the cost of enqueue to be |
129 |
> |
* for a volatile write to item by using Unsafe.putObject instead |
130 |
> |
* of a normal write. This allows the cost of enqueue to be |
131 |
|
* "one-and-a-half" CASes. |
132 |
|
* |
133 |
|
* Both head and tail may or may not point to a Node with a |
139 |
|
*/ |
140 |
|
|
141 |
|
private static class Node<E> { |
142 |
< |
private volatile E item; |
143 |
< |
private volatile Node<E> next; |
142 |
> |
volatile E item; |
143 |
> |
volatile Node<E> next; |
144 |
|
|
145 |
|
/** |
146 |
|
* Constructs a new node. Uses relaxed write because item can |
150 |
|
UNSAFE.putObject(this, itemOffset, item); |
151 |
|
} |
152 |
|
|
153 |
– |
E getItem() { |
154 |
– |
return item; |
155 |
– |
} |
156 |
– |
|
153 |
|
boolean casItem(E cmp, E val) { |
154 |
|
return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); |
155 |
|
} |
156 |
|
|
161 |
– |
void setItem(E val) { |
162 |
– |
item = val; |
163 |
– |
} |
164 |
– |
|
157 |
|
void lazySetNext(Node<E> val) { |
158 |
|
UNSAFE.putOrderedObject(this, nextOffset, val); |
159 |
|
} |
311 |
|
Node<E> h = head; |
312 |
|
Node<E> p = h; |
313 |
|
for (int hops = 0; ; hops++) { |
314 |
< |
E item = p.getItem(); |
314 |
> |
E item = p.item; |
315 |
|
|
316 |
|
if (item != null && p.casItem(item, null)) { |
317 |
|
if (hops >= HOPS) { |
335 |
|
Node<E> p = h; |
336 |
|
E item; |
337 |
|
for (;;) { |
338 |
< |
item = p.getItem(); |
338 |
> |
item = p.item; |
339 |
|
if (item != null) |
340 |
|
break; |
341 |
|
Node<E> next = succ(p); |
361 |
|
Node<E> p = h; |
362 |
|
Node<E> result; |
363 |
|
for (;;) { |
364 |
< |
E item = p.getItem(); |
364 |
> |
E item = p.item; |
365 |
|
if (item != null) { |
366 |
|
result = p; |
367 |
|
break; |
404 |
|
*/ |
405 |
|
public int size() { |
406 |
|
int count = 0; |
407 |
< |
for (Node<E> p = first(); p != null; p = succ(p)) { |
408 |
< |
if (p.getItem() != null) { |
409 |
< |
// Collections.size() spec says to max out |
407 |
> |
for (Node<E> p = first(); p != null; p = succ(p)) |
408 |
> |
if (p.item != null) |
409 |
> |
// Collection.size() spec says to max out |
410 |
|
if (++count == Integer.MAX_VALUE) |
411 |
|
break; |
420 |
– |
} |
421 |
– |
} |
412 |
|
return count; |
413 |
|
} |
414 |
|
|
423 |
|
public boolean contains(Object o) { |
424 |
|
if (o == null) return false; |
425 |
|
for (Node<E> p = first(); p != null; p = succ(p)) { |
426 |
< |
E item = p.getItem(); |
426 |
> |
E item = p.item; |
427 |
|
if (item != null && |
428 |
|
o.equals(item)) |
429 |
|
return true; |
446 |
|
if (o == null) return false; |
447 |
|
Node<E> pred = null; |
448 |
|
for (Node<E> p = first(); p != null; p = succ(p)) { |
449 |
< |
E item = p.getItem(); |
449 |
> |
E item = p.item; |
450 |
|
if (item != null && |
451 |
|
o.equals(item) && |
452 |
|
p.casItem(item, null)) { |
534 |
|
// Use ArrayList to deal with resizing. |
535 |
|
ArrayList<E> al = new ArrayList<E>(); |
536 |
|
for (Node<E> p = first(); p != null; p = succ(p)) { |
537 |
< |
E item = p.getItem(); |
537 |
> |
E item = p.item; |
538 |
|
if (item != null) |
539 |
|
al.add(item); |
540 |
|
} |
583 |
|
int k = 0; |
584 |
|
Node<E> p; |
585 |
|
for (p = first(); p != null && k < a.length; p = succ(p)) { |
586 |
< |
E item = p.getItem(); |
586 |
> |
E item = p.item; |
587 |
|
if (item != null) |
588 |
|
a[k++] = (T)item; |
589 |
|
} |
596 |
|
// If won't fit, use ArrayList version |
597 |
|
ArrayList<E> al = new ArrayList<E>(); |
598 |
|
for (Node<E> q = first(); q != null; q = succ(q)) { |
599 |
< |
E item = q.getItem(); |
599 |
> |
E item = q.item; |
600 |
|
if (item != null) |
601 |
|
al.add(item); |
602 |
|
} |
666 |
|
nextItem = null; |
667 |
|
return x; |
668 |
|
} |
669 |
< |
E item = p.getItem(); |
669 |
> |
E item = p.item; |
670 |
|
if (item != null) { |
671 |
|
nextNode = p; |
672 |
|
nextItem = item; |
694 |
|
Node<E> l = lastRet; |
695 |
|
if (l == null) throw new IllegalStateException(); |
696 |
|
// rely on a future traversal to relink. |
697 |
< |
l.setItem(null); |
697 |
> |
l.item = null; |
698 |
|
lastRet = null; |
699 |
|
} |
700 |
|
} |
714 |
|
|
715 |
|
// Write out all elements in the proper order. |
716 |
|
for (Node<E> p = first(); p != null; p = succ(p)) { |
717 |
< |
Object item = p.getItem(); |
717 |
> |
Object item = p.item; |
718 |
|
if (item != null) |
719 |
|
s.writeObject(item); |
720 |
|
} |