Print this page


Split Close
Expand all
Collapse all
          --- old/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java
          +++ new/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java
↓ open down ↓ 181 lines elided ↑ open up ↑
 182  182          final ReentrantLock putLock = this.putLock;
 183  183          putLock.lock();
 184  184          try {
 185  185              notFull.signal();
 186  186          } finally {
 187  187              putLock.unlock();
 188  188          }
 189  189      }
 190  190  
 191  191      /**
 192      -     * Creates a node and links it at end of queue.
      192 +     * Links node at end of queue.
 193  193       *
 194      -     * @param x the item
      194 +     * @param node the node
 195  195       */
 196      -    private void enqueue(E x) {
      196 +    private void enqueue(Node<E> node) {
 197  197          // assert putLock.isHeldByCurrentThread();
 198  198          // assert last.next == null;
 199      -        last = last.next = new Node<E>(x);
      199 +        last = last.next = node;
 200  200      }
 201  201  
 202  202      /**
 203  203       * Removes a node from head of queue.
 204  204       *
 205  205       * @return the node
 206  206       */
 207  207      private E dequeue() {
 208  208          // assert takeLock.isHeldByCurrentThread();
 209  209          // assert head.item == null;
↓ open down ↓ 65 lines elided ↑ open up ↑
 275  275          this(Integer.MAX_VALUE);
 276  276          final ReentrantLock putLock = this.putLock;
 277  277          putLock.lock(); // Never contended, but necessary for visibility
 278  278          try {
 279  279              int n = 0;
 280  280              for (E e : c) {
 281  281                  if (e == null)
 282  282                      throw new NullPointerException();
 283  283                  if (n == capacity)
 284  284                      throw new IllegalStateException("Queue full");
 285      -                enqueue(e);
      285 +                enqueue(new Node<E>(e));
 286  286                  ++n;
 287  287              }
 288  288              count.set(n);
 289  289          } finally {
 290  290              putLock.unlock();
 291  291          }
 292  292      }
 293  293  
 294  294  
 295  295      // this doc comment is overridden to remove the reference to collections
↓ open down ↓ 29 lines elided ↑ open up ↑
 325  325       * necessary for space to become available.
 326  326       *
 327  327       * @throws InterruptedException {@inheritDoc}
 328  328       * @throws NullPointerException {@inheritDoc}
 329  329       */
 330  330      public void put(E e) throws InterruptedException {
 331  331          if (e == null) throw new NullPointerException();
 332  332          // Note: convention in all put/take/etc is to preset local var
 333  333          // holding count negative to indicate failure unless set.
 334  334          int c = -1;
      335 +        Node<E> node = new Node(e);
 335  336          final ReentrantLock putLock = this.putLock;
 336  337          final AtomicInteger count = this.count;
 337  338          putLock.lockInterruptibly();
 338  339          try {
 339  340              /*
 340  341               * Note that count is used in wait guard even though it is
 341  342               * not protected by lock. This works because count can
 342  343               * only decrease at this point (all other puts are shut
 343  344               * out by lock), and we (or some other waiting put) are
 344  345               * signalled if it ever changes from capacity. Similarly
 345  346               * for all other uses of count in other wait guards.
 346  347               */
 347  348              while (count.get() == capacity) {
 348  349                  notFull.await();
 349  350              }
 350      -            enqueue(e);
      351 +            enqueue(node);
 351  352              c = count.getAndIncrement();
 352  353              if (c + 1 < capacity)
 353  354                  notFull.signal();
 354  355          } finally {
 355  356              putLock.unlock();
 356  357          }
 357  358          if (c == 0)
 358  359              signalNotEmpty();
 359  360      }
 360  361  
↓ open down ↓ 14 lines elided ↑ open up ↑
 375  376          int c = -1;
 376  377          final ReentrantLock putLock = this.putLock;
 377  378          final AtomicInteger count = this.count;
 378  379          putLock.lockInterruptibly();
 379  380          try {
 380  381              while (count.get() == capacity) {
 381  382                  if (nanos <= 0)
 382  383                      return false;
 383  384                  nanos = notFull.awaitNanos(nanos);
 384  385              }
 385      -            enqueue(e);
      386 +            enqueue(new Node<E>(e));
 386  387              c = count.getAndIncrement();
 387  388              if (c + 1 < capacity)
 388  389                  notFull.signal();
 389  390          } finally {
 390  391              putLock.unlock();
 391  392          }
 392  393          if (c == 0)
 393  394              signalNotEmpty();
 394  395          return true;
 395  396      }
↓ open down ↓ 8 lines elided ↑ open up ↑
 404  405       * insert an element only by throwing an exception.
 405  406       *
 406  407       * @throws NullPointerException if the specified element is null
 407  408       */
 408  409      public boolean offer(E e) {
 409  410          if (e == null) throw new NullPointerException();
 410  411          final AtomicInteger count = this.count;
 411  412          if (count.get() == capacity)
 412  413              return false;
 413  414          int c = -1;
      415 +        Node<E> node = new Node(e);
 414  416          final ReentrantLock putLock = this.putLock;
 415  417          putLock.lock();
 416  418          try {
 417  419              if (count.get() < capacity) {
 418      -                enqueue(e);
      420 +                enqueue(node);
 419  421                  c = count.getAndIncrement();
 420  422                  if (c + 1 < capacity)
 421  423                      notFull.signal();
 422  424              }
 423  425          } finally {
 424  426              putLock.unlock();
 425  427          }
 426  428          if (c == 0)
 427  429              signalNotEmpty();
 428  430          return c >= 0;
↓ open down ↓ 124 lines elided ↑ open up ↑
 553  555                      return true;
 554  556                  }
 555  557              }
 556  558              return false;
 557  559          } finally {
 558  560              fullyUnlock();
 559  561          }
 560  562      }
 561  563  
 562  564      /**
      565 +     * Returns {@code true} if this queue contains the specified element.
      566 +     * More formally, returns {@code true} if and only if this queue contains
      567 +     * at least one element {@code e} such that {@code o.equals(e)}.
      568 +     *
      569 +     * @param o object to be checked for containment in this queue
      570 +     * @return {@code true} if this queue contains the specified element
      571 +     */
      572 +    public boolean contains(Object o) {
      573 +        if (o == null) return false;
      574 +        fullyLock();
      575 +        try {
      576 +            for (Node<E> p = head.next; p != null; p = p.next)
      577 +                if (o.equals(p.item))
      578 +                    return true;
      579 +            return false;
      580 +        } finally {
      581 +            fullyUnlock();
      582 +        }
      583 +    }
      584 +
      585 +    /**
 563  586       * Returns an array containing all of the elements in this queue, in
 564  587       * proper sequence.
 565  588       *
 566  589       * <p>The returned array will be "safe" in that no references to it are
 567  590       * maintained by this queue.  (In other words, this method must allocate
 568  591       * a new array).  The caller is thus free to modify the returned array.
 569  592       *
 570  593       * <p>This method acts as bridge between array-based and collection-based
 571  594       * APIs.
 572  595       *
↓ open down ↓ 65 lines elided ↑ open up ↑
 638  661                  a[k] = null;
 639  662              return a;
 640  663          } finally {
 641  664              fullyUnlock();
 642  665          }
 643  666      }
 644  667  
 645  668      public String toString() {
 646  669          fullyLock();
 647  670          try {
 648      -            return super.toString();
      671 +            Node<E> p = head.next;
      672 +            if (p == null)
      673 +                return "[]";
      674 +
      675 +            StringBuilder sb = new StringBuilder();
      676 +            sb.append('[');
      677 +            for (;;) {
      678 +                E e = p.item;
      679 +                sb.append(e == this ? "(this Collection)" : e);
      680 +                p = p.next;
      681 +                if (p == null)
      682 +                    return sb.append(']').toString();
      683 +                sb.append(',').append(' ');
      684 +            }
 649  685          } finally {
 650  686              fullyUnlock();
 651  687          }
 652  688      }
 653  689  
 654  690      /**
 655  691       * Atomically removes all of the elements from this queue.
 656  692       * The queue will be empty after this call returns.
 657  693       */
 658  694      public void clear() {
↓ open down ↓ 61 lines elided ↑ open up ↑
 720  756              }
 721  757          } finally {
 722  758              takeLock.unlock();
 723  759              if (signalNotFull)
 724  760                  signalNotFull();
 725  761          }
 726  762      }
 727  763  
 728  764      /**
 729  765       * Returns an iterator over the elements in this queue in proper sequence.
 730      -     * The returned {@code Iterator} is a "weakly consistent" iterator that
      766 +     * The elements will be returned in order from first (head) to last (tail).
      767 +     *
      768 +     * <p>The returned iterator is a "weakly consistent" iterator that
 731  769       * will never throw {@link java.util.ConcurrentModificationException
 732      -     * ConcurrentModificationException},
 733      -     * and guarantees to traverse elements as they existed upon
 734      -     * construction of the iterator, and may (but is not guaranteed to)
 735      -     * reflect any modifications subsequent to construction.
      770 +     * ConcurrentModificationException}, and guarantees to traverse
      771 +     * elements as they existed upon construction of the iterator, and
      772 +     * may (but is not guaranteed to) reflect any modifications
      773 +     * subsequent to construction.
 736  774       *
 737  775       * @return an iterator over the elements in this queue in proper sequence
 738  776       */
 739  777      public Iterator<E> iterator() {
 740  778        return new Itr();
 741  779      }
 742  780  
 743  781      private class Itr implements Iterator<E> {
 744  782          /*
 745  783           * Basic weakly-consistent iterator.  At all times hold the next
↓ open down ↓ 127 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX