Skip to content

Commit d03f34c

Browse files
committed
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.
1 parent 4395afe commit d03f34c

File tree

3 files changed

+15
-12
lines changed

3 files changed

+15
-12
lines changed

src/main/scala/scala/async/internal/ExprBuilder.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,15 @@ trait ExprBuilder {
9393
val fun = This(tpnme.EMPTY)
9494
val callOnComplete = futureSystemOps.onComplete[Any, Unit](c.Expr[futureSystem.Fut[Any]](awaitable.expr),
9595
c.Expr[futureSystem.Tryy[Any] => Unit](fun), c.Expr[futureSystem.ExecContext](Ident(name.execContext))).tree
96-
val tryGetOrCallOnComplete =
97-
if (futureSystemOps.continueCompletedFutureOnSameThread)
98-
If(futureSystemOps.isCompleted(c.Expr[futureSystem.Fut[_]](awaitable.expr)).tree,
99-
adaptToUnit(ifIsFailureTree[T](futureSystemOps.getCompleted[Any](c.Expr[futureSystem.Fut[Any]](awaitable.expr)).tree) :: Nil),
100-
Block(toList(callOnComplete), Return(literalUnit))) :: Nil
101-
else
96+
val tryGetOrCallOnComplete: List[Tree] =
97+
if (futureSystemOps.continueCompletedFutureOnSameThread) {
98+
val tempName = name.fresh(name.completed)
99+
val initTemp = ValDef(NoMods, tempName, TypeTree(futureSystemOps.tryType[Any]), futureSystemOps.getCompleted[Any](c.Expr[futureSystem.Fut[Any]](awaitable.expr)).tree)
100+
val ifTree = If(Apply(Select(Literal(Constant(null)), TermName("ne")), Ident(tempName) :: Nil),
101+
adaptToUnit(ifIsFailureTree[T](Ident(tempName)) :: Nil),
102+
Block(toList(callOnComplete), Return(literalUnit)))
103+
initTemp :: ifTree :: Nil
104+
} else
102105
toList(callOnComplete) ::: Return(literalUnit) :: Nil
103106
mkHandlerCase(state, stats ++ List(mkStateTree(onCompleteState, symLookup)) ++ tryGetOrCallOnComplete)
104107
}

src/main/scala/scala/async/internal/FutureSystem.scala

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,10 @@ trait FutureSystem {
4949
execContext: Expr[ExecContext]): Expr[Unit]
5050

5151
def continueCompletedFutureOnSameThread = false
52-
def isCompleted(future: Expr[Fut[_]]): Expr[Boolean] =
53-
throw new UnsupportedOperationException("isCompleted not supported by this FutureSystem")
52+
53+
/** Return `null` if this future is not yet completed, or `Tryy[A]` with the completed result
54+
* otherwise
55+
*/
5456
def getCompleted[A: WeakTypeTag](future: Expr[Fut[A]]): Expr[Tryy[A]] =
5557
throw new UnsupportedOperationException("getCompleted not supported by this FutureSystem")
5658

@@ -110,11 +112,8 @@ object ScalaConcurrentFutureSystem extends FutureSystem {
110112

111113
override def continueCompletedFutureOnSameThread: Boolean = true
112114

113-
override def isCompleted(future: Expr[Fut[_]]): Expr[Boolean] = reify {
114-
future.splice.isCompleted
115-
}
116115
override def getCompleted[A: WeakTypeTag](future: Expr[Fut[A]]): Expr[Tryy[A]] = reify {
117-
future.splice.value.get
116+
if (future.splice.isCompleted) future.splice.value.get else null
118117
}
119118

120119
def completeProm[A](prom: Expr[Prom[A]], value: Expr[scala.util.Try[A]]): Expr[Unit] = reify {

src/main/scala/scala/async/internal/TransformUtils.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ private[async] trait TransformUtils {
2424
val ifRes = "ifres"
2525
val await = "await"
2626
val bindSuffix = "$bind"
27+
val completed = newTermName("completed")
2728

2829
val state = newTermName("state")
2930
val result = newTermName("result")

0 commit comments

Comments
 (0)