summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-01-25 15:04:53 +0100
committerMartin Odersky <odersky@gmail.com>2012-01-25 15:04:53 +0100
commitc749710859d32252291802d55d48abe518ddd118 (patch)
treefef90dd9afa4c595b533cb137d27c64b66cb2ce6 /src/compiler/scala/reflect/runtime/SynchronizedTypes.scala
parent65a1e8bd2dbd796bedc0232615cfc3caf18fd4b3 (diff)
downloadscala-c749710859d32252291802d55d48abe518ddd118.tar.gz
scala-c749710859d32252291802d55d48abe518ddd118.tar.bz2
scala-c749710859d32252291802d55d48abe518ddd118.zip
Making reflection thread-safe.
The idea is that all operations that need to be synchronized are overriden in classes reflect.runtime.Synchronized*. Sometimes this applies to operations defined in SymbolTable, which can be directly overridden. Sometimes it is more convenient to generate SynchronizedClazz subclasses of SymbolTable classes Clazz. In the latter case, all instance creation must go over factory methods that can be overridden in the Synchronized traits.
Diffstat (limited to 'src/compiler/scala/reflect/runtime/SynchronizedTypes.scala')
-rw-r--r--src/compiler/scala/reflect/runtime/SynchronizedTypes.scala87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala b/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala
new file mode 100644
index 0000000000..c842d3dd01
--- /dev/null
+++ b/src/compiler/scala/reflect/runtime/SynchronizedTypes.scala
@@ -0,0 +1,87 @@
+package scala.reflect
+package runtime
+
+/** This trait overrides methods in reflect.internal, bracketing
+ * them in synchronized { ... } to make them thread-safe
+ */
+trait SynchronizedTypes extends internal.Types { self: SymbolTable =>
+
+ // No sharing of map objects:
+ override protected def commonOwnerMap = new CommonOwnerMap
+
+ private val uniqueLock = new Object
+ override def unique[T <: Type](tp: T): T = uniqueLock.synchronized { super.unique(tp) }
+
+ class SynchronizedUndoLog extends UndoLog {
+
+ override def clear() =
+ synchronized { super.clear() }
+
+ override def undo[T](block: => T): T =
+ synchronized { super.undo(block) }
+
+ override def undoUnless(block: => Boolean): Boolean =
+ synchronized { super.undoUnless(block) }
+ }
+
+ override protected def newUndoLog = new SynchronizedUndoLog
+
+ override protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) =
+ synchronized { super.baseTypeOfNonClassTypeRef(tpe, clazz) }
+
+ private val subsametypeLock = new Object
+
+ override def isSameType(tp1: Type, tp2: Type): Boolean =
+ subsametypeLock.synchronized { super.isSameType(tp1, tp2) }
+
+ override def isDifferentType(tp1: Type, tp2: Type): Boolean =
+ subsametypeLock.synchronized { super.isDifferentType(tp1, tp2) }
+
+ override def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean =
+ subsametypeLock.synchronized { super.isSubType(tp1, tp2, depth) }
+
+ private val lubglbLock = new Object
+
+ override def glb(ts: List[Type]): Type =
+ lubglbLock.synchronized { super.glb(ts) }
+
+ override def lub(ts: List[Type]): Type =
+ lubglbLock.synchronized { super.lub(ts) }
+
+ private val indentLock = new Object
+
+ override protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = {
+ indentLock.synchronized { super.explain(op, p, tp1, arg2) }
+ }
+
+ private val toStringLock = new Object
+
+ override protected def typeToString(tpe: Type): String =
+ toStringLock.synchronized(super.typeToString(tpe))
+
+ /* The idea of caches is as follows.
+ * When in reflexive mode, a cache is either null, or one sentinal
+ * value representing undefined or the final defined
+ * value. Hence, we can ask in non-synchronized ode whether the cache field
+ * is non null and different from the sentinel (if a sentinel exists).
+ * If that's true, the cache value is current.
+ * Otherwise we arrive in one of the defined... methods listed below
+ * which go through all steps in synchronized mode.
+ */
+
+ override protected def defineUnderlyingOfSingleType(tpe: SingleType) =
+ tpe.synchronized { super.defineUnderlyingOfSingleType(tpe) }
+
+ override protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) =
+ tpe.synchronized { super.defineBaseTypeSeqOfCompoundType(tpe) }
+
+ override protected def defineBaseClassesOfCompoundType(tpe: CompoundType) =
+ tpe.synchronized { super.defineBaseClassesOfCompoundType(tpe) }
+
+ override protected def defineParentsOfTypeRef(tpe: TypeRef) =
+ tpe.synchronized { super.defineParentsOfTypeRef(tpe) }
+
+ override protected def defineBaseTypeSeqOfTypeRef(tpe: TypeRef) =
+ tpe.synchronized { super.defineBaseTypeSeqOfTypeRef(tpe) }
+
+} \ No newline at end of file