summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2010-07-19 13:56:03 +0000
committerMartin Odersky <odersky@gmail.com>2010-07-19 13:56:03 +0000
commit9c365348fd4e0e40b6499f2abf1b1057735296f6 (patch)
treef41c23a921c28c916eee665194b1542e59514d6a
parenta6bb10a310b2d10cfd2713b9d8ca5c21af73902d (diff)
downloadscala-9c365348fd4e0e40b6499f2abf1b1057735296f6.tar.gz
scala-9c365348fd4e0e40b6499f2abf1b1057735296f6.tar.bz2
scala-9c365348fd4e0e40b6499f2abf1b1057735296f6.zip
Added `ask` method to compiler control to do fa...
Added `ask` method to compiler control to do fast trunaround computations on presentation compiler thread.
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala3
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala10
-rw-r--r--src/compiler/scala/tools/nsc/util/WorkScheduler.scala30
3 files changed, 34 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index 26f7fb1115..c6106a9865 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -134,6 +134,9 @@ trait CompilerControl { self: Global =>
/** Tell the compile server to shutdown, and do not restart again */
def askShutdown() = scheduler raise ShutdownReq
+ /** 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 CancelActionReq extends ControlThrowable
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 2c174860e4..cb2f4a0340 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -110,10 +110,16 @@ self =>
// ----------------- Polling ---------------------------------------
/** Called from runner thread and signalDone:
- * Poll for exceptions.
- * Poll for work reload/typedTreeAt/doFirst commands during background checking.
+ * Poll for interrupts and execute them immediately.
+ * Then, poll for exceptions and execute them.
+ * Then, poll for work reload/typedTreeAt/doFirst commands during background checking.
*/
def pollForWork() {
+ scheduler.pollInterrupt() match {
+ case Some(ir) =>
+ ir.execute(); pollForWork()
+ case _ =>
+ }
scheduler.pollThrowable() match {
case Some(ex @ CancelActionReq) => if (acting) throw ex
case Some(ex @ FreshRunReq) =>
diff --git a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala
index e309b19b76..5f33ea4aaa 100644
--- a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala
+++ b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala
@@ -9,22 +9,21 @@ class WorkScheduler {
private var todo = new Queue[Action]
private var throwables = new Queue[Throwable]
+ private var interruptReqs = new Queue[InterruptReq]
- /** Called from server: block until todo list is nonempty */
+ /** Called from server: block until one of todo list, throwables or interruptReqs is nonempty */
def waitForMoreWork() = synchronized {
- while (todo.isEmpty) { wait() }
+ while (todo.isEmpty && throwables.isEmpty && interruptReqs.isEmpty) { wait() }
}
- /** called from Server: test whether todo list is nonempty */
+ /** called from Server: test whether one of todo list, throwables, or InterruptReqs is nonempty */
def moreWork(): Boolean = synchronized {
- todo.nonEmpty
+ todo.nonEmpty || throwables.nonEmpty || interruptReqs.nonEmpty
}
/** Called from server: get first action in todo list, and pop it off */
def nextWorkItem(): Option[Action] = synchronized {
- if (!todo.isEmpty) {
- Some(todo.dequeue())
- } else None
+ if (todo.isEmpty) None else Some(todo.dequeue())
}
/** Called from server: return optional exception posted by client
@@ -41,6 +40,22 @@ class WorkScheduler {
}
}
+ def pollInterrupt(): Option[InterruptReq] = synchronized {
+ if (interruptReqs.isEmpty) None else Some(interruptReqs.dequeue())
+ }
+
+ /** Called from client: have interrupt executed by server and return result */
+ def doQuickly[A](op: () => A): A = {
+ val ir = new InterruptReq {
+ type R = A
+ val todo = op
+ }
+ synchronized {
+ interruptReqs enqueue ir
+ }
+ ir.getResult()
+ }
+
/** Called from client: have action executed by server */
def postWorkItem(action: Action) = synchronized {
todo enqueue action
@@ -60,3 +75,4 @@ class WorkScheduler {
postWorkItem { () => }
}
}
+