summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphaller <hallerp@gmail.com>2012-07-20 16:29:37 +0200
committerphaller <hallerp@gmail.com>2012-07-20 16:32:12 +0200
commitddd5f3aa8f080328e98f656fd5f5d2946b5aa77f (patch)
tree8b53ea9a460f3f9d27567096e2c515e7c836ac06
parent952cb61108faf1a68e58ee95460e9b3bcad40ea8 (diff)
downloadscala-ddd5f3aa8f080328e98f656fd5f5d2946b5aa77f.tar.gz
scala-ddd5f3aa8f080328e98f656fd5f5d2946b5aa77f.tar.bz2
scala-ddd5f3aa8f080328e98f656fd5f5d2946b5aa77f.zip
SIP-14 - Fix critical Java compatibility issue in scala.concurrent.Await
Patch contributed by @viktorklang
-rw-r--r--src/library/scala/concurrent/package.scala78
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala11
2 files changed, 52 insertions, 37 deletions
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index a6488b602f..a2ef42fac8 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -18,41 +18,6 @@ package object concurrent {
type CancellationException = java.util.concurrent.CancellationException
type TimeoutException = java.util.concurrent.TimeoutException
- @implicitNotFound("Don't call `Awaitable` methods directly, use the `Await` object.")
- sealed trait CanAwait
- private implicit object AwaitPermission extends CanAwait
-
- /**
- * `Await` is what is used to ensure proper handling of blocking for `Awaitable` instances.
- */
- object Await {
- /**
- * 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(classOf[TimeoutException])
- def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type =
- blocking(awaitable.ready(atMost))
-
- /**
- * 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(classOf[Exception])
- def result[T](awaitable: Awaitable[T], atMost: Duration): T =
- blocking(awaitable.result(atMost))
- }
-
/** Starts an asynchronous computation and returns a `Future` object with the result of that computation.
*
* The result becomes available once the asynchronous computation is completed.
@@ -85,5 +50,46 @@ package object concurrent {
* - TimeoutException - in the case that the blockable object timed out
*/
@throws(classOf[Exception])
- def blocking[T](body: =>T): T = BlockContext.current.blockOn(body)
+ def blocking[T](body: =>T): T = BlockContext.current.blockOn(body)(scala.concurrent.AwaitPermission)
+}
+
+package concurrent {
+ @implicitNotFound("Don't call `Awaitable` methods directly, use the `Await` object.")
+ sealed trait CanAwait
+
+ /**
+ * Internal usage only, implementation detail.
+ */
+ private[concurrent] object AwaitPermission extends CanAwait
+
+ /**
+ * `Await` is what is used to ensure proper handling of blocking for `Awaitable` instances.
+ */
+ object Await {
+ /**
+ * 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(classOf[TimeoutException])
+ def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type =
+ blocking(awaitable.ready(atMost)(AwaitPermission))
+
+ /**
+ * 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(classOf[Exception])
+ def result[T](awaitable: Awaitable[T], atMost: Duration): T =
+ blocking(awaitable.result(atMost)(AwaitPermission))
+ }
}
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index 1209b710b0..43d4c9dc71 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -700,9 +700,18 @@ trait Blocking extends TestBase {
}
}
+ def testFQCNForAwaitAPI(): Unit = once {
+ done =>
+
+ assert(classOf[CanAwait].getName == "scala.concurrent.CanAwait")
+ assert(Await.getClass.getName == "scala.concurrent.Await")
+
+ done()
+ }
+
testAwaitSuccess()
testAwaitFailure()
-
+ testFQCNForAwaitAPI()
}
trait BlockContexts extends TestBase {