package com.infomancers.collections.concurrent; import java.util.*; import java.util.concurrent.BlockingDeque; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; /** * Copyright (c) 2007, Aviad Ben Dov * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * 3. Neither the name of Infomancers, Ltd. nor the names of its contributors may be * used to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on * a navigable set. *
*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}. *
*This class and its iterator implement all of the * optional methods of the {@link Collection} and {@link * Iterator} interfaces. *
* This code is loosely based on the {@linkplain java.util.concurrent.LinkedBlockingDeque linked blocking deque} code. * * @author Aviad Ben Dov * @paramThis method is equivalent to {@link #addLast}. * * @throws IllegalStateException if the element cannot be added at this * time due to capacity restrictions * @throws NullPointerException if the specified element is null */ @Override public boolean add(E e) { addLast(e); return true; } /** * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { return offerLast(e); } /** * @throws NullPointerException {@inheritDoc} * @throws InterruptedException {@inheritDoc} */ public void put(E e) throws InterruptedException { putLast(e); } /** * @throws NullPointerException {@inheritDoc} * @throws InterruptedException {@inheritDoc} */ public boolean offer(E e, long timeout, 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(); } public E poll() { return pollFirst(); } public E take() throws InterruptedException { return takeFirst(); } public E poll(long timeout, 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(); } 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 size of this deque. *
*Note that you cannot always tell if an attempt to insert
* an element will succeed by inspecting remainingCapacity
* because it may be the case that another thread is about to
* insert or remove an element.
*/
public int remainingCapacity() {
lock.lock();
try {
return capacity - list.size();
} finally {
lock.unlock();
}
}
/**
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection super E> c) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
lock.lock();
try {
for (E e : list) {
c.add(e);
}
int n = list.size();
list.clear();
notFull.signalAll();
return n;
} finally {
lock.unlock();
}
}
/**
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection super E> c, int maxElements) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
lock.lock();
try {
int n = 0;
for (Iterator This method is equivalent to
* {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
*
* @param o element to be removed from this deque, if present
* @return true if this deque changed as a result of the call
*/
@Override
public boolean remove(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 list.size();
} finally {
lock.unlock();
}
}
/**
* Returns true if this deque contains the specified element.
* More formally, returns true if and only if this deque contains
* at least one element e such that o.equals(e).
*
* @param o object to be checked for containment in this deque
* @return true if this deque contains the specified element
*/
@Override
public boolean contains(Object o) {
if (o == null) return false;
lock.lock();
try {
return list.contains(o);
} finally {
lock.unlock();
}
}
/**
* Returns an array containing all of the elements in this deque, in
* proper sequence (from first to last element).
* 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 {
return list.toArray();
} finally {
lock.unlock();
}
}
/**
* Returns an array containing all of the elements in this deque, in
* proper sequence; the runtime type of the returned array is that of
* the specified array. If the deque fits in the specified array, it
* is returned therein. Otherwise, a new array is allocated with the
* runtime type of the specified array and the size of this deque.
* If this deque fits in the specified array with room to spare
* (i.e., the array has more elements than this deque), the element in
* the array immediately following the end of the deque is set to
* null.
* Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
* Suppose x is a deque known to contain only strings.
* The following code can be used to dump the deque into a newly
* allocated array of String:
*
* String[] y = x.toArray(new String[0]);
*
* Note that toArray(new Object[0]) is identical in function to
* toArray().
*
* @param a the array into which the elements of the deque are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose
* @return an array containing all of the elements in this deque
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this deque
* @throws NullPointerException if the specified array is null
*/
@Override
public