/*******************************************************************************
* Copyright (c) 2007, 2010 Association for Decentralized Information Management
* in Industry THTH ry.
* 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:
* VTT Technical Research Centre of Finland - initial API and implementation
*******************************************************************************/
package org.simantics.db.impl.query;
import java.util.Arrays;
import java.util.Iterator;
/**
* An implementation of the Set interface that uses an
* open-addressed hash table to store its contents.
*
* Created: Sat Nov 3 10:38:17 2001
*
* @author Eric D. Friedman
* @version $Id: QueryIdentityHashSet.java,v 1.1 2008/03/14 11:32:01 tuoksk Exp $
*/
final public class QueryIdentityHashSet extends QueryIdentityHash implements Iterable {
/**
* Creates a new THashSet
instance with a prime
* capacity equal to or greater than initialCapacity and
* with the default load factor.
*
* @param initialCapacity an int
value
*/
public QueryIdentityHashSet(int initialCapacity) {
super(initialCapacity);
}
/**
* Inserts a value into the set.
*
* @param obj an Object
value
* @return true if the set was modified by the add operation
*/
final public boolean add(final CacheEntry obj) {
final int index = insertionIndex(obj);
if (index < 0) {
return false; // already present in set, nothing to add
}
final CacheEntry old = _set[index];
_set[index] = obj;
postInsertHook(old == null);
return true; // yes, we added something
}
/**
* Expands the set to accomodate new values.
*
* @param newCapacity an int
value
*/
final protected void rehash(int newCapacity) {
final int oldCapacity = _set.length;
final CacheEntry oldSet[] = _set;
_set = new CacheEntry[newCapacity];
for (int i = oldCapacity; i-- > 0;) {
if(oldSet[i] != null && oldSet[i] != REMOVED) {
final CacheEntry o = oldSet[i];
//if(o.isDiscarded()) continue;
final int index = insertionIndex(o);
if(index < 0) {
new Exception().printStackTrace();
System.out.println("rehash " + i + " " + o);
for (int j = oldCapacity; j-- > 0;) {
System.out.println("rehash " + j+ " " + oldSet[j] + " " + System.identityHashCode(oldSet[j]));
}
}
else _set[index] = o;
}
}
}
/**
* Removes obj from the set.
*
* @param obj an Object
value
* @return true if the set was modified by the remove operation.
*/
final public boolean remove(Object obj) {
int index = index(obj);
if (index >= 0) {
removeAt(index);
return true;
}
return false;
}
private int knownBound = 10;
final public void purge() {
if(size() > (knownBound<<1)) {
knownBound=10;
for(int i=0;i<_set.length;i++) {
CacheEntry entry = _set[i];
if(entry != null && REMOVED != entry) {
if(entry.isDiscarded()) {
removeAt(i);
} else {
knownBound++;
}
}
}
}
}
final public CacheEntry removeDiscarded() {
tempDisableAutoCompaction();
try {
for(int i=0;i<_set.length;i++) {
CacheEntry entry = _set[i];
if(entry != null && REMOVED != entry) {
removeAt(i);
if(!entry.isDiscarded()) return entry;
}
}
return null;
} finally {
reenableAutoCompaction(false);
}
}
/**
* Creates an iterator over the values of the set. The iterator
* supports element deletion.
*
* @return an Iterator
value
*/
final public Iterator iterator() {
class Iter implements Iterator {
private int index = capacity();
public Iter() {
advance();
}
private void advance() {
while (index-- > 0 && (_set[index] == null || _set[index] == QueryIdentityHash.REMOVED)) ;
}
@Override
public boolean hasNext() {
return index >= 0;
}
@Override
public CacheEntry next() {
if(index >= 0) {
CacheEntry result = (CacheEntry)_set[index];
advance();
return result;
}
return null;
}
@Override
public void remove() {
throw new Error("Not supported.");
}
};
return new Iter();
}
public void clear() {
super.clear();
Arrays.fill(_set, 0, _set.length, null);
}
} // THashSet