229 * to check whether we have reached a TERMINATOR node; if so, |
229 * to check whether we have reached a TERMINATOR node; if so, |
230 * restart traversal from tail. |
230 * restart traversal from tail. |
231 * |
231 * |
232 * The implementation is completely directionally symmetrical, |
232 * The implementation is completely directionally symmetrical, |
233 * except that most public methods that iterate through the list |
233 * except that most public methods that iterate through the list |
234 * follow next pointers ("forward" direction). |
234 * follow next pointers, in the "forward" direction. |
235 * |
235 * |
236 * We believe (without full proof) that all single-element deque |
236 * We believe (without full proof) that all single-element Deque |
237 * operations (e.g., addFirst, peekLast, pollLast) are linearizable |
237 * operations that operate directly at the two ends of the Deque |
238 * (see Herlihy and Shavit's book). However, some combinations of |
238 * (e.g., addFirst, peekLast, pollLast) are linearizable (see |
|
239 * Herlihy and Shavit's book). However, some combinations of |
239 * operations are known not to be linearizable. In particular, |
240 * operations are known not to be linearizable. In particular, |
240 * when an addFirst(A) is racing with pollFirst() removing B, it is |
241 * when an addFirst(A) is racing with pollFirst() removing B, it |
241 * possible for an observer iterating over the elements to observe |
242 * is possible for an observer iterating over the elements to |
242 * A B C and subsequently observe A C, even though no interior |
243 * observe first [A B C] and then [A C], even though no interior |
243 * removes are ever performed. Nevertheless, iterators behave |
244 * removes are ever performed. Nevertheless, iterators behave |
244 * reasonably, providing the "weakly consistent" guarantees. |
245 * reasonably, providing the "weakly consistent" guarantees. |
245 * |
246 * |
246 * Empirically, microbenchmarks suggest that this class adds about |
247 * Empirically, microbenchmarks suggest that this class adds about |
247 * 40% overhead relative to ConcurrentLinkedQueue, which feels as |
248 * 40% overhead relative to ConcurrentLinkedQueue, which feels as |
863 linkLast(e); |
864 linkLast(e); |
864 return true; |
865 return true; |
865 } |
866 } |
866 |
867 |
867 public E peekFirst() { |
868 public E peekFirst() { |
868 for (Node<E> p = first(); p != null; p = succ(p)) { |
869 restart: for (;;) { |
869 final E item; |
870 for (Node<E> first = first(), p = first;;) { |
870 if ((item = p.item) != null) |
871 final E item; |
871 return item; |
872 if ((item = p.item) != null) { |
872 } |
873 // recheck for linearizability |
873 return null; |
874 if (first.prev != null) continue restart; |
|
875 return item; |
|
876 } |
|
877 if ((p = succ(p)) == null) |
|
878 return null; |
|
879 } |
|
880 } |
874 } |
881 } |
875 |
882 |
876 public E peekLast() { |
883 public E peekLast() { |
877 for (Node<E> p = last(); p != null; p = pred(p)) { |
884 restart: for (;;) { |
878 final E item; |
885 for (Node<E> last = last(), p = last;;) { |
879 if ((item = p.item) != null) |
886 final E item; |
880 return item; |
887 if ((item = p.item) != null) { |
881 } |
888 // recheck for linearizability |
882 return null; |
889 if (last.next != null) continue restart; |
|
890 return item; |
|
891 } |
|
892 if ((p = pred(p)) == null) |
|
893 return null; |
|
894 } |
|
895 } |
883 } |
896 } |
884 |
897 |
885 /** |
898 /** |
886 * @throws NoSuchElementException {@inheritDoc} |
899 * @throws NoSuchElementException {@inheritDoc} |
887 */ |
900 */ |
895 public E getLast() { |
908 public E getLast() { |
896 return screenNullResult(peekLast()); |
909 return screenNullResult(peekLast()); |
897 } |
910 } |
898 |
911 |
899 public E pollFirst() { |
912 public E pollFirst() { |
900 for (Node<E> p = first(); p != null; p = succ(p)) { |
913 restart: for (;;) { |
901 final E item; |
914 for (Node<E> first = first(), p = first;;) { |
902 if ((item = p.item) != null |
915 final E item; |
903 && ITEM.compareAndSet(p, item, null)) { |
916 if ((item = p.item) != null) { |
904 unlink(p); |
917 // recheck for linearizability |
905 return item; |
918 if (first.prev != null) continue restart; |
906 } |
919 if (ITEM.compareAndSet(p, item, null)) { |
907 } |
920 unlink(p); |
908 return null; |
921 return item; |
|
922 } |
|
923 } |
|
924 if ((p = succ(p)) == null) |
|
925 return null; |
|
926 } |
|
927 } |
909 } |
928 } |
910 |
929 |
911 public E pollLast() { |
930 public E pollLast() { |
912 for (Node<E> p = last(); p != null; p = pred(p)) { |
931 restart: for (;;) { |
913 final E item; |
932 for (Node<E> last = last(), p = last;;) { |
914 if ((item = p.item) != null |
933 final E item; |
915 && ITEM.compareAndSet(p, item, null)) { |
934 if ((item = p.item) != null) { |
916 unlink(p); |
935 // recheck for linearizability |
917 return item; |
936 if (last.next != null) continue restart; |
918 } |
937 if (ITEM.compareAndSet(p, item, null)) { |
919 } |
938 unlink(p); |
920 return null; |
939 return item; |
|
940 } |
|
941 } |
|
942 if ((p = pred(p)) == null) |
|
943 return null; |
|
944 } |
|
945 } |
921 } |
946 } |
922 |
947 |
923 /** |
948 /** |
924 * @throws NoSuchElementException {@inheritDoc} |
949 * @throws NoSuchElementException {@inheritDoc} |
925 */ |
950 */ |
1077 * useful in concurrent applications. |
1102 * useful in concurrent applications. |
1078 * |
1103 * |
1079 * @return the number of elements in this deque |
1104 * @return the number of elements in this deque |
1080 */ |
1105 */ |
1081 public int size() { |
1106 public int size() { |
1082 restartFromHead: for (;;) { |
1107 restart: for (;;) { |
1083 int count = 0; |
1108 int count = 0; |
1084 for (Node<E> p = first(); p != null;) { |
1109 for (Node<E> p = first(); p != null;) { |
1085 if (p.item != null) |
1110 if (p.item != null) |
1086 if (++count == Integer.MAX_VALUE) |
1111 if (++count == Integer.MAX_VALUE) |
1087 break; // @see Collection.size() |
1112 break; // @see Collection.size() |
1088 if (p == (p = p.next)) |
1113 if (p == (p = p.next)) |
1089 continue restartFromHead; |
1114 continue restart; |
1090 } |
1115 } |
1091 return count; |
1116 return count; |
1092 } |
1117 } |
1093 } |
1118 } |
1094 |
1119 |
1220 else if (size == x.length) |
1245 else if (size == x.length) |
1221 x = Arrays.copyOf(x, 2 * (size + 4)); |
1246 x = Arrays.copyOf(x, 2 * (size + 4)); |
1222 x[size++] = item; |
1247 x[size++] = item; |
1223 } |
1248 } |
1224 if (p == (p = p.next)) |
1249 if (p == (p = p.next)) |
1225 continue restartFromHead; |
1250 continue restart; |
1226 } |
1251 } |
1227 if (x == null) |
1252 if (x == null) |
1228 return new Object[0]; |
1253 return new Object[0]; |
1229 else if (a != null && size <= a.length) { |
1254 else if (a != null && size <= a.length) { |
1230 if (a != x) |
1255 if (a != x) |