Skip to content

Commit ea89e60

Browse files
authored
Merge pull request Kotlin#756 from Kotlin/version-1.0.0
Version 1.0.0
2 parents dd472fc + 8a45c47 commit ea89e60

File tree

17 files changed

+112
-46
lines changed

17 files changed

+112
-46
lines changed

CHANGES.md

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

3+
## Version 1.0.0
4+
5+
* All Kotlin dependencies updated to 1.3 release version.
6+
* Fixed potential memory leak in `HandlerDispatcher.scheduleResumeAfterDelay`, thanks @cbeyls.
7+
* `yield` support for `Unconfined` and immediate dispatchers (#737).
8+
* Various documentation improvements.
9+
310
## Version 1.0.0-RC1
411

512
* Coroutines API is updated to Kotlin 1.3.

COMPATIBILITY.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ In order to migrate `kotlinx.coroutines` to `1.0.0`, follow these steps:
2020

2121
1. Update `kotlinx.coroutines` to `0.30.2` version.
2222
2. Inspect compiler warnings about deprecated API and migrate it to a proposed alternative. Most of deprecated API has a corresponding replacement which can be applied from IDEA with quickfix.
23-
3. Update Kotlin version to `1.3.0` or to the latest `1.3.0-rc` and `kotlinx.coroutines` to version `0.30.2-eap13`. Then just get rid of `experimental` suffix in all imports.
23+
3. Update Kotlin version to `1.3.0` and `kotlinx.coroutines` to version `0.30.2-eap13`. Then just get rid of `experimental` suffix in all imports.
2424
4. Update `kotlinx.coroutines` to version `1.0.0` or to the corresponding release candidate of it).
2525

README.md

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

