aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md21
-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
4 files changed, 35 insertions, 13 deletions
diff --git a/README.md b/README.md
index 0f5c730..68a27c4 100644
--- a/README.md
+++ b/README.md
@@ -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")