1
1
# scala-async [ ![ Build Status] ( https://travis-ci.org/scala/scala-async.svg?branch=master )] ( https://travis-ci.org/scala/scala-async ) [ <img src =" https://img.shields.io/maven-central/v/org.scala-lang.modules/scala-async_2.12.svg?label=latest%20release%20for%202.12 " >] ( http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-async_2.12 ) [ <img src =" https://img.shields.io/maven-central/v/org.scala-lang.modules/scala-async_2.13.svg?label=latest%20release%20for%202.13 " >] ( http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-async_2.13 )
2
2
3
- ## Supported Scala versions
4
-
5
- This branch (version series 0.10.x) targets Scala 2.12 and 2.13. ` scala-async ` is no longer maintained for older versions.
6
-
7
3
## Quick start
8
4
9
5
To include scala-async in an existing project use the library published on Maven Central.
10
6
For sbt projects add the following to your build definition - build.sbt or project/Build.scala:
11
7
8
+ ### Use a modern Scala compiler
9
+
10
+ As of scala-async 1.0, Scala 2.12.12+ or 2.13.3+ are required.
11
+
12
+ ### Add dependency
13
+
14
+ #### SBT Example
15
+
12
16
``` scala
13
- libraryDependencies += " org.scala-lang.modules" %% " scala-async" % " 0.10 .0"
17
+ libraryDependencies += " org.scala-lang.modules" %% " scala-async" % " 1.0 .0"
14
18
libraryDependencies += " org.scala-lang" % " scala-reflect" % scalaVersion.value % Provided
15
19
```
16
20
17
21
For Maven projects add the following to your <dependencies > (make sure to use the correct Scala version suffix
18
22
to match your project’s Scala binary version):
19
23
24
+ #### Maven Example
25
+
20
26
``` scala
21
27
<dependency >
22
- <groupId >org.scala- lang.modules</groupId >
23
- <artifactId >scala- async_2.12 </artifactId >
24
- <version >0.10 .0 </version >
28
+ <groupId >org.scala- lang.modules</groupId >
29
+ <artifactId >scala- async_2.13 </artifactId >
30
+ <version >1.0 .0 </version >
25
31
</dependency >
26
32
<dependency >
27
- <groupId >org.scala- lang</groupId >
28
- <artifactId >scala- reflect</artifactId >
29
- <version >2.12.11 </version >
30
- <scope >provided</scope >
33
+ <groupId >org.scala- lang</groupId >
34
+ <artifactId >scala- reflect</artifactId >
35
+ <version >2.13.3 </version >
36
+ <scope >provided</scope >
31
37
</dependency >
32
38
```
33
39
34
- After adding scala-async to your classpath, write your first ` async ` block:
40
+ ### Enable compiler support for ` async `
41
+
42
+ Add the ` -Xasync ` to the Scala compiler options.
43
+
44
+ #### SBT Example
45
+ ``` scala
46
+ scalaOptions += " -Xasync"
47
+ ```
48
+
49
+ #### Maven Example
50
+
51
+ ``` xml
52
+ <project >
53
+ ...
54
+ <plugin >
55
+ <groupId >net.alchim31.maven</groupId >
56
+ <artifactId >scala-maven-plugin</artifactId >
57
+ <version >4.4.0</version >
58
+ <configuration >
59
+ <args >
60
+ <arg >-Xasync</arg >
61
+ </args >
62
+ </configuration >
63
+ </plugin >
64
+ ...
65
+ </project >
66
+ ```
67
+
68
+ ### Start coding
35
69
36
70
``` scala
37
71
import scala .concurrent .ExecutionContext .Implicits .global
@@ -93,6 +127,22 @@ def combined: Future[Int] = async {
93
127
}
94
128
```
95
129
130
+ ## Limitations
131
+
132
+ ### ` await ` must be directly in the control flow of the async expression
133
+
134
+ The ` await ` cannot be nested under a local method, object, class or lambda:
135
+
136
+ ```
137
+ async {
138
+ List(1).foreach { x => await(f(x) } // invalid
139
+ }
140
+ ```
141
+
142
+ ### ` await ` must be not be nested within ` try ` / ` catch ` / ` finally ` .
143
+
144
+ This implementation restriction may be lifted in future versions.
145
+
96
146
## Comparison with direct use of ` Future ` API
97
147
98
148
This computation could also be expressed by directly using the
@@ -119,53 +169,3 @@ The `async` approach has two advantages over the use of
119
169
required at each generator (` <- ` ) in the for-comprehension.
120
170
This reduces the size of generated code, and can avoid boxing
121
171
of intermediate results.
122
-
123
- ## Comparison with CPS plugin
124
-
125
- The existing continuations (CPS) plugin for Scala can also be used
126
- to provide a syntactic layer like ` async ` . This approach has been
127
- used in Akka's [ Dataflow Concurrency] ( http://doc.akka.io/docs/akka/2.3-M1/scala/dataflow.html )
128
- (now deprecated in favour of this library).
129
-
130
- CPS-based rewriting of asynchronous code also produces a closure
131
- for each suspension. It can also lead to type errors that are
132
- difficult to understand.
133
-
134
- ## How it works
135
-
136
- - The ` async ` macro analyses the block of code, looking for control
137
- structures and locations of ` await ` calls. It then breaks the code
138
- into 'chunks'. Each chunk contains a linear sequence of statements
139
- that concludes with a branching decision, or with the registration
140
- of a subsequent state handler as the continuation.
141
- - Before this analysis and transformation, the program is normalized
142
- into a form amenable to this manipulation. This is called the
143
- "A Normal Form" (ANF), and roughly means that:
144
- - ` if ` and ` match ` constructs are only used as statements;
145
- they cannot be used as an expression.
146
- - calls to ` await ` are not allowed in compound expressions.
147
- - Identify vals, vars and defs that are accessed from multiple
148
- states. These will be lifted out to fields in the state machine
149
- object.
150
- - Synthesize a class that holds:
151
- - an integer representing the current state ID.
152
- - the lifted definitions.
153
- - an ` apply(value: Try[Any]): Unit ` method that will be
154
- called on completion of each future. The behavior of
155
- this method is determined by the current state. It records
156
- the downcast result of the future in a field, and calls the
157
- ` resume() ` method.
158
- - the ` resume(): Unit ` method that switches on the current state
159
- and runs the users code for one 'chunk', and either:
160
- a) registers the state machine as the handler for the next future
161
- b) completes the result Promise of the ` async ` block, if at the terminal state.
162
- - an ` apply(): Unit ` method that starts the computation.
163
-
164
- ## Limitations
165
-
166
- - See the [ neg] ( https://github.com/scala/async/tree/master/src/test/scala/scala/async/neg ) test cases
167
- for constructs that are not allowed in an ` async ` block.
168
- - See the [ issue list] ( https://github.com/scala/async/issues?state=open ) for which of these restrictions are planned
169
- to be dropped in the future.
170
- - See [ #32 ] ( https://github.com/scala/async/issues/32 ) for why ` await ` is not possible in closures, and for suggestions on
171
- ways to structure the code to work around this limitation.
0 commit comments