summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2012-07-24 13:54:44 -0700
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-07-24 13:54:44 -0700
commit392438b77ea4961c919e3115055336ce6fca85af (patch)
tree5cf454936989e2c9a7122bd9ceb9cdd254cfc61f
parent5d44a0d2cf40aa9905fbee87c701891d69afc39f (diff)
parent2eff6601dac2b19c3898e46999b0ab1523ff0c0c (diff)
downloadscala-392438b77ea4961c919e3115055336ce6fca85af.tar.gz
scala-392438b77ea4961c919e3115055336ce6fca85af.tar.bz2
scala-392438b77ea4961c919e3115055336ce6fca85af.zip
Merge pull request #984 from scalamacros/ticket/6058
SI-6058 makes JavaMirror caches weak
-rw-r--r--src/reflect/scala/reflect/runtime/TwoWayCache.scala36
1 files changed, 25 insertions, 11 deletions
diff --git a/src/reflect/scala/reflect/runtime/TwoWayCache.scala b/src/reflect/scala/reflect/runtime/TwoWayCache.scala
index c7bfb3435d..f47d59e411 100644
--- a/src/reflect/scala/reflect/runtime/TwoWayCache.scala
+++ b/src/reflect/scala/reflect/runtime/TwoWayCache.scala
@@ -1,27 +1,40 @@
package scala.reflect
package runtime
+import collection.mutable.WeakHashMap
+import java.lang.ref.WeakReference
+
/** A cache that maintains a bijection between Java reflection type `J`
* and Scala reflection type `S`.
+ *
+ * The cache is two-way weak (i.e. is powered by weak references),
+ * so that neither Java artifacts prevent Scala artifacts from being garbage collected,
+ * nor the other way around.
*/
-import collection.mutable.HashMap
-
private[runtime] class TwoWayCache[J, S] {
- private val toScalaMap = new HashMap[J, S]
- private val toJavaMap = new HashMap[S, J]
+ private val toScalaMap = new WeakHashMap[J, WeakReference[S]]
+ private val toJavaMap = new WeakHashMap[S, WeakReference[J]]
def enter(j: J, s: S) = synchronized {
// debugInfo("cached: "+j+"/"+s)
- toScalaMap(j) = s
- toJavaMap(s) = j
+ toScalaMap(j) = new WeakReference(s)
+ toJavaMap(s) = new WeakReference(j)
+ }
+
+ private object SomeRef {
+ def unapply[T](optRef: Option[WeakReference[T]]): Option[T] =
+ if (optRef.nonEmpty) {
+ val result = optRef.get.get
+ if (result != null) Some(result) else None
+ } else None
}
def toScala(key: J)(body: => S): S = synchronized {
toScalaMap get key match {
- case Some(v) =>
+ case SomeRef(v) =>
v
- case none =>
+ case None =>
val result = body
enter(key, result)
result
@@ -30,9 +43,9 @@ private[runtime] class TwoWayCache[J, S] {
def toJava(key: S)(body: => J): J = synchronized {
toJavaMap get key match {
- case Some(v) =>
+ case SomeRef(v) =>
v
- case none =>
+ case None =>
val result = body
enter(result, key)
result
@@ -41,11 +54,12 @@ private[runtime] class TwoWayCache[J, S] {
def toJavaOption(key: S)(body: => Option[J]): Option[J] = synchronized {
toJavaMap get key match {
+ case SomeRef(v) =>
+ Some(v)
case None =>
val result = body
for (value <- result) enter(value, key)
result
- case some => some
}
}
}