diff options
author | Martin Odersky <odersky@gmail.com> | 2012-07-25 15:58:45 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2012-07-27 17:04:36 +0200 |
commit | e896c0ab2d36740207f91086262e9feb4fc1c32d (patch) | |
tree | a5bd5892b7a0cdcd1f5353757af640f2da7919b9 | |
parent | 50903959efc2dcc4093f3d7c0b4b9b9def51cc04 (diff) | |
download | scala-e896c0ab2d36740207f91086262e9feb4fc1c32d.tar.gz scala-e896c0ab2d36740207f91086262e9feb4fc1c32d.tar.bz2 scala-e896c0ab2d36740207f91086262e9feb4fc1c32d.zip |
Adds method askForResponse
Adds method askForResponse which returns a response immediately instead of waiting for a result. That way, one can wait for an ask's result using a timeout.
3 files changed, 31 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index 801b4ad22b..aab1c8fb7e 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -252,6 +252,19 @@ trait CompilerControl { self: Global => /** Asks for a computation to be done quickly on the presentation compiler thread */ def ask[A](op: () => A): A = if (self.onCompilerThread) op() else scheduler doQuickly op + /** Asks for a computation to be done on presentation compiler thread, returning + * a response with the result or an exception + */ + def askForResponse[A](op: () => A): Response[A] = { + val r = new Response[A] + val ir = scheduler askDoQuickly op + ir onComplete { + case Left(result) => r set result + case Right(exc) => r raise exc + } + r + } + def onCompilerThread = Thread.currentThread == compileRunner /** Info given for every member found by completion @@ -390,7 +403,7 @@ trait CompilerControl { self: Global => case _ => println("don't know what to do with this " + action.getClass) } } - + override def doQuickly[A](op: () => A): A = { throw new FailedInterrupt(new Exception("Posted a work item to a compiler that's shutting down")) } diff --git a/src/compiler/scala/tools/nsc/util/InterruptReq.scala b/src/compiler/scala/tools/nsc/util/InterruptReq.scala index 61aaa1bdcb..816d16f767 100644 --- a/src/compiler/scala/tools/nsc/util/InterruptReq.scala +++ b/src/compiler/scala/tools/nsc/util/InterruptReq.scala @@ -2,6 +2,7 @@ package scala.tools.nsc package util /** A class of work items to be used in interrupt requests. + * Todo: we should replace the Eithers by Futures or Try's. */ abstract class InterruptReq { /** The result type of the operation @@ -11,9 +12,14 @@ abstract class InterruptReq { /** The operation to be performed */ protected val todo: () => R + type Continuation = Either[R, Throwable] => Unit + /** The result provided */ private var result: Option[Either[R, Throwable]] = None + /** The continuations waiting asynchronously on a provided result */ + private var waiting: List[Continuation] = Nil + /** To be called from interrupted server to execute demanded task */ def execute(): Unit = synchronized { try { @@ -22,6 +28,7 @@ abstract class InterruptReq { case t: Throwable => result = Some(Right(t)) } finally { notify() + for (k <- waiting.reverse) k(result.get) } } @@ -38,6 +45,10 @@ abstract class InterruptReq { case Right(t) => throw new FailedInterrupt(t) } } + + def onComplete(k: Continuation) = synchronized { + waiting = k :: waiting + } } class FailedInterrupt(cause: Throwable) extends Exception("Compiler exception during call to 'ask'", cause) diff --git a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala index 8c037cbda5..b1f4696d3e 100644 --- a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala +++ b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala @@ -54,6 +54,11 @@ class WorkScheduler { /** Called from client: have interrupt executed by server and return result */ def doQuickly[A](op: () => A): A = { + val ir = askDoQuickly(op) + ir.getResult() + } + + def askDoQuickly[A](op: () => A): InterruptReq { type R = A } = { val ir = new InterruptReq { type R = A val todo = op @@ -62,7 +67,7 @@ class WorkScheduler { interruptReqs enqueue ir notify() } - ir.getResult() + ir } /** Called from client: have action executed by server */ |