Skip to content

Commit a5e653f

Browse files
committed
buildChannel is renamed to produce
top-level readme file for kotlinx-coroutines-core module is improved: Better grouping and list of all available features
1 parent fc7a9a2 commit a5e653f

File tree

10 files changed

+285
-187
lines changed

10 files changed

+285
-187
lines changed

coroutines-guide.md

Lines changed: 41 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
<!---
2-
3-
Copyright 2016-2017 JetBrains s.r.o.
4-
5-
Licensed under the Apache License, Version 2.0 (the "License");
6-
you may not use this file except in compliance with the License.
7-
You may obtain a copy of the License at
8-
9-
http://www.apache.org/licenses/LICENSE-2.0
1+
<!--- INCLUDE .*/example-([a-z]+)-([0-9]+)\.kt
2+
/*
3+
* Copyright 2016-2017 JetBrains s.r.o.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
1017
11-
Unless required by applicable law or agreed to in writing, software
12-
distributed under the License is distributed on an "AS IS" BASIS,
13-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14-
See the License for the specific language governing permissions and
15-
limitations under the License.
18+
// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
19+
package guide.$$1.example$$2
1620
21+
import kotlinx.coroutines.experimental.*
1722
-->
23+
<!--- KNIT kotlinx-coroutines-core/src/test/kotlin/guide/.*\.kt -->
1824

1925
# Guide to kotlinx.coroutines by example
2026

@@ -63,31 +69,8 @@ This is a short guide on core features of `kotlinx.coroutines` with a series of
6369
* [Fan-in](#fan-in)
6470
* [Buffered channels](#buffered-channels)
6571

66-
<!--- KNIT kotlinx-coroutines-core/src/test/kotlin/guide/.*\.kt -->
67-
68-
<!--- INCLUDE .*/example-([a-z]+)-([0-9]+)\.kt
69-
/*
70-
* Copyright 2016-2017 JetBrains s.r.o.
71-
*
72-
* Licensed under the Apache License, Version 2.0 (the "License");
73-
* you may not use this file except in compliance with the License.
74-
* You may obtain a copy of the License at
75-
*
76-
* http://www.apache.org/licenses/LICENSE-2.0
77-
*
78-
* Unless required by applicable law or agreed to in writing, software
79-
* distributed under the License is distributed on an "AS IS" BASIS,
80-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
81-
* See the License for the specific language governing permissions and
82-
* limitations under the License.
83-
*/
84-
85-
// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
86-
package guide.$$1.example$$2
72+
<!--- END_TOC -->
8773

88-
import kotlinx.coroutines.experimental.*
89-
-->
90-
9174
## Coroutine basics
9275

