blob: e54eb3e80df48dad55eb7a14d6a003b466bb8445 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.jobs;
import java.util.*;
/**
* A Queue of objects.
*/
public class Queue {
protected Object[] elements;
protected int head;
protected boolean reuse;
protected int tail;
public Queue() {
this(20, false);
}
/**
* The parameter reuse indicates what do you want to happen with
* the object reference when you remove it from the queue. If
* reuse is false the queue no longer holds a reference to the
* object when it is removed. If reuse is true you can use the
* method getNextAvailableObject to get an used object, set its
* new values and add it again to the queue.
*/
public Queue(int size, boolean reuse) {
elements = new Object[size];
head = tail = 0;
this.reuse = reuse;
}
/**
* Adds an object to the tail of the queue.
*/
public void enqueue(Object element) {
int newTail = increment(tail);
if (newTail == head) {
grow();
newTail = tail + 1;
}
elements[tail] = element;
tail = newTail;
}
/**
* This method does not affect the queue itself. It is only a
* helper to decrement an index in the queue.
*/
public int decrement(int index) {
return (index == 0) ? (elements.length - 1) : index - 1;
}
public Iterator elements() {
/**/
if (isEmpty())
return new ArrayList(0).iterator();
/* if head < tail we can use the same array */
if (head <= tail)
return Arrays.asList(elements).iterator();
/* otherwise we need to create a new array */
Object[] newElements = new Object[size()];
int end = (elements.length - head);
System.arraycopy(elements, head, newElements, 0, end);
System.arraycopy(elements, 0, newElements, end, tail);
return Arrays.asList(newElements).iterator();
}
public Object get(Object o) {
int index = head;
while (index != tail) {
if (elements[index].equals(o))
return elements[index];
index = increment(index);
}
return null;
}
/**
* Removes the given object from the queue. Shifts the underlying array.
*/
public boolean remove(Object o) {
int index = head;
//find the object to remove
while (index != tail) {
if (elements[index].equals(o))
break;
index = increment(index);
}
//if element wasn't found, return
if (index == tail)
return false;
//store a reference to it (needed for reuse of objects)
Object toRemove = elements[index];
int nextIndex = -1;
while (index != tail) {
nextIndex = increment(index);
if (nextIndex != tail)
elements[index] = elements[nextIndex];
index = nextIndex;
}
//decrement tail
tail = decrement(tail);
//if objects are reused, transfer the reference that is removed to the end of the queue
//otherwise set the element after the last one to null (to avoid duplicate references)
elements[tail] = reuse ? toRemove : null;
return true;
}
protected void grow() {
int newSize = (int) (elements.length * 1.5);
Object[] newElements = new Object[newSize];
if (tail >= head)
System.arraycopy(elements, head, newElements, head, size());
else {
int newHead = newSize - (elements.length - head);
System.arraycopy(elements, 0, newElements, 0, tail + 1);
System.arraycopy(elements, head, newElements, newHead, (newSize - newHead));
head = newHead;
}
elements = newElements;
}
/**
* This method does not affect the queue itself. It is only a
* helper to increment an index in the queue.
*/
public int increment(int index) {
return (index == (elements.length - 1)) ? 0 : index + 1;
}
public boolean isEmpty() {
return tail == head;
}
public Object peek() {
return elements[head];
}
/**
* Removes an returns the item at the head of the queue.
*/
public Object dequeue() {
if (isEmpty())
return null;
Object result = peek();
if (!reuse)
elements[head] = null;
head = increment(head);
return result;
}
public int size() {
return tail > head ? (tail - head) : ((elements.length - head) + tail);
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("["); //$NON-NLS-1$
if (!isEmpty()) {
Iterator it = elements();
while (true) {
sb.append(it.next());
if (it.hasNext())
sb.append(", "); //$NON-NLS-1$
else
break;
}
}
sb.append("]"); //$NON-NLS-1$
return sb.toString();
}
}