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 --- CONTRIBUTING.md | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 197 +++----------------------------------------------------- 2 files changed, 194 insertions(+), 189 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..9cd4bb5 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,186 @@ +## 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 +} +``` \ No newline at end of file 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