ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/LinkedBlockingDeque.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/LinkedBlockingDeque.java (file contents):
Revision 1.65 by jsr166, Fri Nov 18 22:45:17 2016 UTC vs.
Revision 1.66 by jsr166, Sun Dec 11 19:59:51 2016 UTC

# Line 1033 | Line 1033 | public class LinkedBlockingDeque<E>
1033          abstract Node<E> firstNode();
1034          abstract Node<E> nextNode(Node<E> n);
1035  
1036 +        private Node<E> succ(Node<E> p) {
1037 +            return (p == (p = nextNode(p))) ? firstNode() : p;
1038 +        }
1039 +
1040          AbstractItr() {
1041              // set to initial position
1042              final ReentrantLock lock = LinkedBlockingDeque.this.lock;
1043              lock.lock();
1044              try {
1045 <                next = firstNode();
1046 <                nextItem = (next == null) ? null : next.item;
1045 >                if ((next = firstNode()) != null)
1046 >                    nextItem = next.item;
1047              } finally {
1048                  // checkInvariants();
1049                  lock.unlock();
# Line 1047 | Line 1051 | public class LinkedBlockingDeque<E>
1051          }
1052  
1053          /**
1050         * Returns the successor node of the given non-null, but
1051         * possibly previously deleted, node.
1052         */
1053        private Node<E> succ(Node<E> n) {
1054            // Chains of deleted nodes ending in null or self-links
1055            // are possible if multiple interior nodes are removed.
1056            for (;;) {
1057                Node<E> s = nextNode(n);
1058                if (s == null)
1059                    return null;
1060                else if (s.item != null)
1061                    return s;
1062                else if (s == n)
1063                    return firstNode();
1064                else
1065                    n = s;
1066            }
1067        }
1068
1069        /**
1054           * Advances next.
1055           */
1056          void advance() {
1057 +            // assert next != null;
1058              final ReentrantLock lock = LinkedBlockingDeque.this.lock;
1059              lock.lock();
1060              try {
1061 <                // assert next != null;
1062 <                next = succ(next);
1063 <                nextItem = (next == null) ? null : next.item;
1061 >                // Chains of deleted nodes ending in null or self-links
1062 >                // are possible if multiple interior nodes are removed.
1063 >                for (next = nextNode(next);; next = succ(next)) {
1064 >                    if (next == null) {
1065 >                        nextItem = null;
1066 >                        break;
1067 >                    } else if ((nextItem = next.item) != null)
1068 >                        break;
1069 >                }
1070              } finally {
1071                  // checkInvariants();
1072                  lock.unlock();
# Line 1124 | Line 1115 | public class LinkedBlockingDeque<E>
1115          Node<E> nextNode(Node<E> n) { return n.prev; }
1116      }
1117  
1118 <    /** A customized variant of Spliterators.IteratorSpliterator */
1118 >    /**
1119 >     * A customized variant of Spliterators.IteratorSpliterator.
1120 >     * Keep this class in sync with (very similar) LBQSpliterator.
1121 >     */
1122      private final class LBDSpliterator implements Spliterator<E> {
1123          static final int MAX_BATCH = 1 << 25;  // max batch array size;
1124          Node<E> current;    // current node; null until initialized
1125          int batch;          // batch size for splits
1126          boolean exhausted;  // true when no more nodes
1127 <        long est;           // size estimate
1127 >        long est = size();  // size estimate
1128  
1129 <        LBDSpliterator() { est = size(); }
1129 >        LBDSpliterator() {}
1130 >
1131 >        private Node<E> succ(Node<E> p) {
1132 >            return (p == (p = p.next)) ? first : p;
1133 >        }
1134  
1135          public long estimateSize() { return est; }
1136  
# Line 1141 | Line 1139 | public class LinkedBlockingDeque<E>
1139              int b = batch;
1140              int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
1141              if (!exhausted &&
1142 <                (((h = current) != null && h != h.next)
1145 <                 || (h = first) != null)
1142 >                ((h = current) != null || (h = first) != null)
1143                  && h.next != null) {
1144                  Object[] a = new Object[n];
1145                  final ReentrantLock lock = LinkedBlockingDeque.this.lock;
# Line 1150 | Line 1147 | public class LinkedBlockingDeque<E>
1147                  Node<E> p = current;
1148                  lock.lock();
1149                  try {
1150 <                    if (((p != null && p != p.next) || (p = first) != null)
1151 <                        && p.item != null)
1152 <                        for (; p != null && i < n; p = p.next)
1153 <                            a[i++] = p.item;
1150 >                    if (p != null || (p = first) != null)
1151 >                        for (; p != null && i < n; p = succ(p))
1152 >                            if ((a[i] = p.item) != null)
1153 >                                i++;
1154                  } finally {
1155                      // checkInvariants();
1156                      lock.unlock();
# Line 1177 | Line 1174 | public class LinkedBlockingDeque<E>
1174  
1175          public void forEachRemaining(Consumer<? super E> action) {
1176              if (action == null) throw new NullPointerException();
1177 <            if (exhausted)
1178 <                return;
1179 <            exhausted = true;
1180 <            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
1181 <            Node<E> p = current;
1182 <            current = null;
1183 <            do {
1177 >            if (!exhausted) {
1178 >                exhausted = true;
1179 >                final ReentrantLock lock = LinkedBlockingDeque.this.lock;
1180 >                Node<E> p = current;
1181 >                current = null;
1182 >                do {
1183 >                    E e = null;
1184 >                    lock.lock();
1185 >                    try {
1186 >                        if (p != null || (p = first) != null)
1187 >                            do {
1188 >                                e = p.item;
1189 >                                p = succ(p);
1190 >                            } while (e == null && p != null);
1191 >                    } finally {
1192 >                        // checkInvariants();
1193 >                        lock.unlock();
1194 >                    }
1195 >                    if (e != null)
1196 >                        action.accept(e);
1197 >                } while (p != null);
1198 >            }
1199 >        }
1200 >
1201 >        public boolean tryAdvance(Consumer<? super E> action) {
1202 >            if (action == null) throw new NullPointerException();
1203 >            if (!exhausted) {
1204 >                final ReentrantLock lock = LinkedBlockingDeque.this.lock;
1205 >                Node<E> p = current;
1206                  E e = null;
1207                  lock.lock();
1208                  try {
1209 <                    if ((p != null && p != p.next) || (p = first) != null) {
1210 <                        e = p.item;
1211 <                        p = p.next;
1212 <                    }
1209 >                    if (p != null || (p = first) != null)
1210 >                        do {
1211 >                            e = p.item;
1212 >                            p = succ(p);
1213 >                        } while (e == null && p != null);
1214                  } finally {
1215                      // checkInvariants();
1216                      lock.unlock();
1217                  }
1218 <                if (e != null)
1218 >                exhausted = ((current = p) == null);
1219 >                if (e != null) {
1220                      action.accept(e);
1221 <            } while (p != null);
1201 <        }
1202 <
1203 <        public boolean tryAdvance(Consumer<? super E> action) {
1204 <            if (action == null) throw new NullPointerException();
1205 <            if (exhausted)
1206 <                return false;
1207 <            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
1208 <            Node<E> p = current;
1209 <            E e = null;
1210 <            lock.lock();
1211 <            try {
1212 <                if ((p != null && p != p.next) || (p = first) != null) {
1213 <                    e = p.item;
1214 <                    p = p.next;
1221 >                    return true;
1222                  }
1216            } finally {
1217                // checkInvariants();
1218                lock.unlock();
1223              }
1224 <            exhausted = ((current = p) == null);
1221 <            if (e == null)
1222 <                return false;
1223 <            action.accept(e);
1224 <            return true;
1224 >            return false;
1225          }
1226  
1227          public int characteristics() {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines