/* * 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.lang.reflect.Array; import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; import jvstm.Atomic; import jvstm.VBox; import jvstm.VBoxInt; public class VLinkedSet<E> implements Set<E> { private final VBox<Cons<E>> entries = new VBox<Cons<E>>((Cons<E>) Cons.empty()); private final VBoxInt size = new VBoxInt(0); public VLinkedSet() { } public VLinkedSet(Collection<? extends E> c) { addAll(c); } @Override public int size() { return size.getInt(); } @Override public boolean isEmpty() { return entries.get().isEmpty(); } @Override public boolean contains(Object o) { return entries.get().contains(o); } @Override public Iterator<E> iterator() { return new VLinkedSetIterator<E>(); } @Override @Atomic(readOnly = true) public Object[] toArray() { int size = size(); Cons<E> elems = entries.get(); Object[] result = new Object[size]; Iterator<?> iter = elems.iterator(); for (int i = 0; i < size; i++) { result[i] = iter.next(); } return result; } @Override @Atomic(readOnly = true) public <T> T[] toArray(T[] a) { int size = size(); Cons<E> elems = entries.get(); if (a.length < size) { a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); } Iterator<E> iter = elems.iterator(); Object[] result = a; for (int i = 0; i < size; i++) { result[i] = iter.next(); } if (size < a.length) { a[size] = null; } return a; } @Override @Atomic(canFail = false) public boolean add(E o) { Cons<E> oldElems = entries.get(); Cons<E> newElems = adjoin(oldElems, o); if (oldElems == newElems) { return false; } else { entries.put(newElems); size.inc(); return true; } } @Override @Atomic(canFail = false) public boolean remove(Object o) { Cons<E> oldElems = entries.get(); Cons<E> newElems = oldElems.removeFirst(o); if (oldElems == newElems) { return false; } else { entries.put(newElems); size.dec(); return true; } } @Override public boolean containsAll(Collection<?> c) { Cons<E> elems = entries.get(); for (Object o : c) { if (!elems.contains(o)) { return false; } } return true; } @Override @Atomic(canFail = false) public boolean addAll(Collection<? extends E> c) { Cons<E> prev = entries.get(); int added = 0; for (E o : c) { Cons<E> next = adjoin(prev, o); if (prev != next) { added++; prev = next; } } if (added > 0) { entries.put(prev); size.inc(added); } return added > 0; } @Override @Atomic(canFail = false) public boolean retainAll(Collection<?> c) { Cons<E> result = Cons.empty(); Cons<E> elems = entries.get(); int removed = 0; for (E o : elems) { if (c.contains(o)) { result = result.cons(o); } else { removed++; } } if (removed > 0) { entries.put(result.reverse()); size.dec(removed); } return removed > 0; } @Override @Atomic(canFail = false) public boolean removeAll(Collection<?> c) { Cons<E> prev = entries.get(); int removed = 0; for (Object o : c) { Cons<E> next = prev.removeFirst(o); if (prev != next) { removed++; prev = next; } } if (removed > 0) { entries.put(prev); size.dec(removed); } return removed > 0; } @Override @Atomic(canFail = false) public void clear() { entries.put((Cons<E>) Cons.empty()); size.putInt(0); } @Override @Atomic(readOnly = true) public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Set)) { return false; } Set<?> otherSet = (Set<?>) o; if (this.size() != otherSet.size()) { return false; } return containsAll(otherSet); } @Override @Atomic(readOnly = true) public int hashCode() { int value = 0; for (E o : entries.get()) { if (o != null) { value += o.hashCode(); } } return value; } private Cons<E> adjoin(Cons<E> list, E elem) { return (list.contains(elem)) ? list : list.cons(elem); } protected void removeCons(Cons<?> cons) { Cons<E> oldElems = entries.get(); Cons<E> newElems = oldElems.removeCons(cons); if (oldElems != newElems) { entries.put(newElems); size.dec(); } } private class VLinkedSetIterator<T> implements Iterator<T> { private Cons<T> current; private Cons<T> previous = null; VLinkedSetIterator() { this.current = (Cons<T>) VLinkedSet.this.entries.get(); } @Override public boolean hasNext() { return (current != Cons.EMPTY); } @Override public T next() { if (current == Cons.EMPTY) { throw new NoSuchElementException(); } else { T result = current.first; previous = current; current = current.rest; return result; } } @Override public void remove() { if (previous == null) { throw new IllegalStateException(); } else { VLinkedSet.this.removeCons(previous); previous = null; } } } }