9376
This section covers basic coroutine concepts.
@@ -1060,13 +1043,15 @@ fun main(args: Array<String>) = runBlocking<Unit> {
10601043
10611044
### Building channel producers
10621045

1063-
The pattern where a coroutine is producing a sequence of elements into a channel is quite common.
1046+
The pattern where a coroutine is producing a sequence of elements is quite common.
1047+
This is a part of _producer-consumer_ pattern that is often found in concurrent code.
10641048
You could abstract such a producer into a function that takes channel as its parameter, but this goes contrary
1065-
to common sense that results must be returned from functions. Here is a convenience
1066-
coroutine builder named [buildChannel] that makes it easy to do it right:
1049+
to common sense that results must be returned from functions.
1050+
1051+
There is a convenience coroutine builder named [produce] that makes it easy to do it right:
10671052

10681053
```kotlin
1069-
fun produceSquares() = buildChannel<Int>(CommonPool) {
1054+
fun produceSquares() = produce<Int>(CommonPool) {
10701055
for (x in 1..5) send(x * x)
10711056
}
10721057

@@ -1084,22 +1069,22 @@ fun main(args: Array<String>) = runBlocking<Unit> {
10841069
Pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
10851070

10861071
```kotlin
1087-
fun produceNumbers() = buildChannel<Int>(CommonPool) {
1072+
fun produceNumbers() = produce<Int>(CommonPool) {
10881073
var x = 1
10891074
while (true) send(x++) // infinite stream of integers starting from 1
10901075
}
10911076
```
10921077

1093-
And another coroutine or coroutines are receiving that stream, doing some processing, and sending the result.
1078+
And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
10941079
In the below example the numbers are just squared:
10951080

10961081
```kotlin
1097-
fun square(numbers: ReceiveChannel<Int>) = buildChannel<Int>(CommonPool) {
1082+
fun square(numbers: ReceiveChannel<Int>) = produce<Int>(CommonPool) {
10981083
for (x in numbers) send(x * x)
10991084
}
11001085
```
11011086

1102-
The main code starts and connects pipeline:
1087+
The main code starts and connects the whole pipeline:
11031088

11041089
```kotlin
11051090
fun main(args: Array<String>) = runBlocking<Unit> {
@@ -1131,7 +1116,7 @@ import kotlin.coroutines.experimental.CoroutineContext
11311116
-->
11321117

11331118
```kotlin
1134-
fun numbersFrom(context: CoroutineContext, start: Int) = buildChannel<Int>(context) {
1119+
fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
11351120
var x = start
11361121
while (true) send(x++) // infinite stream of integers from start
11371122
}
@@ -1141,7 +1126,7 @@ The following pipeline stage filters an incoming stream of numbers, removing all
11411126
that are divisible by the given prime number:
11421127

11431128
```kotlin
1144-
fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = buildChannel<Int>(context) {
1129+
fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
11451130
for (x in numbers) if (x % prime != 0) send(x)
11461131
}
11471132
```
@@ -1150,7 +1135,7 @@ Now we build our pipeline by starting a stream of numbers from 2, taking a prime
11501135
and launching new pipeline stage for each prime number found:
11511136

11521137
```
1153-
numbers -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
1138+
numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
11541139
```
11551140

11561141
The following example prints the first ten prime numbers,
@@ -1184,16 +1169,16 @@ The output of this code is:
11841169
29
11851170
```
11861171

1187-
Note, that you can build the same pipeline using `buildIterator` from the standard library.
1188-
Replace `buildSequence` with `buildIterator`, `send` with `yield`, `receive` with `next`,
1172+
Note, that you can build the same pipeline using `buildIterator` coroutine builder from the standard library.
1173+
Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
11891174
`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
11901175
However, the benefit of a pipeline that uses channels as shown above is that it can actually use
11911176
multiple CPU cores if you run it in [CommonPool] context.
11921177

1193-
Anyway, this is an extremely impractical way to find prime numbers. In practise, pipelines do involve some
1178+
Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
11941179
other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
11951180
built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
1196-
`buildChannel` which is fully asynchronous.
1181+
`produce` which is fully asynchronous.
11971182

11981183
### Fan-out
11991184

@@ -1202,7 +1187,7 @@ Let us start with a producer coroutine that is periodically producing integers
12021187
(ten numbers per second):
12031188

12041189
```kotlin
1205-
fun produceNumbers() = buildChannel<Int>(CommonPool) {
1190+
fun produceNumbers() = produce<Int>(CommonPool) {
12061191
var x = 1 // start from 1
12071192
while (true) {
12081193
send(x++) // produce next
@@ -1303,7 +1288,7 @@ The channels shown so far had no buffer. Unbuffered channels transfer elements w
13031288
meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
13041289
if receive is invoked first, it is suspended until send is invoked.
13051290

1306-
Both [Channel()][Channel.invoke] factory function and [buildChannel] builder take an optional `capacity` parameter to
1291+
Both [Channel()][Channel.invoke] factory function and [produce] builder take an optional `capacity` parameter to
13071292
specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
13081293
similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
13091294

@@ -1369,5 +1354,5 @@ The first four elements are added to the buffer and the sender suspends when try
13691354
[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
13701355
[SendChannel.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/close.html
13711356
[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
1372-
[buildChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/build-channel.html
1357+
[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
13731358
<!--- END -->

knit/src/Knit.kt

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,16 @@ val SECTION_START = "##"
3939
val API_REF_REGEX = Regex("(^|[ \\]])\\[([A-Za-z0-9_.]+)\\]($|[^\\[\\(])")
4040

4141
fun main(args: Array<String>) {
42-
if(args.size != 1) {
43-
println("Usage: Knit <markdown-file>")
42+
if (args.isEmpty()) {
43+
println("Usage: Knit <markdown-files>")
4444
return
4545
}
46-
val markdownFile = File(args[0])
46+
args.forEach(::knit)
47+
}
48+
49+
fun knit(markdownFileName: String) {
50+
println("*** Reading $markdownFileName")
51+
val markdownFile = File(markdownFileName)
4752
val toc = arrayListOf<String>()
4853
var knitRegex: Regex? = null
4954
val includes = arrayListOf<Include>()
@@ -122,8 +127,8 @@ fun main(args: Array<String>) {
122127
}
123128
}
124129
skip = false
125-
postTocText += indexLines
126-
postTocText += putBackLine!!
130+
outText += indexLines
131+
outText += putBackLine!!
127132
}
128133
}
129134
if (inLine.startsWith(CODE_START)) {
@@ -172,8 +177,16 @@ fun main(args: Array<String>) {
172177
}
173178
}
174179
// update markdown file with toc
175-
val newLines = markdown.preTocText + "" + toc + "" + markdown.postTocText
176-
if (newLines != markdown.allText) writeLines(markdownFile, newLines)
180+
val newLines = buildList<String> {
181+
addAll(markdown.preTocText)
182+
if (!toc.isEmpty()) {
183+
add("")
184+
addAll(toc)
185+
add("")
186+
}
187+
addAll(markdown.postTocText)
188+
}
189+
if (newLines != markdown.inText) writeLines(markdownFile, newLines)
177190
// check apiRefs
178191
for (apiRef in allApiRefs) {
179192
if (apiRef.name in remainingApiRefNames) {
@@ -182,6 +195,12 @@ fun main(args: Array<String>) {
182195
}
183196
}
184197

198+
private inline fun <T> buildList(block: ArrayList<T>.() -> Unit): List<T> {
199+
val result = arrayListOf<T>()
200+
result.block()
201+
return result
202+
}
203+
185204
private fun requireSingleLine(directive: Directive) {
186205
require(directive.singleLine) { "${directive.name} directive must end on the same line with '$DIRECTIVE_END'" }
187206
}
@@ -212,23 +231,23 @@ class ApiRef(val line: Int, val name: String)
212231
enum class MarkdownPart { PRE_TOC, TOC, POST_TOC }
213232

214233
class MarkdownTextReader(r: Reader) : LineNumberReader(r) {
215-
val allText = arrayListOf<String>()
234+
val inText = arrayListOf<String>()
216235
val preTocText = arrayListOf<String>()
217236
val postTocText = arrayListOf<String>()
218237
var markdownPart: MarkdownPart = MarkdownPart.PRE_TOC
219238
var skip = false
220239

240+
val outText: MutableList<String> get() = when (markdownPart) {
241+
MarkdownPart.PRE_TOC -> preTocText
242+
MarkdownPart.POST_TOC -> postTocText
243+
else -> throw IllegalStateException("Wrong state: $markdownPart")
244+
}
245+
221246
override fun readLine(): String? {
222247
val line = super.readLine() ?: return null
223-
allText += line
224-
if (!skip) {
225-
when (markdownPart) {
226-
MarkdownPart.PRE_TOC -> preTocText += line
227-
MarkdownPart.POST_TOC -> postTocText += line
228-
MarkdownPart.TOC -> {
229-
} // do nothing
230-
}
231-
}
248+
inText += line
249+
if (!skip && markdownPart != MarkdownPart.TOC)
250+
outText += line
232251
return line
233252
}
234253
}

kotlinx-coroutines-core/README.md

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,75 @@
11
# Module kotlinx-coroutines-core
22

33
Core primitives to work with coroutines.
4+
5+
This module provides the following coroutine builders:
6+
7+
| **Name** | **Result** | **Scope** | **Description**
8+
| ------------- | ------------- | ---------------- | ---------------
9+
| [launch] | [Job] | [CoroutineScope] | Launches coroutine that does not have any result
10+
| [async] | [Deferred] | [CoroutineScope] | Returns a single value with the future result
11+
| [produce] | [ProducerJob] | [ProducerScope] | Produces a stream of elements
12+
| [runBlocking] | `T` | [CoroutineScope] | Blocks the thread while the coroutine runs
13+
14+
These builders can be used with the following [coroutine dispatchers][CoroutineDispatcher]:
15+
16+
| **Name** | **Description**
17+
| --------------------------- | ---------------
18+
| [CommonPool] | Confines coroutine execution to a shared pool of threads
19+
| [newSingleThreadContext] | Create new single-threaded coroutine context
20+
| [newFixedThreadPoolContext] | Creates new thread pool of a fixed size
21+
| [Executor.toCoroutineDispatcher][java.util.concurrent.Executor.toCoroutineDispatcher] | Extension to convert any executor
22+
| [Unconfined] | Does not confine coroutine execution in any way
23+
24+
The following top-level suspending functions are provided to be used _inside coroutines_:
25+
26+
| **Name** | **Description**
27+
| ------------- | ---------------
28+
| [delay] | Non-blocking sleep
29+
| [yield] | Yields thread in single-threaded dispatchers
30+
| [run] | Switches to a different context
31+
| [withTimeout] | Set execution time-limit (deadline)
32+
33+
Cancellation support for user-defined suspending functions is available with [suspendCancellableCoroutine]
34+
helper function. [NonCancellable] job object is provided to suppress cancellation with
35+
`run(NonCancellable) {...}` block of code.
36+
37+
This module provides debugging facilities for coroutines (run JVM with `-ea` or `-Dkotlinx.coroutines.debug` options)
38+
and [newCoroutineContext] function to write user-defined coroutine builders that work with these
39+
debugging facilities.
40+
41+
<!--- SITE_ROOT https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core -->
42+
<!--- DOCS_ROOT kotlinx-coroutines-core/target/dokka/kotlinx-coroutines-core -->
43+
<!--- INDEX kotlinx.coroutines.experimental -->
44+
[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
45+
[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
46+
[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
47+
[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
48+
[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
49+
[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
50+
[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
51+
[java.util.concurrent.Executor.toCoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/java.util.concurrent.-executor/to-coroutine-dispatcher.html
52+
[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
53+
[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
54+
[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
55+
[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
56+
[newFixedThreadPoolContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-fixed-thread-pool-context.html
57+
[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
58+
[run]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run.html
59+
[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
60+
[suspendCancellableCoroutine]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/suspend-cancellable-coroutine.html
61+
[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
62+
[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
63+
<!--- INDEX kotlinx.coroutines.experimental.channels -->
64+
[ProducerJob]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-producer-job/index.html
65+
[ProducerScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-producer-scope/index.html
66+
[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
67+
<!--- END -->
468

569
# Package kotlinx.coroutines.experimental
670

7-
General-purpose coroutine builders and contexts.
8-
9-
* `launch(context) {...}` to start a coroutine in the given context and get reference to its `Job`.
10-
* `run(context) {...}` to switch to a different context inside a coroutine.
11-
* `runBlocking {...}` to use asynchronous Kotlin APIs from a thread-blocking code.
12-
* `async(context) {...}` to get a deferred result of coroutine execution in a
13-
non-blocking way via a light-weight future interface called `Deferred`.
14-
* `delay(...)` for a non-blocking sleep in coroutines and
15-
`yield()` to release a thread in single-threaded dispatchers.
16-
* `withTimeout(timeout) {...}` scope function to easily set coroutine time-limit (deadline),
17-
and `NonCancellable` context to avoid it when needed.
18-
* `CommonPool` and `Unconfined` contexts, access to `context` of a parent coroutine in its `CoroutineScope`.
19-
* `newSingleThreadContext(...)` and `newFixedThreadPoolContext(...)` functions,
20-
`Executor.toCoroutineDispatcher()` extension.
21-
* Cancellation support with `Job` interface and `suspendCancellableCoroutine` helper function.
22-
* Debugging facilities for coroutines (run JVM with `-ea` or `-Dkotlinx.coroutines.debug` options) and
23-
`newCoroutineContext(context)` function to write user-defined coroutine builders that work with these
24-
debugging facilities.
71+
General-purpose coroutine builders, contexts, and helper functions.
2572

2673
# Package kotlinx.coroutines.experimental.channels
2774

28-
Channels -- non-blocking primitives for communicating a stream of values between coroutines.
29-
30-
* `Channel`, `SendChannel`, and `ReceiveChannel` interfaces,
31-
* `RendezvousChannel` (unbuffered) and `ArrayChannel` (buffered) implementations
32-
* `Channel()` factory function and `buildChannel{}` coroutines builder.
75+
Channels -- non-blocking primitives for communicating a stream of elements between coroutines.

0 commit comments

Comments
 (0)