Print this page


Split Close
Expand all
Collapse all
          --- old/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java
          +++ new/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java
↓ open down ↓ 118 lines elided ↑ open up ↑
 119  119          Node<E> prev;
 120  120  
 121  121          /**
 122  122           * One of:
 123  123           * - the real successor Node
 124  124           * - this Node, meaning the successor is head
 125  125           * - null, meaning there is no successor
 126  126           */
 127  127          Node<E> next;
 128  128  
 129      -        Node(E x, Node<E> p, Node<E> n) {
      129 +        Node(E x) {
 130  130              item = x;
 131      -            prev = p;
 132      -            next = n;
 133  131          }
 134  132      }
 135  133  
 136  134      /**
 137  135       * Pointer to first node.
 138  136       * Invariant: (first == null && last == null) ||
 139  137       *            (first.prev == null && first.item != null)
 140  138       */
 141  139      transient Node<E> first;
 142  140  
↓ open down ↓ 49 lines elided ↑ open up ↑
 192  190       *         of its elements are null
 193  191       */
 194  192      public LinkedBlockingDeque(Collection<? extends E> c) {
 195  193          this(Integer.MAX_VALUE);
 196  194          final ReentrantLock lock = this.lock;
 197  195          lock.lock(); // Never contended, but necessary for visibility
 198  196          try {
 199  197              for (E e : c) {
 200  198                  if (e == null)
 201  199                      throw new NullPointerException();
 202      -                if (!linkLast(e))
      200 +                if (!linkLast(new Node<E>(e)))
 203  201                      throw new IllegalStateException("Deque full");
 204  202              }
 205  203          } finally {
 206  204              lock.unlock();
 207  205          }
 208  206      }
 209  207  
 210  208  
 211  209      // Basic linking and unlinking operations, called only while holding lock
 212  210  
 213  211      /**
 214      -     * Links e as first element, or returns false if full.
      212 +     * Links node as first element, or returns false if full.
 215  213       */
 216      -    private boolean linkFirst(E e) {
      214 +    private boolean linkFirst(Node<E> node) {
 217  215          // assert lock.isHeldByCurrentThread();
 218  216          if (count >= capacity)
 219  217              return false;
 220  218          Node<E> f = first;
 221      -        Node<E> x = new Node<E>(e, null, f);
 222      -        first = x;
      219 +        node.next = f;
      220 +        first = node;
 223  221          if (last == null)
 224      -            last = x;
      222 +            last = node;
 225  223          else
 226      -            f.prev = x;
      224 +            f.prev = node;
 227  225          ++count;
 228  226          notEmpty.signal();
 229  227          return true;
 230  228      }
 231  229  
 232  230      /**
 233      -     * Links e as last element, or returns false if full.
      231 +     * Links node as last element, or returns false if full.
 234  232       */
 235      -    private boolean linkLast(E e) {
      233 +    private boolean linkLast(Node<E> node) {
 236  234          // assert lock.isHeldByCurrentThread();
 237  235          if (count >= capacity)
 238  236              return false;
 239  237          Node<E> l = last;
 240      -        Node<E> x = new Node<E>(e, l, null);
 241      -        last = x;
      238 +        node.prev = l;
      239 +        last = node;
 242  240          if (first == null)
 243      -            first = x;
      241 +            first = node;
 244  242          else
 245      -            l.next = x;
      243 +            l.next = node;
 246  244          ++count;
 247  245          notEmpty.signal();
 248  246          return true;
 249  247      }
 250  248  
 251  249      /**
 252  250       * Removes and returns first element, or null if empty.
 253  251       */
 254  252      private E unlinkFirst() {
 255  253          // assert lock.isHeldByCurrentThread();
↓ open down ↓ 76 lines elided ↑ open up ↑
 332  330      public void addLast(E e) {
 333  331          if (!offerLast(e))
 334  332              throw new IllegalStateException("Deque full");
 335  333      }
 336  334  
 337  335      /**
 338  336       * @throws NullPointerException {@inheritDoc}
 339  337       */
 340  338      public boolean offerFirst(E e) {
 341  339          if (e == null) throw new NullPointerException();
      340 +        Node<E> node = new Node<E>(e);
 342  341          final ReentrantLock lock = this.lock;
 343  342          lock.lock();
 344  343          try {
 345      -            return linkFirst(e);
      344 +            return linkFirst(node);
 346  345          } finally {
 347  346              lock.unlock();
 348  347          }
 349  348      }
 350  349  
 351  350      /**
 352  351       * @throws NullPointerException {@inheritDoc}
 353  352       */
 354  353      public boolean offerLast(E e) {
 355  354          if (e == null) throw new NullPointerException();
      355 +        Node<E> node = new Node<E>(e);
 356  356          final ReentrantLock lock = this.lock;
 357  357          lock.lock();
 358  358          try {
 359      -            return linkLast(e);
      359 +            return linkLast(node);
 360  360          } finally {
 361  361              lock.unlock();
 362  362          }
 363  363      }
 364  364  
 365  365      /**
 366  366       * @throws NullPointerException {@inheritDoc}
 367  367       * @throws InterruptedException {@inheritDoc}
 368  368       */
 369  369      public void putFirst(E e) throws InterruptedException {
 370  370          if (e == null) throw new NullPointerException();
      371 +        Node<E> node = new Node<E>(e);
 371  372          final ReentrantLock lock = this.lock;
 372  373          lock.lock();
 373  374          try {
 374      -            while (!linkFirst(e))
      375 +            while (!linkFirst(node))
 375  376                  notFull.await();
 376  377          } finally {
 377  378              lock.unlock();
 378  379          }
 379  380      }
 380  381  
 381  382      /**
 382  383       * @throws NullPointerException {@inheritDoc}
 383  384       * @throws InterruptedException {@inheritDoc}
 384  385       */
 385  386      public void putLast(E e) throws InterruptedException {
 386  387          if (e == null) throw new NullPointerException();
      388 +        Node<E> node = new Node<E>(e);
 387  389          final ReentrantLock lock = this.lock;
 388  390          lock.lock();
 389  391          try {
 390      -            while (!linkLast(e))
      392 +            while (!linkLast(node))
 391  393                  notFull.await();
 392  394          } finally {
 393  395              lock.unlock();
 394  396          }
 395  397      }
 396  398  
 397  399      /**
 398  400       * @throws NullPointerException {@inheritDoc}
 399  401       * @throws InterruptedException {@inheritDoc}
 400  402       */
 401  403      public boolean offerFirst(E e, long timeout, TimeUnit unit)
 402  404          throws InterruptedException {
 403  405          if (e == null) throw new NullPointerException();
      406 +        Node<E> node = new Node<E>(e);
 404  407          long nanos = unit.toNanos(timeout);
 405  408          final ReentrantLock lock = this.lock;
 406  409          lock.lockInterruptibly();
 407  410          try {
 408      -            while (!linkFirst(e)) {
      411 +            while (!linkFirst(node)) {
 409  412                  if (nanos <= 0)
 410  413                      return false;
 411  414                  nanos = notFull.awaitNanos(nanos);
 412  415              }
 413  416              return true;
 414  417          } finally {
 415  418              lock.unlock();
 416  419          }
 417  420      }
 418  421  
 419  422      /**
 420  423       * @throws NullPointerException {@inheritDoc}
 421  424       * @throws InterruptedException {@inheritDoc}
 422  425       */
 423  426      public boolean offerLast(E e, long timeout, TimeUnit unit)
 424  427          throws InterruptedException {
 425  428          if (e == null) throw new NullPointerException();
      429 +        Node<E> node = new Node<E>(e);
 426  430          long nanos = unit.toNanos(timeout);
 427  431          final ReentrantLock lock = this.lock;
 428  432          lock.lockInterruptibly();
 429  433          try {
 430      -            while (!linkLast(e)) {
      434 +            while (!linkLast(node)) {
 431  435                  if (nanos <= 0)
 432  436                      return false;
 433  437                  nanos = notFull.awaitNanos(nanos);
 434  438              }
 435  439              return true;
 436  440          } finally {
 437  441              lock.unlock();
 438  442          }
 439  443      }
 440  444  
↓ open down ↓ 507 lines elided ↑ open up ↑
 948  952              return a;
 949  953          } finally {
 950  954              lock.unlock();
 951  955          }
 952  956      }
 953  957  
 954  958      public String toString() {
 955  959          final ReentrantLock lock = this.lock;
 956  960          lock.lock();
 957  961          try {
 958      -            return super.toString();
      962 +            Node<E> p = first;
      963 +            if (p == null)
      964 +                return "[]";
      965 +
      966 +            StringBuilder sb = new StringBuilder();
      967 +            sb.append('[');
      968 +            for (;;) {
      969 +                E e = p.item;
      970 +                sb.append(e == this ? "(this Collection)" : e);
      971 +                p = p.next;
      972 +                if (p == null)
      973 +                    return sb.append(']').toString();
      974 +                sb.append(',').append(' ');
      975 +            }
 959  976          } finally {
 960  977              lock.unlock();
 961  978          }
 962  979      }
 963  980  
 964  981      /**
 965  982       * Atomically removes all of the elements from this deque.
 966  983       * The deque will be empty after this call returns.
 967  984       */
 968  985      public void clear() {
↓ open down ↓ 78 lines elided ↑ open up ↑
1047 1064              lock.lock();
1048 1065              try {
1049 1066                  next = firstNode();
1050 1067                  nextItem = (next == null) ? null : next.item;
1051 1068              } finally {
1052 1069                  lock.unlock();
1053 1070              }
1054 1071          }
1055 1072  
1056 1073          /**
     1074 +         * Returns the successor node of the given non-null, but
     1075 +         * possibly previously deleted, node.
     1076 +         */
     1077 +        private Node<E> succ(Node<E> n) {
     1078 +            // Chains of deleted nodes ending in null or self-links
     1079 +            // are possible if multiple interior nodes are removed.
     1080 +            for (;;) {
     1081 +                Node<E> s = nextNode(n);
     1082 +                if (s == null)
     1083 +                    return null;
     1084 +                else if (s.item != null)
     1085 +                    return s;
     1086 +                else if (s == n)
     1087 +                    return firstNode();
     1088 +                else
     1089 +                    n = s;
     1090 +            }
     1091 +        }
     1092 +
     1093 +        /**
1057 1094           * Advances next.
1058 1095           */
1059 1096          void advance() {
1060 1097              final ReentrantLock lock = LinkedBlockingDeque.this.lock;
1061 1098              lock.lock();
1062 1099              try {
1063 1100                  // assert next != null;
1064      -                Node<E> s = nextNode(next);
1065      -                if (s == next) {
1066      -                    next = firstNode();
1067      -                } else {
1068      -                    // Skip over removed nodes.
1069      -                    // May be necessary if multiple interior Nodes are removed.
1070      -                    while (s != null && s.item == null)
1071      -                        s = nextNode(s);
1072      -                    next = s;
1073      -                }
     1101 +                next = succ(next);
1074 1102                  nextItem = (next == null) ? null : next.item;
1075 1103              } finally {
1076 1104                  lock.unlock();
1077 1105              }
1078 1106          }
1079 1107  
1080 1108          public boolean hasNext() {
1081 1109              return next != null;
1082 1110          }
1083 1111  
↓ open down ↓ 83 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX