Пример #1
0
  /**
   * Inserts the specified element at the tail of this queue. As the queue is unbounded, this method
   * will never return {@code false}.
   *
   * @return {@code true} (as specified by {@link Queue#offer})
   * @throws NullPointerException if the specified element is null
   */
  public boolean offer(E e) {
    checkNotNull(e);
    final Node<E> newNode = new Node<E>(e);

    for (Node<E> t = tail, p = t; ; ) {
      Node<E> q = p.next;
      if (q == null) {
        // p is last node
        if (p.casNext(null, newNode)) {
          // Successful CAS is the linearization point
          // for e to become an element of this queue,
          // and for newNode to become "live".
          if (p != t) // hop two nodes at a time
          casTail(t, newNode); // Failure is OK.
          return true;
        }
        // Lost CAS race to another thread; re-read next
      } else if (p == q)
        // We have fallen off list.  If tail is unchanged, it
        // will also be off-list, in which case we need to
        // jump to head, from which all live nodes are always
        // reachable.  Else the new tail is a better bet.
        p = (t != (t = tail)) ? t : head;
      else
        // Check for tail updates after two hops.
        p = (p != t && t != (t = tail)) ? t : q;
    }
  }
Пример #2
0
  /**
   * Appends all of the elements in the specified collection to the end of this queue, in the order
   * that they are returned by the specified collection's iterator. Attempts to {@code addAll} of a
   * queue to itself result in {@code IllegalArgumentException}.
   *
   * @param c the elements to be inserted into this queue
   * @return {@code true} if this queue changed as a result of the call
   * @throws NullPointerException if the specified collection or any of its elements are null
   * @throws IllegalArgumentException if the collection is this queue
   */
  public boolean addAll(Collection<? extends E> c) {
    if (c == this)
      // As historically specified in AbstractQueue#addAll
      throw new IllegalArgumentException();

    // Copy c into a private chain of Nodes
    Node<E> beginningOfTheEnd = null, last = null;
    for (E e : c) {
      checkNotNull(e);
      Node<E> newNode = new Node<E>(e);
      if (beginningOfTheEnd == null) beginningOfTheEnd = last = newNode;
      else {
        last.lazySetNext(newNode);
        last = newNode;
      }
    }
    if (beginningOfTheEnd == null) return false;

    // Atomically append the chain at the tail of this collection
    for (Node<E> t = tail, p = t; ; ) {
      Node<E> q = p.next;
      if (q == null) {
        // p is last node
        if (p.casNext(null, beginningOfTheEnd)) {
          // Successful CAS is the linearization point
          // for all elements to be added to this queue.
          if (!casTail(t, last)) {
            // Try a little harder to update tail,
            // since we may be adding many elements.
            t = tail;
            if (last.next == null) casTail(t, last);
          }
          return true;
        }
        // Lost CAS race to another thread; re-read next
      } else if (p == q)
        // We have fallen off list.  If tail is unchanged, it
        // will also be off-list, in which case we need to
        // jump to head, from which all live nodes are always
        // reachable.  Else the new tail is a better bet.
        p = (t != (t = tail)) ? t : head;
      else
        // Check for tail updates after two hops.
        p = (p != t && t != (t = tail)) ? t : q;
    }
  }