summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2010-07-16 08:40:53 -0400
committerRich Hickey <richhickey@gmail.com>2010-07-16 08:45:30 -0400
commit02559a4aad442253b601870f7c9aa04c91baf235 (patch)
treec3c5ce423f8b91e5fd909b4c3b7f646a5f87af1d
parentda14cbb99fd5a3ccb4092fe629822a86065e6fb9 (diff)
use soft refs for keyword intern table
-rw-r--r--src/jvm/clojure/lang/Keyword.java16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/jvm/clojure/lang/Keyword.java b/src/jvm/clojure/lang/Keyword.java
index ac080923..75adcdd7 100644
--- a/src/jvm/clojure/lang/Keyword.java
+++ b/src/jvm/clojure/lang/Keyword.java
@@ -15,18 +15,28 @@ package clojure.lang;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.concurrent.ConcurrentHashMap;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
public final class Keyword implements IFn, Comparable, Named, Serializable {
-private static ConcurrentHashMap<Symbol, Keyword> table = new ConcurrentHashMap();
+private static ConcurrentHashMap<Symbol, SoftReference<Keyword>> table = new ConcurrentHashMap();
+static final ReferenceQueue rq = new ReferenceQueue();
public final Symbol sym;
final int hash;
public static Keyword intern(Symbol sym){
+ Util.clearCache(rq, table);
Keyword k = new Keyword(sym);
- Keyword existingk = table.putIfAbsent(sym, k);
- return existingk == null ? k : existingk;
+ SoftReference<Keyword> existingRef = table.putIfAbsent(sym, new SoftReference<Keyword>(k,rq));
+ if(existingRef == null)
+ return k;
+ Keyword existingk = existingRef.get();
+ if(existingk != null)
+ return existingk;
+ //entry died in the interim, do over
+ return intern(sym);
}
public static Keyword intern(String ns, String name){