Skip to content

Commit a84730b

Browse files
committed
Corrections to the recent guide additions
1 parent f5bc047 commit a84730b

File tree

6 files changed

+41
-49
lines changed

6 files changed

+41
-49
lines changed

coroutines-guide.md

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,7 +1379,7 @@ suspend fun massiveRun(action: suspend () -> Unit) {
13791379

13801380
<!--- INCLUDE .*/example-sync-([0-9]+).kt -->
13811381

1382-
We start with a very simple action, that increments a shared mutable variable.
1382+
We start with a very simple action that increments a shared mutable variable.
13831383

13841384
```kotlin
13851385
var counter = 0
@@ -1482,7 +1482,7 @@ class GetCounter(val response: SendChannel<Int>) : CounterMsg() // a request wit
14821482
// This function launches a new counter actor
14831483
fun counterActor(request: ReceiveChannel<CounterMsg>) = launch(CommonPool) {
14841484
var counter = 0 // actor state
1485-
while (true) { // main loop of the actor
1485+
while (isActive) { // main loop of the actor
14861486
val msg = request.receive()
14871487
when (msg) {
14881488
is IncCounter -> counter++
@@ -1511,7 +1511,7 @@ works as a solution to the problem of shared mutable state.
15111511

15121512
## Select expression
15131513

1514-
Select expression makes it possible to await multiple suspending function simultaneously and _select_
1514+
Select expression makes it possible to await multiple suspending functions simultaneously and _select_
15151515
the first one that becomes available.
15161516

15171517
<!--- INCLUDE .*/example-select-([0-9]+).kt
@@ -1560,7 +1560,7 @@ suspend fun selectFizzBuzz() {
15601560
}
15611561
```
15621562

1563-
Let us run it for 7 times:
1563+
Let us run it seven times:
15641564

15651565
```kotlin
15661566
fun main(args: Array<String>) = runBlocking<Unit> {
@@ -1588,7 +1588,7 @@ buzz -> 'Buzz!'
15881588

15891589
The [onReceive][SelectBuilder.onReceive] clause in `select` fails when the channel is closed and the corresponding
15901590
`select` throws an exception. We can use [onReceiveOrNull][SelectBuilder.onReceiveOrNull] clause to perform a
1591-
specific action when channel is closed. This example also show that `select` is an expression that returns
1591+
specific action when the channel is closed. The following example also shows that `select` is an expression that returns
15921592
the result of its selected clause:
15931593

15941594
```kotlin
@@ -1609,20 +1609,17 @@ suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): St
16091609
}
16101610
```
16111611

1612-
Lets have channel `a` that produces "Hello" string 4 and `b` that produces "World" 4 times for this example:
1612+
Let's use it with channel `a` that produces "Hello" string four times and
1613+
channel `b` that produces "World" four times:
16131614

16141615
```kotlin
16151616
fun main(args: Array<String>) = runBlocking<Unit> {
16161617
// we are using the context of the main thread in this example for predictability ...
16171618
val a = produce<String>(context) {
1618-
repeat(4) {
1619-
send("Hello $it")
1620-
}
1619+
repeat(4) { send("Hello $it") }
16211620
}
16221621
val b = produce<String>(context) {
1623-
repeat(4) {
1624-
send("World $it")
1625-
}
1622+
repeat(4) { send("World $it") }
16261623
}
16271624
repeat(8) { // print first eight results
16281625
println(selectAorB(a, b))
@@ -1632,7 +1629,7 @@ fun main(args: Array<String>) = runBlocking<Unit> {
16321629

16331630
> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-02.kt)
16341631
1635-
The result of this code is quite interesting, so we'll analyze it in mode details:
1632+
The result of this code is quite interesting, so we'll analyze it in mode detail:
16361633

16371634
```
16381635
a -> 'Hello 0'
@@ -1645,11 +1642,11 @@ Channel 'a' is closed
16451642
Channel 'a' is closed
16461643
```
16471644

1648-
There are a couple of observations to make out of it.
1645+
There are couple of observations to make out of it.
16491646

16501647
First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
16511648
the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
1652-
being the first clause in select wins. However, because we are using unbuffered channel, the `a` gets suspended from
1649+
being the first clause in select, wins. However, because we are using unbuffered channel, the `a` gets suspended from
16531650
time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
16541651

16551652
The second observation, is that [onReceiveOrNull][SelectBuilder.onReceiveOrNull] gets immediately selected when the
@@ -1660,16 +1657,16 @@ channel is already closed.
16601657
Select expression has [onSend][SelectBuilder.onSend] clause that can be used for a great good in combination
16611658
with a biased nature of selection.
16621659

1663-
Let us write an example of producer of integer numbers that sends its values to a `side` channel when
1660+
Let us write an example of producer of integers that sends its values to a `side` channel when
16641661
the consumers on its primary channel cannot keep up with it:
16651662

16661663
```kotlin
16671664
fun produceNumbers(side: SendChannel<Int>) = produce<Int>(CommonPool) {
16681665
for (num in 1..10) { // produce 10 numbers from 1 to 10
16691666
delay(100) // every 100 ms
16701667
select<Unit> {
1671-
onSend(num) { } // Send to the primary channel
1672-
side.onSend(num) { } // or to the side channel
1668+
onSend(num) {} // Send to the primary channel
1669+
side.onSend(num) {} // or to the side channel
16731670
}
16741671
}
16751672
}
@@ -1711,8 +1708,8 @@ Done consuming
17111708

17121709
### Selecting deferred values
17131710

1714-
Deferred values can be selected using [onAwait][SelectBuilder.onAwait] clause, which enables "wait first"
1715-
type of logic. Let us start with an async-style function that returns a deferred string value after
1711+
Deferred values can be selected using [onAwait][SelectBuilder.onAwait] clause.
1712+
Let us start with an async function that returns a deferred string value after
17161713
a random delay:
17171714

17181715
<!--- INCLUDE .*/example-select-04.kt
@@ -1726,20 +1723,19 @@ fun asyncString(time: Int) = async(CommonPool) {
17261723
}
17271724
```
17281725

1729-
Let us start a dozen for them with random delay with the following function that returns a
1730-
collection of deferred values:
1726+
Let us start a dozen of them with a random delay.
17311727

17321728
```kotlin
17331729
fun asyncStringsList(): List<Deferred<String>> {
17341730
val random = Random(3)
1735-
return (1..12).map { asyncString(random.nextInt(1000)) }
1731+
return List(12) { asyncString(random.nextInt(1000)) }
17361732
}
17371733
```
17381734

1739-
Now the main function awaits for the first of them to complete and count the number of deferred values
1735+
Now the main function awaits for the first of them to complete and counts the number of deferred values
17401736
that are still active. Note, that we've used here the fact that `select` expression is a Kotlin DSL,
1741-
and we can provide clauses for it using an arbitrary code. In this case we iterate over a list
1742-
of deferred values to produce an `onAwait` clause for each one of them.
1737+
so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
1738+
of deferred values to provide `onAwait` clause for each deferred value.
17431739

17441740
```kotlin
17451741
fun main(args: Array<String>) = runBlocking<Unit> {
@@ -1762,19 +1758,19 @@ fun main(args: Array<String>) = runBlocking<Unit> {
17621758
The output is:
17631759

17641760
```
1765-
Deferred 4 produced answer 'Waited for 254 ms'
1761+
Deferred 4 produced answer 'Waited for 128 ms'
17661762
11 coroutines are still active
17671763
```
17681764

17691765
### Switch over a channel of deferred values
17701766

1771-
Let us write a channel producer function that consumes a channel of deferred string values, await for each received
1772-
deferred value, but only until next deferred value comes over or the channel is closed. This example puts together
1767+
Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
1768+
deferred value, but only until the next deferred value comes over or the channel is closed. This example puts together
17731769
[onReceiveOrNull][SelectBuilder.onReceiveOrNull] and [onAwait][SelectBuilder.onAwait] clauses in the same `select`:
17741770

17751771
```kotlin
17761772
fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String>(CommonPool) {
1777-
var current = input.receive() // will start with first received deferred value
1773+
var current = input.receive() // start with first received deferred value
17781774
while (isActive) { // loop while not cancelled/closed
17791775
val next = select<Deferred<String>?> { // return next deferred value from this select or null
17801776
input.onReceiveOrNull { update ->
@@ -1810,19 +1806,19 @@ data to it:
18101806
```kotlin
18111807
fun main(args: Array<String>) = runBlocking<Unit> {
18121808
val chan = Channel<Deferred<String>>() // the channel for test
1813-
launch(context) { // launch printing coroutines
1809+
launch(context) { // launch printing coroutine
18141810
for (s in switchMapDeferreds(chan))
18151811
println(s) // print each received string
18161812
}
18171813
chan.send(asyncString("BEGIN", 100))
18181814
delay(200) // enough time for "BEGIN" to be produced
18191815
chan.send(asyncString("Slow", 500))
1820-
delay(100) // not enough time for slow
1816+
delay(100) // not enough time to produce slow
18211817
chan.send(asyncString("Replace", 100))
1822-
delay(500) // will give it time before the last one
1818+
delay(500) // give it time before the last one
18231819
chan.send(asyncString("END", 500))
18241820
delay(1000) // give it time to process
1825-
chan.close() // and close the channel immediately
1821+
chan.close() // close the channel ...
18261822
delay(500) // and wait some time to let it finish
18271823
}
18281824
```

kotlinx-coroutines-core/src/test/kotlin/guide/example-select-02.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,10 @@ suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): St
4040
fun main(args: Array<String>) = runBlocking<Unit> {
4141
// we are using the context of the main thread in this example for predictability ...
4242
val a = produce<String>(context) {
43-
repeat(4) {
44-
send("Hello $it")
45-
}
43+
repeat(4) { send("Hello $it") }
4644
}
4745
val b = produce<String>(context) {
48-
repeat(4) {
49-
send("World $it")
50-
}
46+
repeat(4) { send("World $it") }
5147
}
5248
repeat(8) { // print first eight results
5349
println(selectAorB(a, b))

kotlinx-coroutines-core/src/test/kotlin/guide/example-select-03.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ fun produceNumbers(side: SendChannel<Int>) = produce<Int>(CommonPool) {
2525
for (num in 1..10) { // produce 10 numbers from 1 to 10
2626
delay(100) // every 100 ms
2727
select<Unit> {
28-
onSend(num) { } // Send to the primary channel
29-
side.onSend(num) { } // or to the side channel
28+
onSend(num) {} // Send to the primary channel
29+
side.onSend(num) {} // or to the side channel
3030
}
3131
}
3232
}

kotlinx-coroutines-core/src/test/kotlin/guide/example-select-04.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fun asyncString(time: Int) = async(CommonPool) {
2929

3030
fun asyncStringsList(): List<Deferred<String>> {
3131
val random = Random(3)
32-
return (1..12).map { asyncString(random.nextInt(1000)) }
32+
return List(12) { asyncString(random.nextInt(1000)) }
3333
}
3434

3535
fun main(args: Array<String>) = runBlocking<Unit> {

kotlinx-coroutines-core/src/test/kotlin/guide/example-select-05.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import kotlinx.coroutines.experimental.channels.*
2222
import kotlinx.coroutines.experimental.selects.*
2323

2424
fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String>(CommonPool) {
25-
var current = input.receive() // will start with first received deferred value
25+
var current = input.receive() // start with first received deferred value
2626
while (isActive) { // loop while not cancelled/closed
2727
val next = select<Deferred<String>?> { // return next deferred value from this select or null
2828
input.onReceiveOrNull { update ->
@@ -49,18 +49,18 @@ fun asyncString(str: String, time: Long) = async(CommonPool) {
4949

5050
fun main(args: Array<String>) = runBlocking<Unit> {
5151
val chan = Channel<Deferred<String>>() // the channel for test
52-
launch(context) { // launch printing coroutines
52+
launch(context) { // launch printing coroutine
5353
for (s in switchMapDeferreds(chan))
5454
println(s) // print each received string
5555
}
5656
chan.send(asyncString("BEGIN", 100))
5757
delay(200) // enough time for "BEGIN" to be produced
5858
chan.send(asyncString("Slow", 500))
59-
delay(100) // not enough time for slow
59+
delay(100) // not enough time to produce slow
6060
chan.send(asyncString("Replace", 100))
61-
delay(500) // will give it time before the last one
61+
delay(500) // give it time before the last one
6262
chan.send(asyncString("END", 500))
6363
delay(1000) // give it time to process
64-
chan.close() // and close the channel immediately
64+
chan.close() // close the channel ...
6565
delay(500) // and wait some time to let it finish
6666
}

kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-05.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class GetCounter(val response: SendChannel<Int>) : CounterMsg() // a request wit
4242
// This function launches a new counter actor
4343
fun counterActor(request: ReceiveChannel<CounterMsg>) = launch(CommonPool) {
4444
var counter = 0 // actor state
45-
while (true) { // main loop of the actor
45+
while (isActive) { // main loop of the actor
4646
val msg = request.receive()
4747
when (msg) {
4848
is IncCounter -> counter++

0 commit comments

Comments
 (0)