/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
/*
* Created on Apr 9, 2006
*/
package org.python.pydev.core;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
/**
* This pool is to be regarded as a way to have less object instances for a given class,
* so, if you have tons of equal strings, you could pass them here and make them be the same
* to save memory. Note that it is created with weak-references for both, the key and the value,
* so, it should be safe to assume that it will be available for garbage collecting once
* no other place has a reference to the same string.
*
* Still, use this with care...
*/
public final class ObjectsPool {
private ObjectsPool() {
}
private static final Map<String, WeakReference<String>> weakHashMap = new WeakHashMap<String, WeakReference<String>>();
public static final Object lock = new Object();
/**
* This is a way to intern a String in the regular heap (instead of the String.intern which uses the perm-gen).
*/
public static String intern(String o) {
if (o == null) {
return null;
}
synchronized (lock) {
WeakReference<String> w = (WeakReference<String>) weakHashMap.get(o);
if (w == null) {
//Yes, the String constructor will do things properly, so, if a big string is actually backed up by the one
//passed, it'll create a new array only with the parts we want.
o = new String(o);
//garbage collected or still not there...
weakHashMap.put(o, new WeakReference<String>(o));
return o;
} else {
final String ret = w.get();
if (ret == null && o != null) {
//garbage collected just in time hum?
o = new String(o);
weakHashMap.put(o, new WeakReference<String>(o));
return o;
} else {
return ret;
}
}
}
}
/**
* Same thing as intern, but the client is responsible for synchronizing on the lock object of this class!
*
* Note that this should be done on a fast process where many objects will be added (but only on fast processes
* that want to avoid synchronizing at each step).
*/
public static String internUnsynched(String o) {
if (o == null) {
return null;
}
WeakReference<String> w = (WeakReference<String>) weakHashMap.get(o);
if (w == null) {
//Yes, the String constructor will do things properly, so, if a big string is actually backed up by the one
//passed, it'll create a new array only with the parts we want.
o = new String(o);
//garbage collected or still not there...
weakHashMap.put(o, new WeakReference<String>(o));
return o;
} else {
final String ret = w.get();
if (ret == null && o != null) {
//garbage collected just in time hum?
o = new String(o);
weakHashMap.put(o, new WeakReference<String>(o));
return o;
} else {
return ret;
}
}
}
/**
* Class used to store items interned locally in a map (without weak references)
*/
public static final class ObjectsPoolMap extends HashMap<String, String> {
private static final long serialVersionUID = 1L;
}
/**
* Makes an intern unsynched and without weak-references in the passed map.
* Use when creating strings in objects that generate strings and when the map with
* the strings will be garbage-collected.
*
* This is a balance from the regular intern which uses weak references and is global to
* a local one that is faster (unsynched and doesn't use weak references).
*/
public static String internLocal(ObjectsPoolMap mapWithInternedStrings, String string) {
String existing = mapWithInternedStrings.get(string);
if (existing != null) {
return existing;
}
mapWithInternedStrings.put(string, string);
return string;
}
}