/*******************************************************************************
* Copyright (c) 2000, 2011 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 Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.ui.leaktest.reftracker;
import java.util.Arrays;
/**
*
*/
public class IdentityHashSet {
private Object[] fObjects;
private int fThreshold;
private int fSize;
public IdentityHashSet(int initialSize) {
fObjects= new Object[initialSize];
fThreshold= getThreshold(initialSize);
fSize= 0;
}
private static int getThreshold(int initialSize) {
return (initialSize * 5) / 6;
}
public boolean add(Object o) {
if (o == null) {
throw new IllegalArgumentException("Can not add null"); //$NON-NLS-1$
}
int insertionIndex= getInsertionIndex(o, fObjects);
if (insertionIndex == -1) {
return false; // already in set
}
insertElement(o, insertionIndex);
return true;
}
private void insertElement(Object o, int index) {
fObjects[index]= o;
fSize++;
if (fSize > fThreshold) {
increaseSize();
}
}
private static int getInsertionIndex(Object elem, Object[] elements) {
int hash= getHash(elem, elements.length);
Object entry= elements[hash];
while (entry != null && entry != elem) {
hash++;
if (hash == elements.length) {
hash= 0; // wrap
}
entry= elements[hash];
}
if (entry == null) {
return hash;
}
return -1; // already in set
}
private void increaseSize() {
int newSize= fObjects.length * 2;
Object[] newArray= new Object[newSize];
for (int i= 0; i < fObjects.length; i++) {
Object curr= fObjects[i];
if (curr != null) {
int insertionIndex= getInsertionIndex(curr, newArray);
newArray[insertionIndex]= curr;
fObjects[i]= null; // avoid unnecessary references
}
}
fObjects= newArray;
fThreshold= getThreshold(newSize);
}
public boolean contains(Object o) {
return getInsertionIndex(o, fObjects) == -1;
}
public int size() {
return fSize;
}
public void clear() {
Arrays.fill(fObjects, null);
fSize= 0;
}
/**
* Return index for Object x.
* @param x the object
* @param length the length of the hashtable
* @return returns the hash
*/
private static int getHash(Object x, int length) {
return (System.identityHashCode(x) & 0x7FFFFFFF) % length;
}
}