Skip to content

Improve grammar in docs/Basics #2076

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 31 additions & 30 deletions docs/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fun main() {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt).

You will see the following result:

Expand All @@ -57,24 +57,24 @@ They are launched with [launch] _coroutine builder_ in a context of some [Corout
Here we are launching a new coroutine in the [GlobalScope], meaning that the lifetime of the new
coroutine is limited only by the lifetime of the whole application.

You can achieve the same result replacing
`GlobalScope.launch { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`.
You can achieve the same result by replacing
`GlobalScope.launch { ... }` with `thread { ... }`, and `delay(...)` with `Thread.sleep(...)`.
Try it (don't forget to import `kotlin.concurrent.thread`).

If you start by replacing `GlobalScope.launch` by `thread`, the compiler produces the following error:
If you start by replacing `GlobalScope.launch` with `thread`, the compiler produces the following error:

```
Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
```

That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
coroutine and it can be only used from a coroutine.
That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_ the
coroutine, and it can be only used from a coroutine.

### Bridging blocking and non-blocking worlds

The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
It is easy to lose track of which one is blocking and which one is not.
Let's be explicit about blocking using [runBlocking] coroutine builder:
Let's be explicit about blocking using the [runBlocking] coroutine builder:

<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">

Expand All @@ -95,7 +95,7 @@ fun main() {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt).

<!--- TEST
Hello,
Expand Down Expand Up @@ -125,7 +125,7 @@ fun main() = runBlocking<Unit> { // start main coroutine

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt).

<!--- TEST
Hello,
Expand Down Expand Up @@ -180,7 +180,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt).

<!--- TEST
Hello,
Expand All @@ -195,15 +195,15 @@ the background job in any way. Much better.
There is still something to be desired for practical usage of coroutines.
When we use `GlobalScope.launch`, we create a top-level coroutine. Even though it is light-weight, it still
consumes some memory resources while it runs. If we forget to keep a reference to the newly launched
coroutine it still runs. What if the code in the coroutine hangs (for example, we erroneously
coroutine, it still runs. What if the code in the coroutine hangs (for example, we erroneously
delay for too long), what if we launched too many coroutines and ran out of memory?
Having to manually keep references to all the launched coroutines and [join][Job.join] them is error-prone.

There is a better solution. We can use structured concurrency in our code.
Instead of launching coroutines in the [GlobalScope], just like we usually do with threads (threads are always global),
we can launch coroutines in the specific scope of the operation we are performing.

In our example, we have `main` function that is turned into a coroutine using [runBlocking] coroutine builder.
In our example, we have a `main` function that is turned into a coroutine using a [runBlocking] coroutine builder.
Every coroutine builder, including `runBlocking`, adds an instance of [CoroutineScope] to the scope of its code block.
We can launch coroutines in this scope without having to `join` them explicitly, because
an outer coroutine (`runBlocking` in our example) does not complete until all the coroutines launched
Expand All @@ -225,20 +225,20 @@ fun main() = runBlocking { // this: CoroutineScope

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt).

<!--- TEST
Hello,
World!
-->

### Scope builder
In addition to the coroutine scope provided by different builders, it is possible to declare your own scope using
[coroutineScope] builder. It creates a coroutine scope and does not complete until all launched children
complete.

[runBlocking] and [coroutineScope] may look similar because they both wait for its body and all its children to complete.
The main difference between these two is that the [runBlocking] method _blocks_ the current thread for waiting,
In addition to the coroutine scope provided by different builders, it is possible to declare your own scope using the
[coroutineScope] builder. It creates a coroutine scope and does not complete until all launched children complete.

[runBlocking] and [coroutineScope] may look similar because they both wait for their body and all its children to complete.
The main difference is that the [runBlocking] method _blocks_ the current thread for waiting,
while [coroutineScope] just suspends, releasing the underlying thread for other usages.
Because of that difference, [runBlocking] is a regular function and [coroutineScope] is a suspending function.

Expand Down Expand Up @@ -271,7 +271,7 @@ fun main() = runBlocking { // this: CoroutineScope

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt).

<!--- TEST
Task from coroutine scope
Expand All @@ -280,16 +280,16 @@ Task from nested launch
Coroutine scope is over
-->

Note that right after "Task from coroutine scope" message, while waiting for nested launch,
"Task from runBlocking" is executed and printed, though coroutineScope is not completed yet.
Note that right after the "Task from coroutine scope" message (while waiting for nested launch)
"Task from runBlocking" is executed and printed — even though the coroutineScope is not completed yet.

### Extract function refactoring

Let's extract the block of code inside `launch { ... }` into a separate function. When you
perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
That is your first _suspending function_. Suspending functions can be used inside coroutines
perform "Extract function" refactoring on this code, you get a new function with the `suspend` modifier.
This is your first _suspending function_. Suspending functions can be used inside coroutines
just like regular functions, but their additional feature is that they can, in turn,
use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
use other suspending functions (like `delay` in this example) to _suspend_ execution of a coroutine.

<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">

Expand All @@ -310,7 +310,7 @@ suspend fun doWorld() {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt).

<!--- TEST
Hello,
Expand All @@ -319,11 +319,11 @@ World!


But what if the extracted function contains a coroutine builder which is invoked on the current scope?
In this case `suspend` modifier on the extracted function is not enough. Making `doWorld` an extension
method on `CoroutineScope` is one of the solutions, but it may not always be applicable as it does not make API clearer.
In this case, the `suspend` modifier on the extracted function is not enough. Making `doWorld` an extension
method on `CoroutineScope` is one of the solutions, but it may not always be applicable as it does not make the API clearer.
The idiomatic solution is to have either an explicit `CoroutineScope` as a field in a class containing the target function
or an implicit one when the outer class implements `CoroutineScope`.
As a last resort, [CoroutineScope(coroutineContext)][CoroutineScope()] can be used, but such approach is structurally unsafe
As a last resort, [CoroutineScope(coroutineContext)][CoroutineScope()] can be used, but such an approach is structurally unsafe
because you no longer have control on the scope of execution of this method. Only private APIs can use this builder.

### Coroutines ARE light-weight
Expand All @@ -347,11 +347,12 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-08.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-08.kt).

<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->

It launches 100K coroutines and, after a second, each coroutine prints a dot.

Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)

