From 9c365348fd4e0e40b6499f2abf1b1057735296f6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 19 Jul 2010 13:56:03 +0000 Subject: Added `ask` method to compiler control to do fa... Added `ask` method to compiler control to do fast trunaround computations on presentation compiler thread. --- .../tools/nsc/interactive/CompilerControl.scala | 3 +++ .../scala/tools/nsc/interactive/Global.scala | 10 ++++++-- .../scala/tools/nsc/util/WorkScheduler.scala | 30 +++++++++++++++++----- 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 { () => } } } + -- cgit v1.2.3