33
[![official JetBrains project](http://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)](http://www.apache.org/licenses/LICENSE-2.0)
5-
[![Download](https://api.bintray.com/packages/kotlin/kotlinx/kotlinx.coroutines/images/download.svg?version=1.0.0-RC1) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.0.0-RC1)
5+
[![Download](https://api.bintray.com/packages/kotlin/kotlinx/kotlinx.coroutines/images/download.svg?version=1.0.0) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.0.0)
66

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

1010
**NOTE**: `0.30.2` was the last release with Kotlin 1.2 and experimental coroutines.
1111
See [COMPATIBILITY.md](COMPATIBILITY.md) for details of migration onto the stable Kotlin 1.3 coroutines.
@@ -69,35 +69,33 @@ Add dependencies (you can also add other modules that you need):
6969
<dependency>
7070
<groupId>org.jetbrains.kotlinx</groupId>
7171
<artifactId>kotlinx-coroutines-core</artifactId>
72-
<version>1.0.0-RC1</version>
72+
<version>1.0.0</version>
7373
</dependency>
7474
```
7575

7676
And make sure that you use the latest Kotlin version:
7777

7878
```xml
7979
<properties>
80-
<kotlin.version>1.3.0-rc-146</kotlin.version>
80+
<kotlin.version>1.3.0</kotlin.version>
8181
</properties>
8282
```
8383

84-
While Kotlin 1.3 is still in release candidate status, in order to depend on it you should add eap repository: `https://dl.bintray.com/kotlin/kotlin-eap`.
85-
8684
### Gradle
8785

8886
Add dependencies (you can also add other modules that you need):
8987

9088
```groovy
9189
dependencies {
92-
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0-RC1'
90+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'
9391
}
9492
```
9593

9694
And make sure that you use the latest Kotlin version:
9795

9896
```groovy
9997
buildscript {
100-
ext.kotlin_version = '1.3.0-rc-146'
98+
ext.kotlin_version = '1.3.0'
10199
}
102100
```
103101

@@ -115,27 +113,19 @@ Add dependencies (you can also add other modules that you need):
115113

116114
```groovy
117115
dependencies {
118-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0-RC1")
116+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0")
119117
}
120118
```
121119

122120
And make sure that you use the latest Kotlin version:
123121

124122
```groovy
125123
plugins {
126-
kotlin("jvm") version "1.3.0-rc-146"
124+
kotlin("jvm") version "1.3.0"
127125
}
128126
```
129127

130128
Make sure that you have either `jcenter()` or `mavenCentral()` in the list of repositories.
131-
For Kotlin EAP builds you also may need `kotlin-eap` repository:
132-
133-
```
134-
repository {
135-
jcenter()
136-
maven { url "https://kotlin.bintray.com/kotlin-eap" }
137-
}
138-
```
139129

140130
### Multiplatform
141131

@@ -151,7 +141,7 @@ Add [`kotlinx-coroutines-android`](ui/kotlinx-coroutines-android)
151141
module as dependency when using `kotlinx.coroutines` on Android:
152142

153143
```groovy
154-
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0-RC1'
144+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0'
155145
```
156146
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)
157147
coroutine dispatcher and also makes sure that in case of crashed coroutine with unhandled exception this

build.gradle

+9
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,17 @@ allprojects {
5252
kotlin_version = '1.2-SNAPSHOT'
5353
}
5454

55+
def name = it.name
5556
repositories {
57+
/*
58+
* google should be first in the repository list because some of the play services
59+
* transitive dependencies was removed from jcenter, thus breaking gradle dependency resolution
60+
*/
61+
if (name == "kotlinx-coroutines-play-services") {
62+
google()
63+
}
5664
jcenter()
65+
maven { url "https://kotlin.bintray.com/kotlin-dev" }
5766
maven { url "https://kotlin.bintray.com/kotlin-eap" }
5867
maven { url "https://kotlin.bintray.com/kotlinx" }
5968
}

common/kotlinx-coroutines-core-common/src/Dispatched.kt

+23-4
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,40 @@ internal object UndispatchedEventLoop {
2121
@JvmField
2222
internal val threadLocalEventLoop = CommonThreadLocal { EventLoop() }
2323

24-
inline fun execute(continuation: DispatchedContinuation<*>, contState: Any?, mode: Int, block: () -> Unit) {
24+
/**
25+
* Executes given [block] as part of current event loop, updating related to block [continuation]
26+
* mode and state if continuation is not resumed immediately.
27+
* [doYield] indicates whether current continuation is yielding (to provide fast-path if event-loop is empty).
28+
* Returns `true` if execution of continuation was queued (trampolined) or `false` otherwise.
29+
*/
30+
inline fun execute(continuation: DispatchedContinuation<*>, contState: Any?, mode: Int,
31+
doYield: Boolean = false, block: () -> Unit) : Boolean {
2532
val eventLoop = threadLocalEventLoop.get()
2633
if (eventLoop.isActive) {
34+
// If we are yielding and queue is empty, we can bail out as part of fast path
35+
if (doYield && eventLoop.queue.isEmpty) {
36+
return false
37+
}
38+
2739
continuation._state = contState
2840
continuation.resumeMode = mode
2941
eventLoop.queue.addLast(continuation)
30-
return
42+
return true
3143
}
3244

3345
runEventLoop(eventLoop, block)
46+
return false
3447
}
3548

36-
fun resumeUndispatched(task: DispatchedTask<*>) {
49+
fun resumeUndispatched(task: DispatchedTask<*>): Boolean {
3750
val eventLoop = threadLocalEventLoop.get()
3851
if (eventLoop.isActive) {
3952
eventLoop.queue.addLast(task)
40-
return
53+
return true
4154
}
4255

4356
runEventLoop(eventLoop, { task.resume(task.delegate, MODE_UNDISPATCHED) })
57+
return false
4458
}
4559

4660
inline fun runEventLoop(eventLoop: EventLoop, block: () -> Unit) {
@@ -227,6 +241,11 @@ internal interface DispatchedTask<in T> : Runnable {
227241
}
228242
}
229243

244+
internal fun DispatchedContinuation<Unit>.yieldUndispatched(): Boolean =
245+
UndispatchedEventLoop.execute(this, Unit, MODE_CANCELLABLE, doYield = true) {
246+
run()
247+
}
248+
230249
internal fun <T> DispatchedTask<T>.dispatch(mode: Int = MODE_CANCELLABLE) {
231250
val delegate = this.delegate
232251
if (mode.isDispatchedMode && delegate is DispatchedContinuation<*> && mode.isCancellableMode == resumeMode.isCancellableMode) {

common/kotlinx-coroutines-core-common/src/Yield.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ public suspend fun yield(): Unit = suspendCoroutineUninterceptedOrReturn sc@ { u
1919
val context = uCont.context
2020
context.checkCompletion()
2121
val cont = uCont.intercepted() as? DispatchedContinuation<Unit> ?: return@sc Unit
22-
if (!cont.dispatcher.isDispatchNeeded(context)) return@sc Unit
22+
if (!cont.dispatcher.isDispatchNeeded(context)) {
23+
return@sc if (cont.yieldUndispatched()) COROUTINE_SUSPENDED else Unit
24+
}
2325
cont.dispatchYield(Unit)
2426
COROUTINE_SUSPENDED
2527
}

common/kotlinx-coroutines-core-common/src/channels/Channel.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,9 @@ public interface ReceiveChannel<out E> {
210210
* **Note: This is an obsolete api.**
211211
* This function will be replaced with `receiveOrClosed: ReceiveResult<E>` and
212212
* extension `suspend fun <E: Any> ReceiveChannel<E>.receiveOrNull(): E?`
213+
* It is obsolete because it does not distinguish closed channel and null elements.
213214
*/
214-
@ExperimentalCoroutinesApi
215215
@ObsoleteCoroutinesApi
216-
@Deprecated(level = DeprecationLevel.WARNING, message = "This method does not distinguish closed channel and null elements")
217216
public suspend fun receiveOrNull(): E?
218217

219218
/**

common/kotlinx-coroutines-core-common/src/internal/ArrayQueue.kt

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ internal class ArrayQueue<T : Any> {
88
private var elements = arrayOfNulls<Any>(16)
99
private var head = 0
1010
private var tail = 0
11+
val isEmpty: Boolean get() = head == tail
1112

1213
public fun addLast(element: T) {
1314
elements[tail] = element

common/kotlinx-coroutines-core-common/test/UnconfinedTest.kt

+42-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class UnconfinedTest : TestBase() {
5454
}
5555

5656
@Test
57-
fun enterMultipleTimes() = runTest {
57+
fun testEnterMultipleTimes() = runTest {
5858
launch(Unconfined) {
5959
expect(1)
6060
}
@@ -70,5 +70,46 @@ class UnconfinedTest : TestBase() {
7070
finish(4)
7171
}
7272

73+
@Test
74+
fun testYield() = runTest {
75+
expect(1)
76+
launch(Dispatchers.Unconfined) {
77+
expect(2)
78+
yield()
79+
launch {
80+
expect(4)
81+
}
82+
expect(3)
83+
yield()
84+
expect(5)
85+
}.join()
86+
87+
finish(6)
88+
}
89+
90+
@Test
91+
fun testCancellationWihYields() = runTest {
92+
expect(1)
93+
GlobalScope.launch(Dispatchers.Unconfined) {
94+
val job = coroutineContext[Job]!!
95+
expect(2)
96+
yield()
97+
GlobalScope.launch(Dispatchers.Unconfined) {
98+
expect(4)
99+
job.cancel()
100+
expect(5)
101+
}
102+
expect(3)
103+
104+
try {
105+
yield()
106+
} finally {
107+
expect(6)
108+
}
109+
}
110+
111+
finish(7)
112+
}
113+
73114
class TestException : Throwable()
74115
}

core/kotlinx-coroutines-core/test/UnconfinedConcurrentStressTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ class UnconfinedConcurrentStressTest : TestBase() {
1919
executor.close()
2020
}
2121

22-
@Test(timeout = 10_000L)
22+
@Test
2323
fun testConcurrent() = runTest {
24-
val iterations = 10_000 * stressTestMultiplier
24+
val iterations = 1_000 * stressTestMultiplier
2525
val startBarrier = CyclicBarrier(threads + 1)
2626
val finishLatch = CountDownLatch(threads)
2727

gradle.properties

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# Kotlin
2-
version=1.0.0-RC1-SNAPSHOT
2+
version=1.0.0-SNAPSHOT
33
group=org.jetbrains.kotlinx
4-
kotlin_version=1.3.0-rc-146
5-
kotlin_native_version=1.3.0-rc-146
4+
kotlin_version=1.3.0
5+
kotlin_native_version=1.3.0-rc-208
66

77
# Dependencies
88
junit_version=4.12
9-
atomicFU_version=0.11.11
9+
atomicFU_version=0.11.12
1010
html_version=0.6.8
1111
lincheck_version=1.9
1212
dokka_version=0.9.16-rdev-2-mpp-hacks

integration/kotlinx-coroutines-play-services/build.gradle

-4
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ import java.util.zip.ZipFile
99

1010
ext.tasks_version = '15.0.1'
1111

12-
repositories {
13-
google()
14-
}
15-
1612
def attr = Attribute.of("artifactType", String.class)
1713
configurations {
1814
aar {

native/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ repositories {
4242
}
4343
4444
dependencies {
45-
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.0.0-RC1'
45+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.0.0'
4646
}
4747
4848
sourceSets {

ui/coroutines-guide-ui.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ Add dependencies on `kotlinx-coroutines-android` module to the `dependencies { .
165165
`app/build.gradle` file:
166166

167167
```groovy
168-
compile "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0-RC1"
168+
compile "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0"
169169
```
170170

171171
You can clone [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines) project from GitHub onto your

ui/kotlinx-coroutines-android/animation-app/gradle.properties

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ org.gradle.jvmargs=-Xmx1536m
1818

1919
kotlin.coroutines=enable
2020

21-
kotlin_version=1.3.0-rc-146
22-
coroutines_version=1.0.0-RC1
21+
kotlin_version=1.3.0
22+
coroutines_version=1.0.0
2323

ui/kotlinx-coroutines-android/example-app/gradle.properties

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ org.gradle.jvmargs=-Xmx1536m
1818

1919
kotlin.coroutines=enable
2020

21-
kotlin_version=1.3.0-rc-146
22-
coroutines_version=1.0.0-RC1
21+
kotlin_version=1.3.0
22+
coroutines_version=1.0.0
2323

ui/kotlinx-coroutines-android/src/HandlerDispatcher.kt

+4-2
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,11 @@ internal class HandlerContext private constructor(
120120
}
121121

122122
override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
123-
handler.postDelayed({
123+
val block = Runnable {
124124
with(continuation) { resumeUndispatched(Unit) }
125-
}, timeMillis.coerceAtMost(MAX_DELAY))
125+
}
126+
handler.postDelayed(block, timeMillis.coerceAtMost(MAX_DELAY))
127+
continuation.invokeOnCancellation { handler.removeCallbacks(block) }
126128
}
127129

128130
override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {

0 commit comments

Comments
 (0)