### Global coroutines are like daemon threads
Expand Down Expand Up @@ -379,7 +380,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-09.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-09.kt).

You can run and see that it prints three lines and terminates:

Expand Down
14 changes: 7 additions & 7 deletions docs/cancellation-and-timeouts.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt).

It produces the following output:

Expand Down Expand Up @@ -104,7 +104,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt).

Run it to see that it continues to print "I'm sleeping" even after cancellation
until the job completes by itself after five iterations.
Expand Down Expand Up @@ -156,7 +156,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt).

As you can see, now this loop is cancelled. [isActive] is an extension property
available inside the coroutine via the [CoroutineScope] object.
Expand Down Expand Up @@ -203,7 +203,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt).

Both [join][Job.join] and [cancelAndJoin] wait for all finalization actions to complete,
so the example above produces the following output:
Expand Down Expand Up @@ -259,7 +259,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt).

<!--- TEST
job: I'm sleeping 0 ...
Expand Down Expand Up @@ -298,7 +298,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt).

It produces the following output:

Expand Down Expand Up @@ -342,7 +342,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt).

There is no longer an exception when running this code:

Expand Down
20 changes: 10 additions & 10 deletions docs/channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt).

The output of this code is:

Expand Down Expand Up @@ -99,7 +99,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt).

<!--- TEST
1
Expand Down Expand Up @@ -141,7 +141,7 @@ fun main() = runBlocking {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt).

<!--- TEST
1
Expand Down Expand Up @@ -214,7 +214,7 @@ fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = p

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt).

<!--- TEST
1
Expand Down Expand Up @@ -305,7 +305,7 @@ fun CoroutineScope.filter(numbers: ReceiveChannel<Int>, prime: Int) = produce<In

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt).

The output of this code is:

Expand Down Expand Up @@ -408,7 +408,7 @@ fun CoroutineScope.launchProcessor(id: Int, channel: ReceiveChannel<Int>) = laun

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt).

The output will be similar to the the following one, albeit the processor ids that receive
each specific integer may be different:
Expand Down Expand Up @@ -488,7 +488,7 @@ suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt).

The output is:

Expand Down Expand Up @@ -540,7 +540,7 @@ fun main() = runBlocking<Unit> {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt).

It prints "sending" _five_ times using a buffered channel with capacity of _four_:

Expand Down Expand Up @@ -595,7 +595,7 @@ suspend fun player(name: String, table: Channel<Ball>) {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt).

The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
Expand Down Expand Up @@ -658,7 +658,7 @@ fun main() = runBlocking<Unit> {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt).

It prints following lines:

Expand Down
12 changes: 6 additions & 6 deletions docs/composing-suspending-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ suspend fun doSomethingUsefulTwo(): Int {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt).

It produces something like this:

Expand Down Expand Up @@ -134,7 +134,7 @@ suspend fun doSomethingUsefulTwo(): Int {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt).

It produces something like this:

Expand Down Expand Up @@ -188,7 +188,7 @@ suspend fun doSomethingUsefulTwo(): Int {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt).

It produces something like this:

Expand Down Expand Up @@ -285,7 +285,7 @@ suspend fun doSomethingUsefulTwo(): Int {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt).

<!--- TEST ARBITRARY_TIME
The answer is 42
Expand Down Expand Up @@ -361,7 +361,7 @@ suspend fun doSomethingUsefulTwo(): Int {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt).

We still have concurrent execution of both operations, as evident from the output of the above `main` function:

Expand Down Expand Up @@ -408,7 +408,7 @@ suspend fun failedConcurrentSum(): Int = coroutineScope {

</div>

> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt).
> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt).

Note how both the first `async` and the awaiting parent are cancelled on failure of one of the children
(namely, `two`):
Expand Down
Loading