/**
  * Creates a {@code ConcurrentLinkedQueue} initially containing the elements of the given
  * collection, added in traversal order of the collection's iterator.
  *
  * @param c the collection of elements to initially contain
  * @throws NullPointerException if the specified collection or any of its elements are null
  */
 public ConcurrentLinkedQueue(Collection<? extends E> c) {
   Node<E> h = null, t = null;
   for (E e : c) {
     checkNotNull(e);
     Node<E> newNode = new Node<E>(e);
     if (h == null) h = t = newNode;
     else {
       t.lazySetNext(newNode);
       t = newNode;
     }
   }
   if (h == null) h = t = new Node<E>(null);
   head = h;
   tail = t;
 }
  /**
   * 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;
    }
  }
  /**
   * Reconstitutes this queue from a stream (that is, deserializes it).
   *
   * @param s the stream
   * @throws ClassNotFoundException if the class of a serialized object could not be found
   * @throws java.io.IOException if an I/O error occurs
   */
  private void readObject(java.io.ObjectInputStream s)
      throws java.io.IOException, ClassNotFoundException {
    s.defaultReadObject();

    // Read in elements until trailing null sentinel found
    Node<E> h = null, t = null;
    Object item;
    while ((item = s.readObject()) != null) {
      @SuppressWarnings("unchecked")
      Node<E> newNode = new Node<E>((E) item);
      if (h == null) h = t = newNode;
      else {
        t.lazySetNext(newNode);
        t = newNode;
      }
    }
    if (h == null) h = t = new Node<E>(null);
    head = h;
    tail = t;
  }
 /**
  * Tries to CAS head to p. If successful, repoint old head to itself as sentinel for succ(),
  * below.
  */
 final void updateHead(Node<E> h, Node<E> p) {
   if (h != p && casHead(h, p)) h.lazySetNext(h);
 }