1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-12 02:35:37 +02:00

bug 290631: Introduced WeakHashSetSynchronized

This commit is contained in:
Andrew Gvozdev 2012-01-28 09:01:32 -05:00
parent 9d29524781
commit 433e8e34c6
5 changed files with 178 additions and 15 deletions

View file

@ -0,0 +1,124 @@
/*******************************************************************************
* Copyright (c) 2012, 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.utils;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.cdt.internal.core.WeakHashSet;
import org.eclipse.cdt.internal.core.WeakHashSetSynchronized;
/**
* Test suite to test {@link WeakHashSet}.
*/
public class WeakHashSetTest extends TestCase {
/**
* Sample mock class with specialized hashCode()
*/
private class MockClass {
private String str;
private MockClass(String str) {
super();
this.str = str;
}
@Override
public int hashCode() {
// for test purpose make hashcodes equal for all "str" stating with the same letter
// note that "equals()" still reports difference
String s = str.substring(0,1);
return s.hashCode();
}
@Override
public boolean equals(Object obj) {
MockClass other = (MockClass) obj;
return str.equals(other.str);
}
}
public static Test suite() {
return new TestSuite(WeakHashSetTest.class);
}
/**
* Test basic methods of {@link WeakHashSet}.
*/
public void testHashSetBasic() {
// create sample objects
WeakHashSet<MockClass> weakSet = new WeakHashSet<MockClass>();
MockClass a1 = new MockClass("a");
MockClass a2 = new MockClass("a");
// check contains()
assertEquals(false, weakSet.contains(a1));
assertEquals(null, weakSet.get(a1));
// check add() and get()
assertSame(a1, weakSet.add(a1));
assertSame(a1, weakSet.add(a2));
assertSame(a1, weakSet.get(a1));
assertSame(a1, weakSet.get(a2));
assertEquals(true, weakSet.contains(a1));
assertEquals(true, weakSet.contains(a2));
// check remove()
MockClass aOld = weakSet.remove(a2);
assertSame(a1, aOld);
assertEquals(null, weakSet.get(a1));
assertSame(a2, weakSet.add(a2));
assertSame(a2, weakSet.add(a1));
// create sample objects with the same hashcode
MockClass aa = new MockClass("aa");
MockClass ab = new MockClass("ab");
assertEquals(aa.hashCode(), ab.hashCode());
assertEquals(false, aa.equals(ab));
// check add() and get()
assertEquals(false, weakSet.contains(aa));
assertEquals(false, weakSet.contains(ab));
assertEquals(null, weakSet.get(aa));
assertEquals(null, weakSet.get(ab));
assertSame(aa, weakSet.add(aa));
assertSame(ab, weakSet.add(ab));
assertEquals(true, weakSet.contains(aa));
assertEquals(true, weakSet.contains(ab));
assertSame(aa, weakSet.get(aa));
assertSame(ab, weakSet.get(ab));
}
/**
* Test synchronized {@link WeakHashSetSynchronized}.
* Note that regular {@link WeakHashSet} would fail the test.
*/
public void testHashSetSyncronization() throws Exception {
final WeakHashSet<Integer> weakSet = new WeakHashSetSynchronized<Integer>(1);
Thread[] threads= new Thread[5000];
for (int i = 0; i < threads.length; i++) {
final Integer n = i;
Thread t= new Thread() {
@Override
public void run() {
weakSet.add(n);
}
};
threads[i] = t;
t.start();
}
for (int i = 0; i < threads.length; i++) {
threads[i].join();
}
assertEquals(threads.length, weakSet.size());
for (int i = 0; i < threads.length; i++) {
assertEquals(true, weakSet.contains(i));
}
}
}

View file

@ -35,6 +35,7 @@ import org.eclipse.cdt.internal.pdom.tests.PDOMTests;
import org.eclipse.cdt.utils.CdtVariableResolverTest;
import org.eclipse.cdt.utils.CommandLineUtilTest;
import org.eclipse.cdt.utils.FindProgramLocationTest;
import org.eclipse.cdt.utils.WeakHashSetTest;
/**
* @author vhirsl
@ -75,6 +76,7 @@ public class AutomatedIntegrationSuite extends TestSuite {
suite.addTest(RewriteTests.suite());
suite.addTest(CdtVariableResolverTest.suite());
suite.addTest(CommandLineUtilTest.suite());
suite.addTest(WeakHashSetTest.suite());
suite.addTest(FindProgramLocationTest.suite());
suite.addTest(EFSExtensionTests.suite());

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 Andrew Gvozdev and others.
* Copyright (c) 2011, 2012 Andrew Gvozdev 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
@ -22,6 +22,7 @@ import java.util.Set;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.internal.core.WeakHashSet;
import org.eclipse.cdt.internal.core.WeakHashSetSynchronized;
/**
* The class representing the (in-memory) storage for language settings entries {@link ICLanguageSettingEntry}.
@ -39,12 +40,7 @@ public class LanguageSettingsStorage implements Cloneable {
* at the expense of CPU time. WeakHashSet handles garbage collection when a list is not
* referenced anywhere else. See JavaDoc {@link java.lang.ref.WeakReference} about weak reference objects.
*/
private static WeakHashSet<List<ICLanguageSettingEntry>> listPool = new WeakHashSet<List<ICLanguageSettingEntry>>() {
@Override
public synchronized List<ICLanguageSettingEntry> add(List<ICLanguageSettingEntry> list) {
return super.add(list);
}
};
private static WeakHashSet<List<ICLanguageSettingEntry>> listPool = new WeakHashSetSynchronized<List<ICLanguageSettingEntry>>();
/**
* Returns the list of setting entries for the given resource and language.

View file

@ -58,6 +58,7 @@ import org.eclipse.cdt.core.settings.model.extension.CTargetPlatformData;
import org.eclipse.cdt.core.settings.model.extension.impl.CDataFactory;
import org.eclipse.cdt.core.settings.model.extension.impl.CDefaultLanguageData;
import org.eclipse.cdt.internal.core.WeakHashSet;
import org.eclipse.cdt.internal.core.WeakHashSetSynchronized;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
@ -82,12 +83,7 @@ public class CDataUtil {
* at the expense of CPU time. WeakHashSet handles garbage collection when a list is not
* referenced anywhere else. See JavaDoc {@link java.lang.ref.WeakReference} about weak reference objects.
*/
private static WeakHashSet<ICSettingEntry> settingEntriesPool = new WeakHashSet<ICSettingEntry>() {
@Override
public synchronized ICSettingEntry add(ICSettingEntry entry) {
return super.add(entry);
}
};
private static WeakHashSet<ICSettingEntry> settingEntriesPool = new WeakHashSetSynchronized<ICSettingEntry>();
public static int genRandomNumber(){
if (randomNumber == null) {

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2012 Andrew Gvozdev 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:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core;
/**
* A synchronized hashset whose values can be garbage collected.
*/
public class WeakHashSetSynchronized<T> extends WeakHashSet<T> {
/**
* Constructor.
*/
public WeakHashSetSynchronized() {
super(5);
}
/**
* Constructor.
*
* @param size - initial capacity.
*/
public WeakHashSetSynchronized(int size) {
super(size);
}
@Override
synchronized public T add(T obj) {
return super.add(obj);
}
@Override
synchronized public T get(T obj) {
return super.get(obj);
}
@Override
synchronized public T remove(T obj) {
return super.remove(obj);
}
}