diff options
author | Martin Odersky <odersky@gmail.com> | 2010-09-29 13:42:47 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2010-09-29 13:42:47 +0000 |
commit | 57f2b3d5e06fd2a0238baea8242ac7ba80960891 (patch) | |
tree | 092d7f7df4223e1ab0cc272a5ee58bf91eef737f /src | |
parent | 44ba99aacf2c25dd59eec14506f462546ff0d9e4 (diff) | |
download | scala-57f2b3d5e06fd2a0238baea8242ac7ba80960891.tar.gz scala-57f2b3d5e06fd2a0238baea8242ac7ba80960891.tar.bz2 scala-57f2b3d5e06fd2a0238baea8242ac7ba80960891.zip |
Changed Response so that get does what it did b...
Changed Response so that get does what it did before, and get(TIMEOUT)
returns provisional results if it can. Review by vigdorchick.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/interactive/Response.scala | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/Response.scala b/src/compiler/scala/tools/nsc/interactive/Response.scala index 96e474a34a..56a48e44cd 100644 --- a/src/compiler/scala/tools/nsc/interactive/Response.scala +++ b/src/compiler/scala/tools/nsc/interactive/Response.scala @@ -1,8 +1,6 @@ package scala.tools.nsc package interactive -import scala.concurrent.SyncVar - /** Typical interaction, given a predicate <user-input>, a function <display>, * and an exception handler <handle>: * @@ -19,49 +17,80 @@ import scala.concurrent.SyncVar */ class Response[T] { - private val data = new SyncVar[Either[T, Throwable]] + private var data: Option[Either[T, Throwable]] = None private var complete = false private var cancelled = false /** Set provisional data, more to come */ - def setProvisionally(x: T) = - data.set(Left(x)) + def setProvisionally(x: T) = synchronized { + data = Some(Left(x)) + } - /** Set final data, and mark resposne as complete. + /** Set final data, and mark response as complete. */ - def set(x: T) = data.synchronized { - data.set(Left(x)) + def set(x: T) = synchronized { + data = Some(Left(x)) complete = true + notifyAll() } - def raise(exc: Throwable) = data.synchronized { - data.set(Right(exc)) + /** Store raised exception in data, and mark response as complete. + */ + def raise(exc: Throwable) = synchronized { + data = Some(Right(exc)) complete = true + notifyAll() } - /** Get data, wait as long as necessary + /** Get final data, wait as long as necessary. + * When interrupted will return with Right(InterruptedException) */ - def get: Either[T, Throwable] = data.get + def get: Either[T, Throwable] = synchronized { + while (!complete) { + try { + wait() + } catch { + case exc: InterruptedException => raise(exc) + } + } + data.get + } /** Optionally get data within `timeout` milliseconds. + * When interrupted will return with Some(Right(InterruptedException)) + * When timeout ends, will return last stored provisional result, + * or else None if no provisional result was stored. */ - def get(timeout: Long): Option[Either[T, Throwable]] = data.get(timeout) + def get(timeout: Long): Option[Either[T, Throwable]] = { + val start = System.currentTimeMillis + var current = start + while (!complete && start + timeout > current) { + try { + wait(timeout - (current - start)) + } catch { + case exc: InterruptedException => raise(exc) + } + current = System.currentTimeMillis + } + data + } /** Final data set was stored */ - def isComplete = data.synchronized { complete } + def isComplete = synchronized { complete } - /** Cancel action computing this response + /** Cancel action computing this response (Only the + * party that calls get on a response may cancel). */ - def cancel() = data.synchronized { cancelled = true } + def cancel() = synchronized { cancelled = true } /** A cancel request for this response has been issued */ - def isCancelled = data.synchronized { cancelled } + def isCancelled = synchronized { cancelled } - def clear() = data.synchronized { - data.unset() + def clear() = synchronized { + data = None complete = false cancelled = false } |