/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.tomcat.dbcp.pool2.impl; import java.io.Serializable; import java.util.AbstractQueue; import java.util.Collection; import java.util.Deque; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; /** * An optionally-bounded {@linkplain java.util.concurrent.BlockingDeque blocking * deque} based on linked nodes. * *
The optional capacity bound constructor argument serves as a * way to prevent excessive expansion. The capacity, if unspecified, * is equal to {@link Integer#MAX_VALUE}. Linked nodes are * dynamically created upon each insertion unless this would bring the * deque above capacity. *
* *Most operations run in constant time (ignoring time spent * blocking). Exceptions include {@link #remove(Object) remove}, * {@link #removeFirstOccurrence removeFirstOccurrence}, {@link * #removeLastOccurrence removeLastOccurrence}, {@link #contains * contains}, {@link #iterator iterator.remove()}, and the bulk * operations, all of which run in linear time. *
* *This class and its iterator implement all of the * optional methods of the {@link Collection} and {@link * Iterator} interfaces. *
* *This class is a member of the * * Java Collections Framework. *
* * @paramThis method is equivalent to {@link #putLast(Object)}. * * @param e element to link * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ public void put(final E e) throws InterruptedException { putLast(e); } /** * Links the provided element as the last in the queue, waiting up to the * specified time to do so if the queue is full. *
* This method is equivalent to {@link #offerLast(Object, long, TimeUnit)} * * @param e element to link * @param timeout length of time to wait * @param unit units that timeout is expressed in * * @return {@code true} if successful, otherwise {@code false} * * @throws NullPointerException if e is null * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ public boolean offer(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { return offerLast(e, timeout, unit); } /** * Retrieves and removes the head of the queue represented by this deque. * This method differs from {@link #poll poll} only in that it throws an * exception if this deque is empty. * *
This method is equivalent to {@link #removeFirst() removeFirst}. * * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ @Override public E remove() { return removeFirst(); } @Override public E poll() { return pollFirst(); } /** * Unlinks the first element in the queue, waiting until there is an element * to unlink if the queue is empty. * *
This method is equivalent to {@link #takeFirst()}. * * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ public E take() throws InterruptedException { return takeFirst(); } /** * Unlinks the first element in the queue, waiting up to the specified time * to do so if the queue is empty. * *
This method is equivalent to {@link #pollFirst(long, TimeUnit)}. * * @param timeout length of time to wait * @param unit units that timeout is expressed in * * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ public E poll(final long timeout, final TimeUnit unit) throws InterruptedException { return pollFirst(timeout, unit); } /** * Retrieves, but does not remove, the head of the queue represented by * this deque. This method differs from {@link #peek peek} only in that * it throws an exception if this deque is empty. * *
This method is equivalent to {@link #getFirst() getFirst}. * * @return the head of the queue represented by this deque * @throws NoSuchElementException if this deque is empty */ @Override public E element() { return getFirst(); } @Override public E peek() { return peekFirst(); } /** * Returns the number of additional elements that this deque can ideally * (in the absence of memory or resource constraints) accept without * blocking. This is always equal to the initial capacity of this deque * less the current {@code size} of this deque. * *
Note that you cannot always tell if an attempt to insert * an element will succeed by inspecting {@code remainingCapacity} * because it may be the case that another thread is about to * insert or remove an element. * * @return The number of additional elements the queue is able to accept */ public int remainingCapacity() { lock.lock(); try { return capacity - count; } finally { lock.unlock(); } } /** * Drains the queue to the specified collection. * * @param c The collection to add the elements to * * @return number of elements added to the collection * * @throws UnsupportedOperationException if the add operation is not * supported by the specified collection * @throws ClassCastException if the class of the elements held by this * collection prevents them from being added to the specified * collection * @throws NullPointerException if c is null * @throws IllegalArgumentException if c is this instance */ public int drainTo(final Collection super E> c) { return drainTo(c, Integer.MAX_VALUE); } /** * Drains no more than the specified number of elements from the queue to the * specified collection. * * @param c collection to add the elements to * @param maxElements maximum number of elements to remove from the queue * * @return number of elements added to the collection * @throws UnsupportedOperationException if the add operation is not * supported by the specified collection * @throws ClassCastException if the class of the elements held by this * collection prevents them from being added to the specified * collection * @throws NullPointerException if c is null * @throws IllegalArgumentException if c is this instance */ public int drainTo(final Collection super E> c, final int maxElements) { if (c == null) { throw new NullPointerException(); } if (c == this) { throw new IllegalArgumentException(); } lock.lock(); try { final int n = Math.min(maxElements, count); for (int i = 0; i < n; i++) { c.add(first.item); // In this order, in case add() throws. unlinkFirst(); } return n; } finally { lock.unlock(); } } // Stack methods /** * {@inheritDoc} */ @Override public void push(final E e) { addFirst(e); } /** * {@inheritDoc} */ @Override public E pop() { return removeFirst(); } // Collection methods /** * Removes the first occurrence of the specified element from this deque. * If the deque does not contain the element, it is unchanged. * More formally, removes the first element {@code e} such that * {@code o.equals(e)} (if such an element exists). * Returns {@code true} if this deque contained the specified element * (or equivalently, if this deque changed as a result of the call). * *
This method is equivalent to
* {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
*
* @param o element to be removed from this deque, if present
* @return {@code true} if this deque changed as a result of the call
*/
@Override
public boolean remove(final Object o) {
return removeFirstOccurrence(o);
}
/**
* Returns the number of elements in this deque.
*
* @return the number of elements in this deque
*/
@Override
public int size() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
/**
* Returns {@code true} if this deque contains the specified element.
* More formally, returns {@code true} if and only if this deque contains
* at least one element {@code e} such that {@code o.equals(e)}.
*
* @param o object to be checked for containment in this deque
* @return {@code true} if this deque contains the specified element
*/
@Override
public boolean contains(final Object o) {
if (o == null) {
return false;
}
lock.lock();
try {
for (Node The returned array will be "safe" in that no references to it are
* maintained by this deque. (In other words, this method must allocate
* a new array). The caller is thus free to modify the returned array.
*
* This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all of the elements in this deque
*/
@Override
public Object[] toArray() {
lock.lock();
try {
final Object[] a = new Object[count];
int k = 0;
for (Node