diff options
author | Roland <rk@rkuhn.info> | 2012-09-11 17:58:35 +0200 |
---|---|---|
committer | Roland <rk@rkuhn.info> | 2012-09-11 17:58:35 +0200 |
commit | ad6c261eafbe72e014d005d0452c8a628a07f123 (patch) | |
tree | 9d96d5c18f44ea1bb6305d8b689019864f90a3b4 /src/library | |
parent | 3767a6a83efc74d34e9025f798eeb2a043e6df8d (diff) | |
download | scala-ad6c261eafbe72e014d005d0452c8a628a07f123.tar.gz scala-ad6c261eafbe72e014d005d0452c8a628a07f123.tar.bz2 scala-ad6c261eafbe72e014d005d0452c8a628a07f123.zip |
improve docs and Promise impl
- scaladoc the exceptions thrown by Await.* and Awaitable.*
- move intercept[Exception] into partest’s TestUtil object
- improve Promise.tryAwait implementation following Viktor’s comments
and make use of Deadline to avoid calling System.nanoTime too often
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/concurrent/Awaitable.scala | 22 | ||||
-rw-r--r-- | src/library/scala/concurrent/impl/Promise.scala | 30 | ||||
-rw-r--r-- | src/library/scala/concurrent/package.scala | 34 |
3 files changed, 53 insertions, 33 deletions
diff --git a/src/library/scala/concurrent/Awaitable.scala b/src/library/scala/concurrent/Awaitable.scala index 2205dd9869..655115349a 100644 --- a/src/library/scala/concurrent/Awaitable.scala +++ b/src/library/scala/concurrent/Awaitable.scala @@ -16,20 +16,34 @@ import scala.concurrent.util.Duration trait Awaitable[+T] { /** - * Should throw [[scala.concurrent.TimeoutException]] if it times out + * Await the "resolved" state of this Awaitable. * This method should not be called directly. * - * @throws InterruptedException if the wait call was interrupted + * @param atMost + * maximum wait time, which may be negative (no waiting is done), + * [[Duration.Inf]] for unbounded waiting, or a finite positive + * duration + * @return the Awaitable itself + * @throws InterruptedException if the wait call was interrupted + * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready + * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]] */ @throws(classOf[TimeoutException]) @throws(classOf[InterruptedException]) def ready(atMost: Duration)(implicit permit: CanAwait): this.type /** - * Throws exceptions if it cannot produce a T within the specified time. + * Await and return the result of this Awaitable, which is either of type T or a thrown exception (any Throwable). * This method should not be called directly. * - * @throws InterruptedException if the wait call was interrupted + * @param atMost + * maximum wait time, which may be negative (no waiting is done), + * [[Duration.Inf]] for unbounded waiting, or a finite positive + * duration + * @return the value if the Awaitable was successful within the specific maximum wait time + * @throws InterruptedException if the wait call was interrupted + * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready + * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]] */ @throws(classOf[Exception]) def result(atMost: Duration)(implicit permit: CanAwait): T diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index 35aac974ec..f7ab85dc0c 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -12,7 +12,7 @@ package scala.concurrent.impl import java.util.concurrent.TimeUnit.NANOSECONDS import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException } -import scala.concurrent.util.Duration +import scala.concurrent.util.{ Duration, Deadline } import scala.annotation.tailrec import scala.util.control.NonFatal import scala.util.{ Try, Success, Failure } @@ -64,16 +64,14 @@ private[concurrent] object Promise { protected final def tryAwait(atMost: Duration): Boolean = { @tailrec - def awaitUnsafe(waitTimeNanos: Long): Boolean = { - if (!isCompleted && waitTimeNanos > 0) { - val ms = NANOSECONDS.toMillis(waitTimeNanos) - val ns = (waitTimeNanos % 1000000l).toInt // as per object.wait spec - val start = System.nanoTime() - synchronized { - if (!isCompleted) wait(ms, ns) // previously - this was a `while`, ending up in an infinite loop - } + def awaitUnsafe(deadline: Deadline, nextWait: Duration): Boolean = { + if (!isCompleted && nextWait > Duration.Zero) { + val ms = nextWait.toMillis + val ns = (nextWait.toNanos % 1000000l).toInt // as per object.wait spec + + synchronized { if (!isCompleted) wait(ms, ns) } - awaitUnsafe(waitTimeNanos - (System.nanoTime() - start)) + awaitUnsafe(deadline, deadline.timeLeft) } else isCompleted } @@ -81,21 +79,19 @@ private[concurrent] object Promise { def awaitUnbounded(): Boolean = { if (isCompleted) true else { - synchronized { - if (!isCompleted) wait() - } + synchronized { if (!isCompleted) wait() } awaitUnbounded() } } - if (atMost <= Duration.Zero) - isCompleted - else if (atMost eq Duration.Undefined) + if (atMost eq Duration.Undefined) throw new IllegalArgumentException("cannot wait for Undefined period") + else if (atMost <= Duration.Zero) + isCompleted else if (atMost == Duration.Inf) awaitUnbounded() else - awaitUnsafe(atMost.toNanos) + awaitUnsafe(atMost.fromNow, atMost) } @throws(classOf[TimeoutException]) diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index 3681109653..1d06341d4d 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -67,14 +67,19 @@ package concurrent { */ object Await { /** + * Await the "resolved" state of this Awaitable. * Invokes ready() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`. - * ready() blocks until the awaitable has completed or the timeout expires. * - * Throws a TimeoutException if the timeout expires, as that is in the contract of `Awaitable.ready`. - * @param awaitable the `Awaitable` on which `ready` is to be called - * @param atMost the maximum timeout for which to wait - * @return the result of `awaitable.ready` which is defined to be the awaitable itself. - * @throws InterruptedException if the wait call was interrupted + * @param awaitable + * the `Awaitable` on which `ready` is to be called + * @param atMost + * maximum wait time, which may be negative (no waiting is done), + * [[Duration.Inf]] for unbounded waiting, or a finite positive + * duration + * @return the awaitable itself + * @throws InterruptedException if the wait call was interrupted + * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready + * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]] */ @throws(classOf[TimeoutException]) @throws(classOf[InterruptedException]) @@ -82,14 +87,19 @@ package concurrent { blocking(awaitable.ready(atMost)(AwaitPermission)) /** + * Await and return the result of this Awaitable, which is either of type T or a thrown exception (any Throwable). * Invokes result() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`. - * result() blocks until the awaitable has completed or the timeout expires. * - * Throws a TimeoutException if the timeout expires, or any exception thrown by `Awaitable.result`. - * @param awaitable the `Awaitable` on which `result` is to be called - * @param atMost the maximum timeout for which to wait - * @return the result of `awaitable.result` - * @throws InterruptedException if the wait call was interrupted + * @param awaitable + * the `Awaitable` on which `result` is to be called + * @param atMost + * maximum wait time, which may be negative (no waiting is done), + * [[Duration.Inf]] for unbounded waiting, or a finite positive + * duration + * @return the value if the Awaitable was successful within the specific maximum wait time + * @throws InterruptedException if the wait call was interrupted + * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready + * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]] */ @throws(classOf[Exception]) def result[T](awaitable: Awaitable[T], atMost: Duration): T = |