summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2011-01-10 15:43:55 +0000
committerIulian Dragos <jaguarul@gmail.com>2011-01-10 15:43:55 +0000
commitfe65bb177fb7ceccad2004a7cfd69195b6c3bc3d (patch)
treeb150f52d4ca3d72820a344662fd6deb8036dc2ab /src
parent158e748e44932beb477d5bc69a062a6f738efd91 (diff)
downloadscala-fe65bb177fb7ceccad2004a7cfd69195b6c3bc3d.tar.gz
scala-fe65bb177fb7ceccad2004a7cfd69195b6c3bc3d.tar.bz2
scala-fe65bb177fb7ceccad2004a7cfd69195b6c3bc3d.zip
Moved the presentation compiler thread in its o...
Moved the presentation compiler thread in its own top-level class. This allows to collect the presentation compiler instance when the thread is not GCed, but the compiler should be discarded (for example, after a shutdown request). Having the thread as an inner class keeps a reference to the outer class. review by odersky.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala11
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala47
-rw-r--r--src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala53
3 files changed, 68 insertions, 43 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index 4a4808b28e..16a7b2377a 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -74,7 +74,7 @@ trait CompilerControl { self: Global =>
/** The scheduler by which client and compiler communicate
* Must be initialized before starting compilerRunner
*/
- protected val scheduler = new WorkScheduler
+ protected[interactive] val scheduler = new WorkScheduler
/** The compilation unit corresponding to a source file
* if it does not yet exist creat a new one atomically
@@ -177,9 +177,12 @@ trait CompilerControl { self: Global =>
/** Ask for a computation to be done quickly on the presentation compiler thread */
def ask[A](op: () => A): A = scheduler doQuickly op
+}
// ---------------- Interpreted exceptions -------------------
- object FreshRunReq extends ControlThrowable
- object ShutdownReq extends ControlThrowable
-}
+/** It has to stay top-level so that the PresentationCompilerThread may access it. */
+object FreshRunReq extends ControlThrowable
+
+/** It has to stay top-level so that the PresentationCompilerThread may access it. */
+object ShutdownReq extends ControlThrowable
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 7f8f3385bf..649193cffb 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -71,7 +71,7 @@ self =>
/** Is a background compiler run needed?
* Note: outOfDate is true as long as there is a background compile scheduled or going on.
*/
- private var outOfDate = false
+ protected[interactive] var outOfDate = false
/** Units compiled by a run with id >= minRunId are considered up-to-date */
private[interactive] var minRunId = 1
@@ -269,53 +269,22 @@ self =>
// ----------------- The Background Runner Thread -----------------------
/** The current presentation compiler runner */
- @volatile protected var compileRunner = newRunnerThread
- compileRunner.start()
+ @volatile protected[interactive] var compileRunner = newRunnerThread()
- private var threadId = 1
+ private var threadId = 0
/** Create a new presentation compiler runner.
*/
- def newRunnerThread: Thread = new Thread("Scala Presentation Compiler V"+threadId) {
- override def run() {
- debugLog("starting new runner thread")
- try {
- while (true) {
- logreplay("wait for more work", { scheduler.waitForMoreWork(); true })
- pollForWork(NoPosition)
- debugLog("got more work")
- while (outOfDate) {
- try {
- backgroundCompile()
- outOfDate = false
- } catch {
- case FreshRunReq =>
- }
- log.flush()
- }
- }
- } catch {
- case ex @ ShutdownReq =>
- debugLog("exiting presentation compiler")
- log.close()
- case ex =>
- log.flush()
- outOfDate = false
- compileRunner = newRunnerThread
- compileRunner.start()
- ex match {
- case FreshRunReq => // This shouldn't be reported
- case _ : ValidateException => // This will have been reported elsewhere
- case _ => ex.printStackTrace(); informIDE("Fatal Error: "+ex)
- }
- }
- }
+ def newRunnerThread(): Thread = {
threadId += 1
+ compileRunner = new PresentationCompilerThread(this, threadId)
+ compileRunner.start()
+ compileRunner
}
/** Compile all loaded source files in the order given by `allSources`.
*/
- private def backgroundCompile() {
+ protected[interactive] def backgroundCompile() {
informIDE("Starting new presentation compiler type checking pass")
reporter.reset()
// remove any files in first that are no longer maintained by presentation compiler (i.e. closed)
diff --git a/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala b/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
new file mode 100644
index 0000000000..499f0712b0
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/interactive/PresentationCompilerThread.scala
@@ -0,0 +1,53 @@
+package scala.tools.nsc.interactive
+
+/** A presentation compiler thread. This is a lightweight class, delegating most
+ * of its functionality to the compiler instance.
+ *
+ * @note This thread class may not be GCd, so it's important not to keep around
+ * large objects. For instance, the JDT weaving framework keeps threads around
+ * in a map, preventing them from being GCd. This prompted the separation between
+ * interactive.Global and this class.
+ */
+class PresentationCompilerThread(var compiler: Global, threadId: Int) extends Thread("Scala Presentation Compiler V"+threadId) {
+ /** The presentation compiler loop.
+ */
+ override def run() {
+ compiler.debugLog("starting new runner thread")
+ try {
+ while (true) {
+ compiler.log.logreplay("wait for more work", { compiler.scheduler.waitForMoreWork(); true })
+ compiler.pollForWork(compiler.NoPosition)
+ compiler.debugLog("got more work")
+ while (compiler.outOfDate) {
+ try {
+ compiler.backgroundCompile()
+ compiler.outOfDate = false
+ } catch {
+ case FreshRunReq =>
+ }
+ compiler.log.flush()
+ }
+ }
+ } catch {
+ case ex @ ShutdownReq =>
+ compiler.debugLog("exiting presentation compiler")
+ compiler.log.close()
+
+ // make sure we don't keep around stale instances
+ compiler = null
+ case ex =>
+ compiler.log.flush()
+ compiler.outOfDate = false
+ compiler.newRunnerThread()
+
+ ex match {
+ case FreshRunReq => // This shouldn't be reported
+ case _ : Global#ValidateException => // This will have been reported elsewhere
+ case _ => ex.printStackTrace(); compiler.informIDE("Fatal Error: "+ex)
+ }
+
+ // make sure we don't keep around stale instances
+ compiler = null
+ }
+ }
+} \ No newline at end of file