diff options
-rw-r--r-- | README.md | 21 | ||||
-rw-r--r-- | src/main/scala/scala/async/internal/ExprBuilder.scala | 15 | ||||
-rw-r--r-- | src/main/scala/scala/async/internal/FutureSystem.scala | 11 | ||||
-rw-r--r-- | src/main/scala/scala/async/internal/TransformUtils.scala | 1 |
4 files changed, 35 insertions, 13 deletions
@@ -4,6 +4,24 @@ Note: this branch targets Scala 2.11.x, support for Scala 2.10.x has been moved ## Quick start +To include scala-async in an existing project use the library published on Maven Central. +For sbt projects add the following to your build definition - build.sbt or project/Build.scala: + +```scala +libraryDependencies += "org.scala-lang.modules" %% "scala-async" % "0.9.5" +``` + +For Maven projects add the following to your <dependencies> (make sure to use the correct Scala version prefix, _2.10 or _2.11, +to match your project’s Scala version): + +```scala +<dependency> + <groupId>org.scala-lang.modules</groupId> + <artifactId>scala-async_2.11</artifactId> + <version>0.9.5</version> +</dependency> +``` + After adding a scala-async to your classpath, write your first `async` block: ```scala @@ -97,7 +115,8 @@ The `async` approach has two advantages over the use of The existing continuations (CPS) plugin for Scala can also be used to provide a syntactic layer like `async`. This approach has been -used in Akka's [Dataflow Concurrency](http://doc.akka.io/docs/akka/snapshot/scala/dataflow.html) +used in Akka's [Dataflow Concurrency](http://doc.akka.io/docs/akka/2.3-M1/scala/dataflow.html) +(now deprecated in favour of this library). CPS-based rewriting of asynchronous code also produces a closure for each suspension. It can also lead to type errors that are 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 8b94513..c86540b 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") |