aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-03-03 14:35:46 +1000
committerJason Zaugg <jzaugg@gmail.com>2016-03-03 14:35:46 +1000
commitd03f34c3e16dc7a6ddb6a3efa4fca5ee3f989c85 (patch)
treee63defea9ab4f85ddc79bfc75a89205191c5376a /src
parent4395afe0ab7c59f088607d0849abe48b0f83265d (diff)
downloadscala-async-d03f34c3e16dc7a6ddb6a3efa4fca5ee3f989c85.tar.gz
scala-async-d03f34c3e16dc7a6ddb6a3efa4fca5ee3f989c85.tar.bz2
scala-async-d03f34c3e16dc7a6ddb6a3efa4fca5ee3f989c85.zip
Rework extension point for checking for already-completed futures
The current extension point assumes that if a future is in the completed state, a subsequent call to get the already completed value will succeed. While this assumption holds for scala.concurrent.Future, it might not hold for a future system that has semantics like a weak reference. This commit uses a single call `getCompleted` to query the state and get the already completed value. This returns null if the value is not available.
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/scala/async/internal/ExprBuilder.scala15
-rw-r--r--src/main/scala/scala/async/internal/FutureSystem.scala11
-rw-r--r--src/main/scala/scala/async/internal/TransformUtils.scala1
3 files changed, 15 insertions, 12 deletions
diff --git a/src/main/scala/scala/async/internal/ExprBuilder.scala b/src/main/scala/scala/async/internal/ExprBuilder.scala
index 3ef9da5..fe62cd6 100644
--- a/src/main/scala/scala/async/internal/ExprBuilder.scala
+++ b/src/main/scala/scala/async/internal/ExprBuilder.scala
@@ -93,12 +93,15 @@ trait ExprBuilder {
val fun = This(tpnme.EMPTY)
val callOnComplete = futureSystemOps.onComplete[Any, Unit](c.Expr[futureSystem.Fut[Any]](awaitable.expr),
c.Expr[futureSystem.Tryy[Any] => Unit](fun), c.Expr[futureSystem.ExecContext](Ident(name.execContext))).tree
- val tryGetOrCallOnComplete =
- if (futureSystemOps.continueCompletedFutureOnSameThread)
- If(futureSystemOps.isCompleted(c.Expr[futureSystem.Fut[_]](awaitable.expr)).tree,
- adaptToUnit(ifIsFailureTree[T](futureSystemOps.getCompleted[Any](c.Expr[futureSystem.Fut[Any]](awaitable.expr)).tree) :: Nil),
- Block(toList(callOnComplete), Return(literalUnit))) :: Nil
- else
+ val tryGetOrCallOnComplete: List[Tree] =
+ if (futureSystemOps.continueCompletedFutureOnSameThread) {
+ val tempName = name.fresh(name.completed)
+ val initTemp = ValDef(NoMods, tempName, TypeTree(futureSystemOps.tryType[Any]), futureSystemOps.getCompleted[Any](c.Expr[futureSystem.Fut[Any]](awaitable.expr)).tree)
+ val ifTree = If(Apply(Select(Literal(Constant(null)), TermName("ne")), Ident(tempName) :: Nil),
+ adaptToUnit(ifIsFailureTree[T](Ident(tempName)) :: Nil),
+ Block(toList(callOnComplete), Return(literalUnit)))
+ initTemp :: ifTree :: Nil
+ } else
toList(callOnComplete) ::: Return(literalUnit) :: Nil
mkHandlerCase(state, stats ++ List(mkStateTree(onCompleteState, symLookup)) ++ tryGetOrCallOnComplete)
}
diff --git a/src/main/scala/scala/async/internal/FutureSystem.scala b/src/main/scala/scala/async/internal/FutureSystem.scala
index 04adafc..f330cbf 100644
--- a/src/main/scala/scala/async/internal/FutureSystem.scala
+++ b/src/main/scala/scala/async/internal/FutureSystem.scala
@@ -49,8 +49,10 @@ trait FutureSystem {
execContext: Expr[ExecContext]): Expr[Unit]
def continueCompletedFutureOnSameThread = false
- def isCompleted(future: Expr[Fut[_]]): Expr[Boolean] =
- throw new UnsupportedOperationException("isCompleted not supported by this FutureSystem")
+
+ /** Return `null` if this future is not yet completed, or `Tryy[A]` with the completed result
+ * otherwise
+ */
def getCompleted[A: WeakTypeTag](future: Expr[Fut[A]]): Expr[Tryy[A]] =
throw new UnsupportedOperationException("getCompleted not supported by this FutureSystem")
@@ -110,11 +112,8 @@ object ScalaConcurrentFutureSystem extends FutureSystem {
override def continueCompletedFutureOnSameThread: Boolean = true
- override def isCompleted(future: Expr[Fut[_]]): Expr[Boolean] = reify {
- future.splice.isCompleted
- }
override def getCompleted[A: WeakTypeTag](future: Expr[Fut[A]]): Expr[Tryy[A]] = reify {
- future.splice.value.get
+ if (future.splice.isCompleted) future.splice.value.get else null
}
def completeProm[A](prom: Expr[Prom[A]], value: Expr[scala.util.Try[A]]): Expr[Unit] = reify {
diff --git a/src/main/scala/scala/async/internal/TransformUtils.scala b/src/main/scala/scala/async/internal/TransformUtils.scala
index 2999be2..e3a1206 100644
--- a/src/main/scala/scala/async/internal/TransformUtils.scala
+++ b/src/main/scala/scala/async/internal/TransformUtils.scala
@@ -24,6 +24,7 @@ private[async] trait TransformUtils {
val ifRes = "ifres"
val await = "await"
val bindSuffix = "$bind"
+ val completed = newTermName("completed")
val state = newTermName("state")
val result = newTermName("result")