Skip to content

Commit 7699a20

Browse files
authored
Merge pull request #1258 from Kotlin/version-1.3.0-M1
Version 1.3.0-M1
2 parents a97fd43 + 6139ed3 commit 7699a20

File tree

196 files changed

+7858
-1534
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

196 files changed

+7858
-1534
lines changed

CHANGES.md

+38
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
11
# Change log for kotlinx.coroutines
22

3+
## Version 1.3.0-M1
4+
5+
Flow:
6+
* Core `Flow` interfaces and operators are graduated from preview status to experimental.
7+
* Context preservation invariant rework (#1210).
8+
* `channelFlow` and `callbackFlow` replacements for `flowViaChannel` for concurrent flows or callback-based APIs.
9+
* `flow` prohibits emissions from non-scoped coroutines by default and recommends to use `channelFlow` instead to avoid most of the concurrency-related bugs.
10+
* Flow cannot be implemented directly
11+
* `AbstractFlow` is introduced for extension (e.g. for managing state) and ensures all context preservation invariants.
12+
* Buffer size is decoupled from all operators that imply channel usage (#1233)
13+
* `buffer` operator can be used to adjust buffer size of any buffer-dependent operator (e.g. `channelFlow`, `flowOn` and `flatMapMerge`).
14+
* `conflate` operator is introduced.
15+
* Flow performance is significantly improved.
16+
* New operators: `scan`, `scanReduce`, `first`, `emitAll`.
17+
* `flowWith` and `flowViaChannel` are deprecated.
18+
* `retry` ignores cancellation exceptions from upstream when the flow was externally cancelled (#1122).
19+
* `combineLatest` overloads for multiple flows (#1193).
20+
* Fixed numerical overflow in `drop` operator.
21+
22+
Channels:
23+
* `consumeEach` is promoted to experimental API (#1080).
24+
* Conflated channels always deliver the latest value after closing (#332, #1235).
25+
* Non-suspending `ChannelIterator.next` to improve iteration performance (#1162).
26+
* Channel exception types are consistent with `produce` and are no longer swallowed as cancellation exceptions in case of programmatic errors (#957, #1128).
27+
* All operators on channels (that were prone to coroutine leaks) are deprecated in the favor of `Flow`.
28+
29+
General changes:
30+
* Kotlin updated to 1.3.31
31+
* `Semaphore` implementation (#1088)
32+
* Loading of `Dispatchers.Main` is tweaked so the latest version of R8 can completely remove I/O when loading it (#1231).
33+
* Performace of all JS dispatchers is significantly improved (#820).
34+
* `withContext` checks cancellation status on exit to make reasoning about sequential concurrent code easier (#1177).
35+
* Consistent exception handling mechanism for complex hierarchies (#689).
36+
* Convenient overload for `CoroutinesTimeout.seconds` (#1184).
37+
* Fix cancellation bug in onJoin (#1130).
38+
* Prevent internal names clash that caused errors for ProGuard (#1159).
39+
* POSIX's `nanosleep` as `delay` in `runBlocking ` in K/N (#1225).
40+
341
## Version 1.2.1
442

543
Major:

README.md

+12-12
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
[![official JetBrains project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
44
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)
5-
[![Download](https://api.bintray.com/packages/kotlin/kotlinx/kotlinx.coroutines/images/download.svg?version=1.2.1) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.2.1)
5+
[![Download](https://api.bintray.com/packages/kotlin/kotlinx/kotlinx.coroutines/images/download.svg?version=1.3.0-M1) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.3.0-M1)
66

77
Library support for Kotlin coroutines with [multiplatform](#multiplatform) support.
8-
This is a companion version for Kotlin `1.3.30` release.
8+
This is a companion version for Kotlin `1.3.31` release.
99

1010
```kotlin
1111
suspend fun main() = coroutineScope {
@@ -81,15 +81,15 @@ Add dependencies (you can also add other modules that you need):
8181
<dependency>
8282
<groupId>org.jetbrains.kotlinx</groupId>
8383
<artifactId>kotlinx-coroutines-core</artifactId>
84-
<version>1.2.1</version>
84+
<version>1.3.0-M1</version>
8585
</dependency>
8686
```
8787

8888
And make sure that you use the latest Kotlin version:
8989

9090
```xml
9191
<properties>
92-
<kotlin.version>1.3.30</kotlin.version>
92+
<kotlin.version>1.3.31</kotlin.version>
9393
</properties>
9494
```
9595

@@ -99,15 +99,15 @@ Add dependencies (you can also add other modules that you need):
9999

100100
```groovy
101101
dependencies {
102-
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
102+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0-M1'
103103
}
104104
```
105105

106106
And make sure that you use the latest Kotlin version:
107107

108108
```groovy
109109
buildscript {
110-
ext.kotlin_version = '1.3.30'
110+
ext.kotlin_version = '1.3.31'
111111
}
112112
```
113113

@@ -125,15 +125,15 @@ Add dependencies (you can also add other modules that you need):
125125

126126
```groovy
127127
dependencies {
128-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1")
128+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0-M1")
129129
}
130130
```
131131

132132
And make sure that you use the latest Kotlin version:
133133

134134
```groovy
135135
plugins {
136-
kotlin("jvm") version "1.3.30"
136+
kotlin("jvm") version "1.3.31"
137137
}
138138
```
139139

@@ -144,7 +144,7 @@ Make sure that you have either `jcenter()` or `mavenCentral()` in the list of re
144144
Core modules of `kotlinx.coroutines` are also available for
145145
[Kotlin/JS](#js) and [Kotlin/Native](#native).
146146
In common code that should get compiled for different platforms, add dependency to
147-
[`kotlinx-coroutines-core-common`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-common/1.2.1/jar)
147+
[`kotlinx-coroutines-core-common`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-common/1.3.0-M1/jar)
148148
(follow the link to get the dependency declaration snippet).
149149

150150
### Android
@@ -153,7 +153,7 @@ Add [`kotlinx-coroutines-android`](ui/kotlinx-coroutines-android)
153153
module as dependency when using `kotlinx.coroutines` on Android:
154154

155155
```groovy
156-
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1'
156+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0-M1'
157157
```
158158

159159
This gives you access to Android [Dispatchers.Main](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-android/kotlinx.coroutines.android/kotlinx.coroutines.-dispatchers/index.html)
@@ -172,15 +172,15 @@ R8 is a replacement for ProGuard in Android ecosystem, it is enabled by default
172172
### JS
173173

174174
[Kotlin/JS](https://kotlinlang.org/docs/reference/js-overview.html) version of `kotlinx.coroutines` is published as
175-
[`kotlinx-coroutines-core-js`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.2.1/jar)
175+
[`kotlinx-coroutines-core-js`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.3.0-M1/jar)
176176
(follow the link to get the dependency declaration snippet).
177177

178178
You can also use [`kotlinx-coroutines-core`](https://www.npmjs.com/package/kotlinx-coroutines-core) package via NPM.
179179

180180
### Native
181181

182182
[Kotlin/Native](https://kotlinlang.org/docs/reference/native-overview.html) version of `kotlinx.coroutines` is published as
183-
[`kotlinx-coroutines-core-native`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-native/1.2.1/jar)
183+
[`kotlinx-coroutines-core-native`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-native/1.3.0-M1/jar)
184184
(follow the link to get the dependency declaration snippet).
185185

186186
Only single-threaded code (JS-style) on Kotlin/Native is currently supported.

benchmarks/build.gradle

+45-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/*
22
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
33
*/
4+
sourceCompatibility = 1.8
5+
targetCompatibility = 1.8
46

57
apply plugin: "net.ltgt.apt"
68
apply plugin: "com.github.johnrengelman.shadow"
@@ -10,15 +12,50 @@ repositories {
1012
maven { url "https://repo.typesafe.com/typesafe/releases/" }
1113
}
1214

13-
jmh.jmhVersion = '1.21'
15+
compileJmhKotlin {
16+
kotlinOptions {
17+
jvmTarget = "1.8"
18+
freeCompilerArgs += ['-Xjvm-default=enable']
19+
}
20+
}
21+
22+
/*
23+
* Due to a bug in the inliner it sometimes does not remove inlined symbols (that are later renamed) from unused code paths,
24+
* and it breaks JMH that tries to post-process these symbols and fails because they are renamed.
25+
*/
26+
task removeRedundantFiles(type: Delete) {
27+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt\$play\$buildHistoOnScore\$1\$\$special\$\$inlined\$filter\$1\$1.class"
28+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt\$play\$nBlanks\$1\$\$special\$\$inlined\$map\$1\$1.class"
29+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt\$play\$score2\$1\$\$special\$\$inlined\$map\$1\$1.class"
30+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt\$play\$bonusForDoubleLetter\$1\$\$special\$\$inlined\$map\$1\$1.class"
31+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt\$play\$nBlanks\$1\$\$special\$\$inlined\$map\$1\$2\$1.class"
32+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt\$play\$bonusForDoubleLetter\$1\$\$special\$\$inlined\$map\$1\$2\$1.class"
33+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt\$play\$score2\$1\$\$special\$\$inlined\$map\$1\$2\$1.class"
34+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOptKt\$\$special\$\$inlined\$collect\$1\$1.class"
35+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOptKt\$\$special\$\$inlined\$collect\$2\$1.class"
36+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt\$play\$histoOfLetters\$1\$\$special\$\$inlined\$fold\$1\$1.class"
37+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleBase\$play\$buildHistoOnScore\$1\$\$special\$\$inlined\$filter\$1\$1.class"
38+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble/FlowPlaysScrabbleBase\$play\$histoOfLetters\$1\$\$special\$\$inlined\$fold\$1\$1.class"
39+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/scrabble//SaneFlowPlaysScrabble\$play\$buildHistoOnScore\$1\$\$special\$\$inlined\$filter\$1\$1.class"
40+
41+
// Primes
42+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/misc/Numbers\$\$special\$\$inlined\$filter\$1\$2\$1.class"
43+
delete "$buildDir/classes/kotlin/jmh/benchmarks/flow/misc/Numbers\$\$special\$\$inlined\$filter\$1\$1.class"
44+
}
45+
46+
jmhRunBytecodeGenerator.dependsOn(removeRedundantFiles)
1447

1548
// It is better to use the following to run benchmarks, otherwise you may get unexpected errors:
16-
// ../gradlew --no-daemon cleanJmhJar jmh
49+
// ./gradlew --no-daemon cleanJmhJar jmh -Pjmh="MyBenchmark"
1750
jmh {
51+
jmhVersion = '1.21'
1852
duplicateClassesStrategy DuplicatesStrategy.INCLUDE
1953
failOnError = true
2054
resultFormat = 'CSV'
21-
// include = ['.*ChannelProducerConsumer.*']
55+
if (project.hasProperty('jmh')) {
56+
include = ".*" + project.jmh + ".*"
57+
}
58+
// includeTests = false
2259
}
2360

2461
jmhJar {
@@ -29,8 +66,12 @@ jmhJar {
2966
}
3067

3168
dependencies {
69+
compile "org.openjdk.jmh:jmh-core:1.21"
70+
compile "io.projectreactor:reactor-core:$reactor_vesion"
71+
compile 'io.reactivex.rxjava2:rxjava:2.1.9'
72+
compile "com.github.akarnokd:rxjava2-extensions:0.20.8"
73+
3274
compile "org.openjdk.jmh:jmh-core:1.21"
3375
compile 'com.typesafe.akka:akka-actor_2.12:2.5.0'
3476
compile project(':kotlinx-coroutines-core')
3577
}
36-
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package benchmarks.flow.scrabble;
6+
7+
import benchmarks.flow.scrabble.IterableSpliterator;
8+
import benchmarks.flow.scrabble.ShakespearePlaysScrabble;
9+
import io.reactivex.Flowable;
10+
import io.reactivex.Maybe;
11+
import io.reactivex.Single;
12+
import io.reactivex.functions.Function;
13+
import org.openjdk.jmh.annotations.*;
14+
15+
import java.util.*;
16+
import java.util.Map.Entry;
17+
import java.util.concurrent.TimeUnit;
18+
19+
/**
20+
* Shakespeare plays Scrabble with RxJava 2 Flowable.
21+
* @author José
22+
* @author akarnokd
23+
*/
24+
@Warmup(iterations = 7, time = 1, timeUnit = TimeUnit.SECONDS)
25+
@Measurement(iterations = 7, time = 1, timeUnit = TimeUnit.SECONDS)
26+
@Fork(value = 1)
27+
@BenchmarkMode(Mode.AverageTime)
28+
@OutputTimeUnit(TimeUnit.MILLISECONDS)
29+
@State(Scope.Benchmark)
30+
public class RxJava2PlaysScrabble extends ShakespearePlaysScrabble {
31+
32+
@Benchmark
33+
@Override
34+
public List<Entry<Integer, List<String>>> play() throws Exception {
35+
36+
// Function to compute the score of a given word
37+
Function<Integer, Flowable<Integer>> scoreOfALetter = letter -> Flowable.just(letterScores[letter - 'a']) ;
38+
39+
// score of the same letters in a word
40+
Function<Entry<Integer, LongWrapper>, Flowable<Integer>> letterScore =
41+
entry ->
42+
Flowable.just(
43+
letterScores[entry.getKey() - 'a'] *
44+
Integer.min(
45+
(int)entry.getValue().get(),
46+
scrabbleAvailableLetters[entry.getKey() - 'a']
47+
)
48+
) ;
49+
50+
Function<String, Flowable<Integer>> toIntegerFlowable =
51+
string -> Flowable.fromIterable(IterableSpliterator.of(string.chars().boxed().spliterator())) ;
52+
53+
// Histogram of the letters in a given word
54+
Function<String, Single<HashMap<Integer, LongWrapper>>> histoOfLetters =
55+
word -> toIntegerFlowable.apply(word)
56+
.collect(
57+
() -> new HashMap<>(),
58+
(HashMap<Integer, LongWrapper> map, Integer value) ->
59+
{
60+
LongWrapper newValue = map.get(value) ;
61+
if (newValue == null) {
62+
newValue = () -> 0L ;
63+
}
64+
map.put(value, newValue.incAndSet()) ;
65+
}
66+
67+
) ;
68+
69+
// number of blanks for a given letter
70+
Function<Entry<Integer, LongWrapper>, Flowable<Long>> blank =
71+
entry ->
72+
Flowable.just(
73+
Long.max(
74+
0L,
75+
entry.getValue().get() -
76+
scrabbleAvailableLetters[entry.getKey() - 'a']
77+
)
78+
) ;
79+
80+
// number of blanks for a given word
81+
Function<String, Maybe<Long>> nBlanks =
82+
word -> histoOfLetters.apply(word)
83+
.flatMapPublisher(map -> Flowable.fromIterable(() -> map.entrySet().iterator()))
84+
.flatMap(blank)
85+
.reduce(Long::sum) ;
86+
87+
88+
// can a word be written with 2 blanks?
89+
Function<String, Maybe<Boolean>> checkBlanks =
90+
word -> nBlanks.apply(word)
91+
.flatMap(l -> Maybe.just(l <= 2L)) ;
92+
93+
// score taking blanks into account letterScore1
94+
Function<String, Maybe<Integer>> score2 =
95+
word -> histoOfLetters.apply(word)
96+
.flatMapPublisher(map -> Flowable.fromIterable(() -> map.entrySet().iterator()))
97+
.flatMap(letterScore)
98+
.reduce(Integer::sum) ;
99+
100+
// Placing the word on the board
101+
// Building the streams of first and last letters
102+
Function<String, Flowable<Integer>> first3 =
103+
word -> Flowable.fromIterable(IterableSpliterator.of(word.chars().boxed().limit(3).spliterator())) ;
104+
Function<String, Flowable<Integer>> last3 =
105+
word -> Flowable.fromIterable(IterableSpliterator.of(word.chars().boxed().skip(3).spliterator())) ;
106+
107+
108+
// Stream to be maxed
109+
Function<String, Flowable<Integer>> toBeMaxed =
110+
word -> Flowable.just(first3.apply(word), last3.apply(word))
111+
.flatMap(observable -> observable) ;
112+
113+
// Bonus for double letter
114+
Function<String, Maybe<Integer>> bonusForDoubleLetter =
115+
word -> toBeMaxed.apply(word)
116+
.flatMap(scoreOfALetter)
117+
.reduce(Integer::max) ;
118+
119+
// score of the word put on the board
120+
Function<String, Maybe<Integer>> score3 =
121+
word ->
122+
Maybe.merge(Arrays.asList(
123+
score2.apply(word),
124+
score2.apply(word),
125+
bonusForDoubleLetter.apply(word),
126+
bonusForDoubleLetter.apply(word),
127+
Maybe.just(word.length() == 7 ? 50 : 0)
128+
)
129+
)
130+
.reduce(Integer::sum) ;
131+
132+
Function<Function<String, Maybe<Integer>>, Single<TreeMap<Integer, List<String>>>> buildHistoOnScore =
133+
score -> Flowable.fromIterable(() -> shakespeareWords.iterator())
134+
.filter(scrabbleWords::contains)
135+
.filter(word -> checkBlanks.apply(word).blockingGet())
136+
.collect(
137+
() -> new TreeMap<>(Comparator.reverseOrder()),
138+
(TreeMap<Integer, List<String>> map, String word) -> {
139+
Integer key = score.apply(word).blockingGet() ;
140+
List<String> list = map.get(key) ;
141+
if (list == null) {
142+
list = new ArrayList<>() ;
143+
map.put(key, list) ;
144+
}
145+
list.add(word) ;
146+
}
147+
) ;
148+
149+
// best key / value pairs
150+
List<Entry<Integer, List<String>>> finalList2 =
151+
buildHistoOnScore.apply(score3)
152+
.flatMapPublisher(map -> Flowable.fromIterable(() -> map.entrySet().iterator()))
153+
.take(3)
154+
.collect(
155+
() -> new ArrayList<Entry<Integer, List<String>>>(),
156+
(list, entry) -> {
157+
list.add(entry) ;
158+
}
159+
)
160+
.blockingGet() ;
161+
return finalList2 ;
162+
}
163+
}

0 commit comments

Comments
 (0)