Skip to content

Commit 162c461

Browse files
committed
Make call to service loader in reactor integrations optimizable by R8
Fixes #1817
1 parent d7de5f5 commit 162c461

File tree

4 files changed

+10
-19
lines changed

4 files changed

+10
-19
lines changed

reactive/kotlinx-coroutines-reactive/src/Await.kt

-10
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,6 @@ public suspend fun <T> Publisher<T>.awaitSingle(): T = awaitOne(Mode.SINGLE)
8282

8383
// ------------------------ private ------------------------
8484

85-
// ContextInjector service is implemented in `kotlinx-coroutines-reactor` module only.
86-
// If `kotlinx-coroutines-reactor` module is not included, the list is empty.
87-
private val contextInjectors: Array<ContextInjector> =
88-
ServiceLoader.load(ContextInjector::class.java, ContextInjector::class.java.classLoader).iterator().asSequence().toList().toTypedArray() // R8 opto
89-
90-
private fun <T> Publisher<T>.injectCoroutineContext(coroutineContext: CoroutineContext) =
91-
contextInjectors.fold(this) { pub, contextInjector ->
92-
contextInjector.injectCoroutineContext(pub, coroutineContext)
93-
}
94-
9585
private enum class Mode(val s: String) {
9686
FIRST("awaitFirst"),
9787
FIRST_OR_DEFAULT("awaitFirstOrDefault"),

reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt

+5-4
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,14 @@ private class ReactiveSubscriber<T : Any>(
140140

141141
// ContextInjector service is implemented in `kotlinx-coroutines-reactor` module only.
142142
// If `kotlinx-coroutines-reactor` module is not included, the list is empty.
143-
private val contextInjectors: List<ContextInjector> =
144-
ServiceLoader.load(ContextInjector::class.java, ContextInjector::class.java.classLoader).toList()
143+
private val contextInjectors: Array<ContextInjector> =
144+
ServiceLoader.load(ContextInjector::class.java, ContextInjector::class.java.classLoader)
145+
.iterator().asSequence()
146+
.toList().toTypedArray() // R8 opto
145147

146-
private fun <T> Publisher<T>.injectCoroutineContext(coroutineContext: CoroutineContext) =
148+
internal fun <T> Publisher<T>.injectCoroutineContext(coroutineContext: CoroutineContext) =
147149
contextInjectors.fold(this) { pub, contextInjector -> contextInjector.injectCoroutineContext(pub, coroutineContext) }
148150

149-
150151
/**
151152
* Adapter that transforms [Flow] into TCK-complaint [Publisher].
152153
* [cancel] invocation cancels the original flow.

ui/kotlinx-coroutines-android/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ task runR8(type: RunR8Task, dependsOn: 'jar'){
7777
inputConfig = file('testdata/r8-test-rules.pro')
7878
}
7979

80-
task runR8NoOptim(type: RunR8Task, dependsOn: 'jar'){
80+
task runR8NoOptim(type: RunR8Task, dependsOn: 'jar') {
8181
outputDex = unOptimizedDexDir
8282
inputConfig = file('testdata/r8-test-rules-no-optim.pro')
8383
}
@@ -103,4 +103,4 @@ tasks.withType(dokka.getClass()) {
103103
url = new URL("https://developer.android.com/reference/")
104104
packageListUrl = projectDir.toPath().resolve("package.list").toUri().toURL()
105105
}
106-
}
106+
}

ui/kotlinx-coroutines-android/test/R8ServiceLoaderOptimizationTest.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class R8ServiceLoaderOptimizationTest : TestBase() {
1616
private val r8DexNoOptim = File(System.getProperty("noOptimDexPath")!!).asDexFile()
1717

1818
@Test
19-
fun noServiceLoaderCalls() {
19+
fun testNoServiceLoaderCalls() {
2020
val serviceLoaderInvocations = r8Dex.types.any {
2121
it.type == "Ljava/util/ServiceLoader;"
2222
}
@@ -28,7 +28,7 @@ class R8ServiceLoaderOptimizationTest : TestBase() {
2828
}
2929

3030
@Test
31-
fun androidDispatcherIsKept() {
31+
fun testAndroidDispatcherIsKept() {
3232
val hasAndroidDispatcher = r8DexNoOptim.classes.any {
3333
it.type == "Lkotlinx/coroutines/android/AndroidDispatcherFactory;"
3434
}
@@ -38,7 +38,7 @@ class R8ServiceLoaderOptimizationTest : TestBase() {
3838

3939
@Test
4040
@Ignore
41-
fun noOptimRulesMatch() {
41+
fun testNoOptimRulesMatch() {
4242
val paths = listOf(
4343
"META-INF/com.android.tools/proguard/coroutines.pro",
4444
"META-INF/proguard/coroutines.pro",

0 commit comments

Comments
 (0)