@Override
  public int drainTo(Collection<? super E> c, int maxElements) {
    if (c == null) {
      throw new NullPointerException();
    }
    if (c == this) {
      throw new IllegalArgumentException();
    }
    boolean signalNotFull = false;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lock();
    try {
      int n = Math.min(maxElements, count.get());
      // count.get provides visibility to first n Nodes
      Node<E> h = head;
      int i = 0;
      try {
        while (i < n) {
          Node<E> p = h.next;
          c.add(p.item);
          p.item = null;
          h.next = h;
          h = p;
          ++i;
        }
        return n;
      } finally {
        // Restore invariants even if c.add() threw
        if (i > 0) {
          // assert h.item == null;
          head = h;
          signalNotFull = (count.getAndAdd(-i) >= capacity); // GEMFIRE changed == to >=
        }
      }
    } finally {
      takeLock.unlock();
      if (signalNotFull) {
        signalNotFull();
      }
    }
  }
@throws UnsupportedOperationException if addition of elements
        is not supported by the specified collection
@throws ClassCastException if the class of an element of this queue
        prevents it from being added to the specified collection
@throws NullPointerException if the specified collection is null
@throws IllegalArgumentException if the specified collection is this
        queue, or some property of an element of this queue prevents
        it from being added to the specified collection
geode-core/src/main/java/org/apache/geode/internal/cache/ForceableLinkedBlockingQueue.java