/*
* JVSTM: a Java library for Software Transactional Memory
* Copyright (C) 2005 INESC-ID Software Engineering Group
* http://www.esw.inesc-id.pt
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Author's contact:
* INESC-ID Software Engineering Group
* Rua Alves Redol 9
* 1000 - 029 Lisboa
* Portugal
*/
package jvstm.util;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Queue;
import jvstm.Atomic;
import jvstm.VBox;
import jvstm.VBoxInt;
public class VQueue<E> extends AbstractCollection<E> implements Queue<E> {
private final VBox<Cons<E>> front = new VBox<Cons<E>>((Cons<E>) Cons.empty());
private final VBox<Cons<E>> rear = new VBox<Cons<E>>((Cons<E>) Cons.empty());
private final VBoxInt size = new VBoxInt(0);
public VQueue() {
}
public VQueue(Collection<? extends E> c) {
addAll(c);
}
@Override
public int size() {
return size.getInt();
}
@Override
public boolean add(E o) {
return offer(o);
}
// the Queue interface methods
@Override
@Atomic(canFail = false)
public boolean offer(E o) {
Cons<E> frontElems = front.get();
if (frontElems.isEmpty()) {
front.put(frontElems.cons(o));
} else {
rear.put(rear.get().cons(o));
}
size.inc();
return true;
}
@Override
@Atomic(canFail = false)
public E poll() {
Cons<E> frontElems = front.get();
if (frontElems.isEmpty()) {
return null;
} else {
return removeExisting(frontElems);
}
}
@Override
@Atomic
public E remove() {
Cons<E> frontElems = front.get();
if (frontElems.isEmpty()) {
throw new NoSuchElementException();
} else {
return removeExisting(frontElems);
}
}
private E removeExisting(Cons<E> frontElems) {
E result = frontElems.first();
frontElems = frontElems.rest();
if (frontElems.isEmpty()) {
frontElems = rear.get().reverse();
if (!frontElems.isEmpty()) {
// only clear the rear if it had anything
rear.put((Cons<E>) Cons.empty());
}
}
front.put(frontElems);
size.dec();
return result;
}
@Override
@Atomic(readOnly = true)
public E peek() {
Cons<E> frontElems = front.get();
if (frontElems.isEmpty()) {
return null;
} else {
return frontElems.first();
}
}
@Override
@Atomic(readOnly = true)
public E element() {
Cons<E> frontElems = front.get();
if (frontElems.isEmpty()) {
throw new NoSuchElementException();
} else {
return frontElems.first();
}
}
// override some methods with better performing implementations
@Override
@Atomic(readOnly = true)
public boolean contains(Object o) {
return front.get().contains(o) || rear.get().contains(o);
}
@Override
public Iterator<E> iterator() {
return new VQueueIterator<E>();
}
@Override
@Atomic(canFail = false)
public void clear() {
front.put((Cons<E>) Cons.empty());
rear.put((Cons<E>) Cons.empty());
size.putInt(0);
}
private class VQueueIterator<T> implements Iterator<T> {
private Iterator<T> current;
private Cons<T> rearElems;
VQueueIterator() {
this.current = (Iterator<T>) VQueue.this.front.get().iterator();
this.rearElems = (Cons<T>) VQueue.this.rear.get();
}
@Override
public boolean hasNext() {
return current.hasNext() || (!rearElems.isEmpty());
}
@Override
public T next() {
if (!current.hasNext()) {
if (!rearElems.isEmpty()) {
current = rearElems.reverse().iterator();
rearElems = (Cons<T>) Cons.empty();
}
}
if (!current.hasNext()) {
throw new NoSuchElementException();
} else {
return current.next();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}