summaryrefslogtreecommitdiff
path: root/src/library/scala/Symbol.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-05-08 22:02:14 +0000
committerPaul Phillips <paulp@improving.org>2009-05-08 22:02:14 +0000
commit974735b01f3c08d9fef02b8ab5f086d2d689a590 (patch)
treea245e72d2e006a43d102f1d1b57e95e02ff69621 /src/library/scala/Symbol.scala
parent8b030ca4844d6a0ad67f4b47f416a7af59bddea2 (diff)
downloadscala-974735b01f3c08d9fef02b8ab5f086d2d689a590.tar.gz
scala-974735b01f3c08d9fef02b8ab5f086d2d689a590.tar.bz2
scala-974735b01f3c08d9fef02b8ab5f086d2d689a590.zip
Explicit locking on Symbol creation so multiple...
Explicit locking on Symbol creation so multiple readers don't have to block up on synchronize. Closes bug #1307.
Diffstat (limited to 'src/library/scala/Symbol.scala')
-rw-r--r--src/library/scala/Symbol.scala84
1 files changed, 49 insertions, 35 deletions
diff --git a/src/library/scala/Symbol.scala b/src/library/scala/Symbol.scala
index becb37bc96..610cc839c3 100644
--- a/src/library/scala/Symbol.scala
+++ b/src/library/scala/Symbol.scala
@@ -11,13 +11,6 @@
package scala
-// jcl disabled for now; go directly to java collections.
-//import scala.collection.jcl
-
-//private[scala] object internedSymbols extends jcl.WeakHashMap[String, ref.WeakReference[Symbol]]
-private[scala] object internedSymbols
- extends java.util.WeakHashMap[String, java.lang.ref.WeakReference[Symbol]]
-
/** <p>
* This class provides a simple way to get unique objects for
* equal strings. Since symbols are interned, they can be compared using
@@ -37,7 +30,6 @@ private[scala] object internedSymbols
*/
@serializable
final class Symbol private (val name: String) {
-
/** Converts this symbol to a string.
*/
override def toString(): String = "'" + name
@@ -46,34 +38,56 @@ final class Symbol private (val name: String) {
private def readResolve(): Any = Symbol.apply(name)
}
-object Symbol {
+object Symbol extends UniquenessCache[String, Symbol]
+{
+ protected def valueFromKey(name: String): Symbol = new Symbol(name)
+ protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name)
+}
- /** <p>
- * Makes this symbol into a unique reference.
- * </p>
- * <p>
- * If two interened symbols are equal (i.e. they have the same name)
- * then they must be identical (wrt reference equality).
- * </p>
- *
- * @return the unique reference to this string.
- */
- def apply(name: String): Symbol = internedSymbols.synchronized {
-// internedSymbols.get(name).flatMap(_.get) match {
-// case Some(sym) => sym
-// case _ =>
-// val sym = new Symbol(name)
-// internedSymbols(name) = new ref.WeakReference(sym)
-// sym
- var sym: Symbol = null
- val ref = internedSymbols.get(name)
- if (ref != null) sym = ref.get
- if (sym == null) {
- sym = new Symbol(name)
- internedSymbols.put(name, new java.lang.ref.WeakReference(sym))
+/** This is private so it won't appear in the library API, but
+ * abstracted to offer some hope of reusability. */
+private[scala] abstract class UniquenessCache[K, V >: Null]
+{
+ import java.lang.ref.{ ReferenceQueue, WeakReference }
+ import java.util.WeakHashMap
+ import java.util.concurrent.locks.ReentrantReadWriteLock
+
+ private val queue = new ReferenceQueue[V]
+ private val rwl = new ReentrantReadWriteLock()
+ private val rlock = rwl.readLock
+ private val wlock = rwl.writeLock
+ private val map = new WeakHashMap[K, WeakReference[V]]
+
+ protected def valueFromKey(k: K): V
+ protected def keyFromValue(v: V): Option[K]
+
+ def apply(name: K): V = {
+ def cached(): V = {
+ rlock.lock
+ try {
+ val reference = map get name
+ if (reference == null) null
+ else reference.get // will be null if we were gc-ed
+ }
+ finally rlock.unlock
+ }
+ def updateCache(): V = {
+ wlock.lock
+ try {
+ val res = cached()
+ if (res != null) res
+ else {
+ val sym = valueFromKey(name)
+ map.put(name, new WeakReference(sym, queue))
+ sym
+ }
+ }
+ finally wlock.unlock
}
- sym
- }
- def unapply(other: Symbol): Option[String] = Some(other.name)
+ val res = cached()
+ if (res == null) updateCache()
+ else res
+ }
+ def unapply(other: V): Option[K] = keyFromValue(other)
}