From 1c8a3bde9490f3b771543589be22d789d3b45701 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 7 Nov 2013 16:06:59 +0100 Subject: Update and split the README --- README.md | 197 +++----------------------------------------------------------- 1 file changed, 8 insertions(+), 189 deletions(-) (limited to 'README.md') diff --git a/README.md b/README.md index 552320f..8283c11 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,14 @@ ## Quick start - - Add `scala-async.jar` to your classpath - - Use Scala 2.10.0 +Add a dependency: + +```scala +// SBT +libraryDependencies += "org.scala-lang.modules.scala-async" % "scala-async" % "0.9.0-M2" +``` + +Write your first `async` block: ```scala import ExecutionContext.Implicits.global @@ -145,190 +151,3 @@ difficult to understand. to be dropped in the next milestone. - See [#13](https://github.com/scala/async/issues/13) for why `await` is not possible in closures, and for suggestions on ways to structure the code to work around this limitation. - -## Building - -The async macro and its test suite can be built and run with SBT. - -## Contributing - -If you are interested in contributing code, we ask you to complete and submit -to us the Scala Contributor License Agreement, which allows us to ensure that -all code submitted to the project is unencumbered by copyrights or patents. -The form is available at: -http://www.scala-lang.org/sites/default/files/contributor_agreement.pdf - -Before submitting a pull-request, please make sure you have followed the guidelines -outlined in our [Pull Request Policy](https://github.com/scala/scala/wiki/Pull-Request-Policy). - -### Generated Code examples - -```scala -val future = async { - val f1 = async { true } - val x = 1 - def inc(t: Int) = t + x - val t = 0 - val f2 = async { 42 } - if (await(f1)) await(f2) else { val z = 1; inc(t + z) } -} -``` - -After ANF transform. - - - await calls are moved to only appear on the RHS of a value definition. - - `if` is not used as an expression, instead each branch writes its result - to a synthetic `var`. - -```scala - { - (); - val f1: scala.concurrent.Future[Boolean] = { - scala.concurrent.Future.apply[Boolean](true)(scala.concurrent.ExecutionContext.Implicits.global) - }; - val x: Int = 1; - def inc(t: Int): Int = t.+(x); - val t: Int = 0; - val f2: scala.concurrent.Future[Int] = { - scala.concurrent.Future.apply[Int](42)(scala.concurrent.ExecutionContext.Implicits.global) - }; - val await$1: Boolean = scala.async.Async.await[Boolean](f1); - var ifres$1: Int = 0; - if (await$1) - { - val await$2: Int = scala.async.Async.await[Int](f2); - ifres$1 = await$2 - } - else - { - ifres$1 = { - val z: Int = 1; - inc(t.+(z)) - } - }; - ifres$1 -} -``` - -After async transform: - - - one class synthesized to act as the state machine. It's `apply()` method will - be used to start the computation (even the code before the first await call - is executed asynchronously), and the `apply(tr: scala.util.Try[Any])` method - will continue after each completed background task. - - each chunk of code moved into the a branch of the pattern match in `resume$async`. - - value and method definitions accessed from multiple states are lifted to be - members of `class stateMachine`. Others remain local, e.g. `val z`. - -```scala - { - class stateMachine$7 extends ... { - def () = { - super.(); - () - }; - var state$async: Int = 0; - val result$async: scala.concurrent.Promise[Int] = scala.concurrent.Promise.apply[Int](); - val execContext$async = scala.concurrent.ExecutionContext.Implicits.global; - var x$1: Int = 0; - def inc$1(t: Int): Int = t.$plus(x$1); - var t$1: Int = 0; - var f2$1: scala.concurrent.Future[Int] = null; - var await$1: Boolean = false; - var ifres$1: Int = 0; - var await$2: Int = 0; - def resume$async(): Unit = try { - state$async match { - case 0 => { - (); - val f1 = { - scala.concurrent.Future.apply[Boolean](true)(scala.concurrent.ExecutionContext.Implicits.global) - }; - x$1 = 1; - t$1 = 0; - f2$1 = { - scala.concurrent.Future.apply[Int](42)(scala.concurrent.ExecutionContext.Implicits.global) - }; - f1.onComplete(this)(execContext$async) - } - case 1 => { - ifres$1 = 0; - if (await$1) - { - state$async = 2; - resume$async() - } - else - { - state$async = 3; - resume$async() - } - } - case 2 => { - f2$1.onComplete(this)(execContext$async); - () - } - case 5 => { - ifres$1 = await$2; - state$async = 4; - resume$async() - } - case 3 => { - ifres$1 = { - val z = 1; - inc$1(t$1.$plus(z)) - }; - state$async = 4; - resume$async() - } - case 4 => { - result$async.complete(scala.util.Success.apply(ifres$1)); - () - } - } - } catch { - case NonFatal((tr @ _)) => { - { - result$async.complete(scala.util.Failure.apply(tr)); - () - }; - () - } - }; - def apply(tr: scala.util.Try[Any]): Unit = state$async match { - case 0 => { - if (tr.isFailure) - { - result$async.complete(tr.asInstanceOf[scala.util.Try[Int]]); - () - } - else - { - await$1 = tr.get.asInstanceOf[Boolean]; - state$async = 1; - resume$async() - }; - () - } - case 2 => { - if (tr.isFailure) - { - result$async.complete(tr.asInstanceOf[scala.util.Try[Int]]); - () - } - else - { - await$2 = tr.get.asInstanceOf[Int]; - state$async = 5; - resume$async() - }; - () - } - }; - def apply: Unit = resume$async() - }; - val stateMachine$7: StateMachine[scala.concurrent.Promise[Int], scala.concurrent.ExecutionContext] = new stateMachine$7(); - scala.concurrent.Future.apply(stateMachine$7.apply())(scala.concurrent.ExecutionContext.Implicits.global); - stateMachine$7.result$async.future -} -``` -- cgit v1.2.3