[TMP] Remove :kotlin-coroutines-experimental-compat module
This commit is contained in:
+2
-4
@@ -333,8 +333,7 @@ val coreLibProjects = listOfNotNull(
|
|||||||
":kotlin-test:kotlin-test-junit5",
|
":kotlin-test:kotlin-test-junit5",
|
||||||
":kotlin-test:kotlin-test-testng",
|
":kotlin-test:kotlin-test-testng",
|
||||||
":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
|
":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
|
||||||
":kotlin-reflect",
|
":kotlin-reflect"
|
||||||
":kotlin-coroutines-experimental-compat"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val gradlePluginProjects = listOf(
|
val gradlePluginProjects = listOf(
|
||||||
@@ -944,8 +943,7 @@ tasks {
|
|||||||
":kotlin-reflect:publish",
|
":kotlin-reflect:publish",
|
||||||
":kotlin-main-kts:publish",
|
":kotlin-main-kts:publish",
|
||||||
":kotlin-stdlib-js:publish",
|
":kotlin-stdlib-js:publish",
|
||||||
":kotlin-test:kotlin-test-js:publish",
|
":kotlin-test:kotlin-test-js:publish"
|
||||||
":kotlin-coroutines-experimental-compat:publish"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-5
@@ -100,11 +100,6 @@ public class ForTestCompileRuntime {
|
|||||||
return assertExists(new File("dist/kotlinc/lib/kotlin-annotations-android.jar"));
|
return assertExists(new File("dist/kotlinc/lib/kotlin-annotations-android.jar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static File coroutinesCompatForTests() {
|
|
||||||
return assertExists(new File("dist/kotlinc/lib/kotlin-coroutines-experimental-compat.jar"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static File assertExists(@NotNull File file) {
|
private static File assertExists(@NotNull File file) {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
|
|||||||
+1
-4
@@ -93,10 +93,7 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest
|
|||||||
@NotNull
|
@NotNull
|
||||||
private URLClassLoader createGeneratedClassLoader() throws Exception {
|
private URLClassLoader createGeneratedClassLoader() throws Exception {
|
||||||
return new URLClassLoader(
|
return new URLClassLoader(
|
||||||
new URL[]{
|
new URL[]{bDir.toURI().toURL(), aDir.toURI().toURL()},
|
||||||
bDir.toURI().toURL(), aDir.toURI().toURL(),
|
|
||||||
ForTestCompileRuntime.coroutinesCompatForTests().toURI().toURL()
|
|
||||||
},
|
|
||||||
ForTestCompileRuntime.runtimeAndReflectJarClassLoader()
|
ForTestCompileRuntime.runtimeAndReflectJarClassLoader()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,6 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
|
|||||||
if (additionalDependencies != null) {
|
if (additionalDependencies != null) {
|
||||||
files.addAll(additionalDependencies);
|
files.addAll(additionalDependencies);
|
||||||
}
|
}
|
||||||
files.addAll(getExtraDependenciesFromKotlinCompileClasspath());
|
|
||||||
|
|
||||||
ScriptDependenciesProvider externalImportsProvider =
|
ScriptDependenciesProvider externalImportsProvider =
|
||||||
ScriptDependenciesProvider.Companion.getInstance(myEnvironment.getProject());
|
ScriptDependenciesProvider.Companion.getInstance(myEnvironment.getProject());
|
||||||
@@ -262,20 +261,6 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<File> getExtraDependenciesFromKotlinCompileClasspath() {
|
|
||||||
List<File> includeFromCompileClasspath = CollectionsKt.listOf(
|
|
||||||
ForTestCompileRuntime.coroutinesCompatForTests()
|
|
||||||
);
|
|
||||||
List<File> compileClasspath =
|
|
||||||
CollectionsKt.map(
|
|
||||||
CollectionsKt.filterIsInstance(
|
|
||||||
myEnvironment.getConfiguration().get(CLIConfigurationKeys.CONTENT_ROOTS),
|
|
||||||
JvmClasspathRoot.class),
|
|
||||||
JvmClasspathRoot::getFile);
|
|
||||||
return CollectionsKt.intersect(compileClasspath, includeFromCompileClasspath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected String generateToText() {
|
protected String generateToText() {
|
||||||
return generateToText(null);
|
return generateToText(null);
|
||||||
@@ -483,7 +468,6 @@ public abstract class CodegenTestCase extends KotlinBaseTest<KotlinBaseTest.Test
|
|||||||
if (loadAndroidAnnotations) {
|
if (loadAndroidAnnotations) {
|
||||||
javaClasspath.add(ForTestCompileRuntime.androidAnnotationsForTests().getPath());
|
javaClasspath.add(ForTestCompileRuntime.androidAnnotationsForTests().getPath());
|
||||||
}
|
}
|
||||||
javaClasspath.addAll(CollectionsKt.map(getExtraDependenciesFromKotlinCompileClasspath(), File::getPath));
|
|
||||||
updateJavaClasspath(javaClasspath);
|
updateJavaClasspath(javaClasspath);
|
||||||
|
|
||||||
javaClassesOutputDirectory = getJavaClassesOutputDirectory();
|
javaClassesOutputDirectory = getJavaClassesOutputDirectory();
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
|
|||||||
usePreparsedDirectives: Boolean
|
usePreparsedDirectives: Boolean
|
||||||
) {
|
) {
|
||||||
var explicitLanguageVersionSettings: LanguageVersionSettings? = null
|
var explicitLanguageVersionSettings: LanguageVersionSettings? = null
|
||||||
var includeCompatExperimentalCoroutines = false
|
|
||||||
val kotlinConfigurationFlags: MutableList<String> = ArrayList(0)
|
val kotlinConfigurationFlags: MutableList<String> = ArrayList(0)
|
||||||
for (testFile in testFilesWithConfigurationDirectives) {
|
for (testFile in testFilesWithConfigurationDirectives) {
|
||||||
val content = testFile.content
|
val content = testFile.content
|
||||||
@@ -171,18 +170,12 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
|
|||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (content.contains(StandardNames.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.asString())) {
|
|
||||||
includeCompatExperimentalCoroutines = true
|
|
||||||
}
|
|
||||||
val fileLanguageVersionSettings: LanguageVersionSettings? = parseLanguageVersionSettings(directives)
|
val fileLanguageVersionSettings: LanguageVersionSettings? = parseLanguageVersionSettings(directives)
|
||||||
if (fileLanguageVersionSettings != null) {
|
if (fileLanguageVersionSettings != null) {
|
||||||
assert(explicitLanguageVersionSettings == null) { "Should not specify !LANGUAGE directive twice" }
|
assert(explicitLanguageVersionSettings == null) { "Should not specify !LANGUAGE directive twice" }
|
||||||
explicitLanguageVersionSettings = fileLanguageVersionSettings
|
explicitLanguageVersionSettings = fileLanguageVersionSettings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (includeCompatExperimentalCoroutines) {
|
|
||||||
configuration.addJvmClasspathRoot(ForTestCompileRuntime.coroutinesCompatForTests())
|
|
||||||
}
|
|
||||||
if (explicitLanguageVersionSettings != null) {
|
if (explicitLanguageVersionSettings != null) {
|
||||||
configuration.languageVersionSettings = explicitLanguageVersionSettings
|
configuration.languageVersionSettings = explicitLanguageVersionSettings
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ dependencies {
|
|||||||
compileOnly(intellijPluginDep("Groovy"))
|
compileOnly(intellijPluginDep("Groovy"))
|
||||||
compileOnly(intellijPluginDep("junit"))
|
compileOnly(intellijPluginDep("junit"))
|
||||||
compileOnly(intellijPluginDep("testng"))
|
compileOnly(intellijPluginDep("testng"))
|
||||||
runtimeOnly(project(":kotlin-coroutines-experimental-compat"))
|
|
||||||
|
|
||||||
compileOnly(project(":kotlin-gradle-statistics"))
|
compileOnly(project(":kotlin-gradle-statistics"))
|
||||||
|
|
||||||
@@ -125,4 +124,4 @@ if (Ide.AS41.orHigher()) {
|
|||||||
getOrCreateTask<Test>("test") {
|
getOrCreateTask<Test>("test") {
|
||||||
setExcludes(listOf("**"))
|
setExcludes(listOf("**"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -40,8 +40,7 @@ public class KotlinWithJdkAndRuntimeLightProjectDescriptor extends KotlinJdkAndL
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static final KotlinWithJdkAndRuntimeLightProjectDescriptor INSTANCE = new KotlinWithJdkAndRuntimeLightProjectDescriptor(
|
public static final KotlinWithJdkAndRuntimeLightProjectDescriptor INSTANCE = new KotlinWithJdkAndRuntimeLightProjectDescriptor(
|
||||||
Arrays.asList(ForTestCompileRuntime.runtimeJarForTests(),
|
Arrays.asList(ForTestCompileRuntime.runtimeJarForTests())
|
||||||
ForTestCompileRuntime.coroutinesCompatForTests())
|
|
||||||
);
|
);
|
||||||
|
|
||||||
public static KotlinWithJdkAndRuntimeLightProjectDescriptor getInstance(LanguageLevel level) {
|
public static KotlinWithJdkAndRuntimeLightProjectDescriptor getInstance(LanguageLevel level) {
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
kotlin("jvm")
|
|
||||||
}
|
|
||||||
|
|
||||||
publish()
|
|
||||||
|
|
||||||
description = "Kotlin pre 1.3 experimental coroutines compatibility library"
|
|
||||||
|
|
||||||
jvmTarget = "1.6"
|
|
||||||
javaHome = rootProject.extra["JDK_16"] as String
|
|
||||||
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
"main" {
|
|
||||||
java.srcDirs("src", "jvm/src")
|
|
||||||
}
|
|
||||||
"test" {
|
|
||||||
java.srcDirs("jvm/test")
|
|
||||||
}
|
|
||||||
"migrationTest" {
|
|
||||||
if(!kotlinBuildProperties.isInIdeaSync)
|
|
||||||
java.srcDirs("jvm/test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val migrationTestSourceSet = sourceSets["migrationTest"]
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
"migrationTestImplementation" {
|
|
||||||
extendsFrom(testImplementation.get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
api(kotlinStdlib())
|
|
||||||
testImplementation(project(":kotlin-test:kotlin-test-junit"))
|
|
||||||
"migrationTestImplementation"(sourceSets.main.get().output)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
val compileKotlin by existing(KotlinCompile::class) {
|
|
||||||
kotlinOptions {
|
|
||||||
languageVersion = "1.3"
|
|
||||||
apiVersion = "1.3"
|
|
||||||
freeCompilerArgs = listOf(
|
|
||||||
"-Xmulti-platform",
|
|
||||||
"-Xallow-kotlin-package",
|
|
||||||
"-Xmultifile-parts-inherit",
|
|
||||||
"-Xopt-in=kotlin.RequiresOptIn",
|
|
||||||
"-Xopt-in=kotlin.contracts.ExperimentalContracts",
|
|
||||||
"-Xcoroutines=enable",
|
|
||||||
"-XXLanguage:-ReleaseCoroutines",
|
|
||||||
"-Xno-use-ir",
|
|
||||||
"-Xuse-old-backend"
|
|
||||||
)
|
|
||||||
moduleName = "kotlin-coroutines-experimental-compat"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val compileTestKotlin by existing(KotlinCompile::class) {
|
|
||||||
kotlinOptions {
|
|
||||||
languageVersion = "1.2"
|
|
||||||
apiVersion = "1.2"
|
|
||||||
freeCompilerArgs = listOf(
|
|
||||||
"-Xcoroutines=enable",
|
|
||||||
"-Xno-use-ir",
|
|
||||||
"-Xuse-old-backend"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val compileMigrationTestKotlin by existing(KotlinCompile::class) {
|
|
||||||
kotlinOptions {
|
|
||||||
languageVersion = "1.3"
|
|
||||||
apiVersion = "1.3"
|
|
||||||
freeCompilerArgs = listOf(
|
|
||||||
"-Xno-use-ir",
|
|
||||||
"-Xuse-old-backend"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val migrationTestClasses by existing
|
|
||||||
val migrationTest by creating(Test::class) {
|
|
||||||
dependsOn(migrationTestClasses)
|
|
||||||
group = "verification"
|
|
||||||
testClassesDirs = migrationTestSourceSet.output.classesDirs
|
|
||||||
classpath = migrationTestSourceSet.runtimeClasspath
|
|
||||||
}
|
|
||||||
|
|
||||||
val check by existing {
|
|
||||||
dependsOn(migrationTest)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val jar by existing(Jar::class) {
|
|
||||||
callGroovy("manifestAttributes", manifest, project, "Main")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sourcesJar()
|
|
||||||
javadocJar()
|
|
||||||
-81
@@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
|
||||||
import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal actual class SafeContinuation<in T>
|
|
||||||
internal actual constructor(
|
|
||||||
private val delegate: Continuation<T>,
|
|
||||||
initialResult: Any?
|
|
||||||
) : Continuation<T> {
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal actual constructor(delegate: Continuation<T>) : this(delegate, UNDECIDED)
|
|
||||||
|
|
||||||
public actual override val context: CoroutineContext
|
|
||||||
get() = delegate.context
|
|
||||||
|
|
||||||
@Volatile
|
|
||||||
private var result: Any? = initialResult
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val UNDECIDED: Any? = Any()
|
|
||||||
private val RESUMED: Any? = Any()
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
@JvmStatic
|
|
||||||
private val RESULT = AtomicReferenceFieldUpdater.newUpdater<SafeContinuation<*>, Any?>(
|
|
||||||
SafeContinuation::class.java, Any::class.java as Class<Any?>, "result"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Fail(val exception: Throwable)
|
|
||||||
|
|
||||||
actual override fun resume(value: T) {
|
|
||||||
while (true) { // lock-free loop
|
|
||||||
val result = this.result // atomic read
|
|
||||||
when {
|
|
||||||
result === UNDECIDED -> if (RESULT.compareAndSet(this, UNDECIDED, value)) return
|
|
||||||
result === COROUTINE_SUSPENDED -> if (RESULT.compareAndSet(this, COROUTINE_SUSPENDED, RESUMED)) {
|
|
||||||
delegate.resume(value)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
else -> throw IllegalStateException("Already resumed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actual override fun resumeWithException(exception: Throwable) {
|
|
||||||
while (true) { // lock-free loop
|
|
||||||
val result = this.result // atomic read
|
|
||||||
when {
|
|
||||||
result === UNDECIDED -> if (RESULT.compareAndSet(this, UNDECIDED, Fail(exception))) return
|
|
||||||
result === COROUTINE_SUSPENDED -> if (RESULT.compareAndSet(this, COROUTINE_SUSPENDED, RESUMED)) {
|
|
||||||
delegate.resumeWithException(exception)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
else -> throw IllegalStateException("Already resumed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal actual fun getResult(): Any? {
|
|
||||||
var result = this.result // atomic read
|
|
||||||
if (result === UNDECIDED) {
|
|
||||||
if (RESULT.compareAndSet(this, UNDECIDED, COROUTINE_SUSPENDED)) return COROUTINE_SUSPENDED
|
|
||||||
result = this.result // reread volatile var
|
|
||||||
}
|
|
||||||
when {
|
|
||||||
result === RESUMED -> return COROUTINE_SUSPENDED // already called continuation, indicate COROUTINE_SUSPENDED upstream
|
|
||||||
result is Fail -> throw result.exception
|
|
||||||
else -> return result // either COROUTINE_SUSPENDED or data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-119
@@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:kotlin.jvm.JvmName("IntrinsicsKt")
|
|
||||||
@file:kotlin.jvm.JvmMultifileClass
|
|
||||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental.intrinsics
|
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts unintercepted coroutine without receiver and with result type [T] and executes it until its first suspension.
|
|
||||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
|
||||||
* In the latter case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
* This function is designed to be used from inside of [suspendCoroutineOrReturn] to resume the execution of a suspended
|
|
||||||
* coroutine using a reference to the suspending function.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
@kotlin.internal.InlineOnly
|
|
||||||
public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Any? = (this as Function1<Continuation<T>, Any?>).invoke(completion)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension.
|
|
||||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
|
||||||
* In the latter case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
* This function is designed to be used from inside of [suspendCoroutineOrReturn] to resume the execution of a suspended
|
|
||||||
* coroutine using a reference to the suspending function.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
@kotlin.internal.InlineOnly
|
|
||||||
public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
|
|
||||||
receiver: R,
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Any? = (this as Function2<R, Continuation<T>, Any?>).invoke(receiver, completion)
|
|
||||||
|
|
||||||
|
|
||||||
// JVM declarations
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a coroutine without receiver and with result type [T].
|
|
||||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
|
||||||
*
|
|
||||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
|
||||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
*
|
|
||||||
* This function is _unchecked_. Repeated invocation of any resume function on the resulting continuation corrupts the
|
|
||||||
* state machine of the coroutine and may result in arbitrary behaviour or exception.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public actual fun <T> (suspend () -> T).createCoroutineUnchecked(
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Continuation<Unit> =
|
|
||||||
if (this !is kotlin.coroutines.experimental.jvm.internal.CoroutineImpl)
|
|
||||||
buildContinuationByInvokeCall(completion) {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
(this as Function1<Continuation<T>, Any?>).invoke(completion)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
(this.create(completion) as kotlin.coroutines.experimental.jvm.internal.CoroutineImpl).facade
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a coroutine with receiver type [R] and result type [T].
|
|
||||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
|
||||||
*
|
|
||||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
|
||||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
*
|
|
||||||
* This function is _unchecked_. Repeated invocation of any resume function on the resulting continuation corrupts the
|
|
||||||
* state machine of the coroutine and may result in arbitrary behaviour or exception.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public actual fun <R, T> (suspend R.() -> T).createCoroutineUnchecked(
|
|
||||||
receiver: R,
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Continuation<Unit> =
|
|
||||||
if (this !is kotlin.coroutines.experimental.jvm.internal.CoroutineImpl)
|
|
||||||
buildContinuationByInvokeCall(completion) {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
(this as Function2<R, Continuation<T>, Any?>).invoke(receiver, completion)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
(this.create(receiver, completion) as kotlin.coroutines.experimental.jvm.internal.CoroutineImpl).facade
|
|
||||||
|
|
||||||
// INTERNAL DEFINITIONS
|
|
||||||
|
|
||||||
private inline fun <T> buildContinuationByInvokeCall(
|
|
||||||
completion: Continuation<T>,
|
|
||||||
crossinline block: () -> Any?
|
|
||||||
): Continuation<Unit> {
|
|
||||||
val continuation =
|
|
||||||
object : Continuation<Unit> {
|
|
||||||
override val context: CoroutineContext
|
|
||||||
get() = completion.context
|
|
||||||
|
|
||||||
override fun resume(value: Unit) {
|
|
||||||
processBareContinuationResume(completion, block)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resumeWithException(exception: Throwable) {
|
|
||||||
completion.resumeWithException(exception)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return kotlin.coroutines.experimental.jvm.internal.interceptContinuationIfNeeded(completion.context, continuation)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This value is used as a return value of [suspendCoroutineOrReturn] `block` argument to state that
|
|
||||||
* the execution was suspended and will not return any result immediately.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public actual val COROUTINE_SUSPENDED: Any get() = kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
|
|
||||||
-61
@@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental.jvm.internal
|
|
||||||
|
|
||||||
import java.lang.IllegalStateException
|
|
||||||
import kotlin.coroutines.experimental.Continuation
|
|
||||||
import kotlin.coroutines.experimental.CoroutineContext
|
|
||||||
import kotlin.coroutines.experimental.processBareContinuationResume
|
|
||||||
import kotlin.jvm.internal.Lambda
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
abstract class CoroutineImpl(
|
|
||||||
arity: Int,
|
|
||||||
@JvmField
|
|
||||||
protected var completion: Continuation<Any?>?
|
|
||||||
) : Lambda<Any?>(arity), Continuation<Any?> {
|
|
||||||
|
|
||||||
// label == -1 when coroutine cannot be started (it is just a factory object) or has already finished execution
|
|
||||||
// label == 0 in initial part of the coroutine
|
|
||||||
@JvmField
|
|
||||||
protected var label: Int = if (completion != null) 0 else -1
|
|
||||||
|
|
||||||
private val _context: CoroutineContext? = completion?.context
|
|
||||||
|
|
||||||
override val context: CoroutineContext
|
|
||||||
get() = _context!!
|
|
||||||
|
|
||||||
private var _facade: Continuation<Any?>? = null
|
|
||||||
|
|
||||||
val facade: Continuation<Any?> get() {
|
|
||||||
if (_facade == null) _facade = interceptContinuationIfNeeded(_context!!, this)
|
|
||||||
return _facade!!
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resume(value: Any?) {
|
|
||||||
processBareContinuationResume(completion!!) {
|
|
||||||
doResume(value, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resumeWithException(exception: Throwable) {
|
|
||||||
processBareContinuationResume(completion!!) {
|
|
||||||
doResume(null, exception)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun doResume(data: Any?, exception: Throwable?): Any?
|
|
||||||
|
|
||||||
open fun create(completion: Continuation<*>): Continuation<Unit> {
|
|
||||||
throw IllegalStateException("create(Continuation) has not been overridden")
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun create(value: Any?, completion: Continuation<*>): Continuation<Unit> {
|
|
||||||
throw IllegalStateException("create(Any?;Continuation) has not been overridden")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:JvmName("CoroutineIntrinsics")
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental.jvm.internal
|
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.Continuation
|
|
||||||
import kotlin.coroutines.experimental.ContinuationInterceptor
|
|
||||||
import kotlin.coroutines.experimental.CoroutineContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
fun <T> normalizeContinuation(continuation: Continuation<T>): Continuation<T> =
|
|
||||||
(continuation as? CoroutineImpl)?.facade ?: continuation
|
|
||||||
|
|
||||||
internal fun <T> interceptContinuationIfNeeded(
|
|
||||||
context: CoroutineContext,
|
|
||||||
continuation: Continuation<T>
|
|
||||||
) = context[ContinuationInterceptor]?.interceptContinuation(continuation) ?: continuation
|
|
||||||
-144
@@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental.migration
|
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.Continuation as ExperimentalContinuation
|
|
||||||
import kotlin.coroutines.experimental.CoroutineContext as ExperimentalCoroutineContext
|
|
||||||
import kotlin.coroutines.experimental.AbstractCoroutineContextElement as ExperimentalAbstractCoroutineContextElement
|
|
||||||
import kotlin.coroutines.experimental.EmptyCoroutineContext as ExperimentalEmptyCoroutineContext
|
|
||||||
import kotlin.coroutines.experimental.ContinuationInterceptor as ExperimentalContinuationInterceptor
|
|
||||||
import kotlin.coroutines.*
|
|
||||||
import kotlin.coroutines.intrinsics.*
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts [Continuation] to [ExperimentalContinuation].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.3")
|
|
||||||
public fun <T> Continuation<T>.toExperimentalContinuation(): ExperimentalContinuation<T> =
|
|
||||||
(this as? ContinuationMigration<T>)?.continuation ?: ExperimentalContinuationMigration(this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts [ExperimentalContinuation] to [Continuation].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.3")
|
|
||||||
public fun <T> ExperimentalContinuation<T>.toContinuation(): Continuation<T> =
|
|
||||||
(this as? ExperimentalContinuationMigration<T>)?.continuation ?: ContinuationMigration(this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts [CoroutineContext] to [ExperimentalCoroutineContext].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.3")
|
|
||||||
public fun CoroutineContext.toExperimentalCoroutineContext(): ExperimentalCoroutineContext {
|
|
||||||
val interceptor = get(ContinuationInterceptor.Key)
|
|
||||||
val migration = get(ContextMigration.Key)
|
|
||||||
val remainder = minusKey(ContinuationInterceptor.Key).minusKey(ContextMigration.Key)
|
|
||||||
val original = migration?.context ?: ExperimentalEmptyCoroutineContext
|
|
||||||
val result = if (remainder === EmptyCoroutineContext) original else original + ExperimentalContextMigration(remainder)
|
|
||||||
return if (interceptor == null) result else result + interceptor.toExperimentalContinuationInterceptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts [ExperimentalCoroutineContext] to [CoroutineContext].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.3")
|
|
||||||
public fun ExperimentalCoroutineContext.toCoroutineContext(): CoroutineContext {
|
|
||||||
val interceptor = get(ExperimentalContinuationInterceptor.Key)
|
|
||||||
val migration = get(ExperimentalContextMigration.Key)
|
|
||||||
val remainder = minusKey(ExperimentalContinuationInterceptor.Key).minusKey(ExperimentalContextMigration.Key)
|
|
||||||
val original = migration?.context ?: EmptyCoroutineContext
|
|
||||||
val result = if (remainder === ExperimentalEmptyCoroutineContext) original else original + ContextMigration(remainder)
|
|
||||||
return if (interceptor == null) result else result + interceptor.toContinuationInterceptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts [ContinuationInterceptor] to [ExperimentalContinuationInterceptor].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.3")
|
|
||||||
public fun ContinuationInterceptor.toExperimentalContinuationInterceptor(): ExperimentalContinuationInterceptor =
|
|
||||||
(this as? ContinuationInterceptorMigration)?.interceptor ?: ExperimentalContinuationInterceptorMigration(this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts [ExperimentalContinuationInterceptor] to [ContinuationInterceptor].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.3")
|
|
||||||
public fun ExperimentalContinuationInterceptor.toContinuationInterceptor(): ContinuationInterceptor =
|
|
||||||
(this as? ExperimentalContinuationInterceptorMigration)?.interceptor ?: ContinuationInterceptorMigration(this)
|
|
||||||
|
|
||||||
// ------------------ converter classes ------------------
|
|
||||||
// Their name starts with "Experimental" if they implement the corresponding Experimental interfaces
|
|
||||||
|
|
||||||
private class ExperimentalContinuationMigration<T>(val continuation: Continuation<T>): ExperimentalContinuation<T> {
|
|
||||||
override val context = continuation.context.toExperimentalCoroutineContext()
|
|
||||||
override fun resume(value: T) = continuation.resume(value)
|
|
||||||
override fun resumeWithException(exception: Throwable) = continuation.resumeWithException(exception)
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ContinuationMigration<T>(val continuation: ExperimentalContinuation<T>): Continuation<T> {
|
|
||||||
override val context: CoroutineContext = continuation.context.toCoroutineContext()
|
|
||||||
override fun resumeWith(result: Result<T>) {
|
|
||||||
result
|
|
||||||
.onSuccess { continuation.resume(it) }
|
|
||||||
.onFailure { continuation.resumeWithException(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExperimentalContextMigration(val context: CoroutineContext): ExperimentalAbstractCoroutineContextElement(Key) {
|
|
||||||
companion object Key : ExperimentalCoroutineContext.Key<ExperimentalContextMigration>
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ContextMigration(val context: ExperimentalCoroutineContext): AbstractCoroutineContextElement(Key) {
|
|
||||||
companion object Key : CoroutineContext.Key<ContextMigration>
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExperimentalContinuationInterceptorMigration(val interceptor: ContinuationInterceptor) : ExperimentalContinuationInterceptor {
|
|
||||||
override val key: ExperimentalCoroutineContext.Key<*>
|
|
||||||
get() = ExperimentalContinuationInterceptor.Key
|
|
||||||
|
|
||||||
override fun <T> interceptContinuation(continuation: ExperimentalContinuation<T>): ExperimentalContinuation<T> =
|
|
||||||
interceptor.interceptContinuation(continuation.toContinuation()).toExperimentalContinuation()
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ContinuationInterceptorMigration(val interceptor: ExperimentalContinuationInterceptor) : ContinuationInterceptor {
|
|
||||||
override val key: CoroutineContext.Key<*>
|
|
||||||
get() = ContinuationInterceptor.Key
|
|
||||||
|
|
||||||
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
|
|
||||||
interceptor.interceptContinuation(continuation.toExperimentalContinuation()).toContinuation()
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun <R> ((Continuation<R>) -> Any?).toExperimentalSuspendFunction(): (ExperimentalContinuation<R>) -> Any? =
|
|
||||||
ExperimentalSuspendFunction0Migration(this)
|
|
||||||
|
|
||||||
internal fun <T1, R> ((T1, Continuation<R>) -> Any?).toExperimentalSuspendFunction(): (T1, ExperimentalContinuation<R>) -> Any? =
|
|
||||||
ExperimentalSuspendFunction1Migration(this)
|
|
||||||
|
|
||||||
internal fun <T1, T2, R> ((T1, T2, Continuation<R>) -> Any?).toExperimentalSuspendFunction(): (T1, T2, ExperimentalContinuation<R>) -> Any? =
|
|
||||||
ExperimentalSuspendFunction2Migration(this)
|
|
||||||
|
|
||||||
private class ExperimentalSuspendFunction0Migration<R>(
|
|
||||||
val function: (Continuation<R>) -> Any?
|
|
||||||
) : (ExperimentalContinuation<R>) -> Any? {
|
|
||||||
override fun invoke(continuation: ExperimentalContinuation<R>): Any? {
|
|
||||||
return function(continuation.toContinuation())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExperimentalSuspendFunction1Migration<T1, R>(
|
|
||||||
val function: (T1, Continuation<R>) -> Any?
|
|
||||||
) : (T1, ExperimentalContinuation<R>) -> Any? {
|
|
||||||
override fun invoke(t1: T1, continuation: ExperimentalContinuation<R>): Any? {
|
|
||||||
return function(t1, continuation.toContinuation())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExperimentalSuspendFunction2Migration<T1, T2, R>(
|
|
||||||
val function: (T1, T2, Continuation<R>) -> Any?
|
|
||||||
) : (T1, T2, ExperimentalContinuation<R>) -> Any? {
|
|
||||||
override fun invoke(t1: T1, t2: T2, continuation: ExperimentalContinuation<R>): Any? {
|
|
||||||
return function(t1, t2, continuation.toContinuation())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package test.coroutines
|
|
||||||
|
|
||||||
import kotlin.test.*
|
|
||||||
import kotlin.coroutines.experimental.*
|
|
||||||
|
|
||||||
class CoroutineContextTest {
|
|
||||||
data class CtxA(val i: Int) : AbstractCoroutineContextElement(CtxA) {
|
|
||||||
companion object Key : CoroutineContext.Key<CtxA>
|
|
||||||
}
|
|
||||||
|
|
||||||
data class CtxB(val i: Int) : AbstractCoroutineContextElement(CtxB) {
|
|
||||||
companion object Key : CoroutineContext.Key<CtxB>
|
|
||||||
}
|
|
||||||
|
|
||||||
data class CtxC(val i: Int) : AbstractCoroutineContextElement(CtxC) {
|
|
||||||
companion object Key : CoroutineContext.Key<CtxC>
|
|
||||||
}
|
|
||||||
|
|
||||||
object Disp1 : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
|
|
||||||
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = continuation
|
|
||||||
override fun toString(): String = "Disp1"
|
|
||||||
}
|
|
||||||
|
|
||||||
object Disp2 : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
|
|
||||||
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = continuation
|
|
||||||
override fun toString(): String = "Disp2"
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testGetPlusFold() {
|
|
||||||
var ctx: CoroutineContext = EmptyCoroutineContext
|
|
||||||
assertContents(ctx)
|
|
||||||
assertEquals("EmptyCoroutineContext", ctx.toString())
|
|
||||||
|
|
||||||
ctx += CtxA(1)
|
|
||||||
assertContents(ctx, CtxA(1))
|
|
||||||
assertEquals("CtxA(i=1)", ctx.toString())
|
|
||||||
assertEquals(CtxA(1), ctx[CtxA])
|
|
||||||
assertEquals(null, ctx[CtxB])
|
|
||||||
assertEquals(null, ctx[CtxC])
|
|
||||||
|
|
||||||
ctx += CtxB(2)
|
|
||||||
assertContents(ctx, CtxA(1), CtxB(2))
|
|
||||||
assertEquals("[CtxA(i=1), CtxB(i=2)]", ctx.toString())
|
|
||||||
assertEquals(CtxA(1), ctx[CtxA])
|
|
||||||
assertEquals(CtxB(2), ctx[CtxB])
|
|
||||||
assertEquals(null, ctx[CtxC])
|
|
||||||
|
|
||||||
ctx += CtxC(3)
|
|
||||||
assertContents(ctx, CtxA(1), CtxB(2), CtxC(3))
|
|
||||||
assertEquals("[CtxA(i=1), CtxB(i=2), CtxC(i=3)]", ctx.toString())
|
|
||||||
assertEquals(CtxA(1), ctx[CtxA])
|
|
||||||
assertEquals(CtxB(2), ctx[CtxB])
|
|
||||||
assertEquals(CtxC(3), ctx[CtxC])
|
|
||||||
|
|
||||||
ctx += CtxB(4)
|
|
||||||
assertContents(ctx, CtxA(1), CtxC(3), CtxB(4))
|
|
||||||
assertEquals("[CtxA(i=1), CtxC(i=3), CtxB(i=4)]", ctx.toString())
|
|
||||||
assertEquals(CtxA(1), ctx[CtxA])
|
|
||||||
assertEquals(CtxB(4), ctx[CtxB])
|
|
||||||
assertEquals(CtxC(3), ctx[CtxC])
|
|
||||||
|
|
||||||
ctx += CtxA(5)
|
|
||||||
assertContents(ctx, CtxC(3), CtxB(4), CtxA(5))
|
|
||||||
assertEquals("[CtxC(i=3), CtxB(i=4), CtxA(i=5)]", ctx.toString())
|
|
||||||
assertEquals(CtxA(5), ctx[CtxA])
|
|
||||||
assertEquals(CtxB(4), ctx[CtxB])
|
|
||||||
assertEquals(CtxC(3), ctx[CtxC])
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testMinusKey() {
|
|
||||||
var ctx: CoroutineContext = CtxA(1) + CtxB(2) + CtxC(3)
|
|
||||||
assertContents(ctx, CtxA(1), CtxB(2), CtxC(3))
|
|
||||||
assertEquals("[CtxA(i=1), CtxB(i=2), CtxC(i=3)]", ctx.toString())
|
|
||||||
|
|
||||||
ctx = ctx.minusKey(CtxA)
|
|
||||||
assertContents(ctx, CtxB(2), CtxC(3))
|
|
||||||
assertEquals("[CtxB(i=2), CtxC(i=3)]", ctx.toString())
|
|
||||||
assertEquals(null, ctx[CtxA])
|
|
||||||
assertEquals(CtxB(2), ctx[CtxB])
|
|
||||||
assertEquals(CtxC(3), ctx[CtxC])
|
|
||||||
|
|
||||||
ctx = ctx.minusKey(CtxC)
|
|
||||||
assertContents(ctx, CtxB(2))
|
|
||||||
assertEquals("CtxB(i=2)", ctx.toString())
|
|
||||||
assertEquals(null, ctx[CtxA])
|
|
||||||
assertEquals(CtxB(2), ctx[CtxB])
|
|
||||||
assertEquals(null, ctx[CtxC])
|
|
||||||
|
|
||||||
ctx = ctx.minusKey(CtxC)
|
|
||||||
assertContents(ctx, CtxB(2))
|
|
||||||
assertEquals("CtxB(i=2)", ctx.toString())
|
|
||||||
assertEquals(null, ctx[CtxA])
|
|
||||||
assertEquals(CtxB(2), ctx[CtxB])
|
|
||||||
assertEquals(null, ctx[CtxC])
|
|
||||||
|
|
||||||
ctx = ctx.minusKey(CtxB)
|
|
||||||
assertContents(ctx)
|
|
||||||
assertEquals("EmptyCoroutineContext", ctx.toString())
|
|
||||||
assertEquals(null, ctx[CtxA])
|
|
||||||
assertEquals(null, ctx[CtxB])
|
|
||||||
assertEquals(null, ctx[CtxC])
|
|
||||||
|
|
||||||
assertEquals(EmptyCoroutineContext, ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testPlusCombined() {
|
|
||||||
val ctx1 = CtxA(1) + CtxB(2)
|
|
||||||
val ctx2 = CtxB(3) + CtxC(4)
|
|
||||||
val ctx = ctx1 + ctx2
|
|
||||||
assertContents(ctx, CtxA(1), CtxB(3), CtxC(4))
|
|
||||||
assertEquals("[CtxA(i=1), CtxB(i=3), CtxC(i=4)]", ctx.toString())
|
|
||||||
assertEquals(CtxA(1), ctx[CtxA])
|
|
||||||
assertEquals(CtxB(3), ctx[CtxB])
|
|
||||||
assertEquals(CtxC(4), ctx[CtxC])
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testLastDispatcher() {
|
|
||||||
var ctx: CoroutineContext = EmptyCoroutineContext
|
|
||||||
assertContents(ctx)
|
|
||||||
ctx += CtxA(1)
|
|
||||||
assertContents(ctx, CtxA(1))
|
|
||||||
ctx += Disp1
|
|
||||||
assertContents(ctx, CtxA(1), Disp1)
|
|
||||||
ctx += CtxA(2)
|
|
||||||
assertContents(ctx, CtxA(2), Disp1)
|
|
||||||
ctx += CtxB(3)
|
|
||||||
assertContents(ctx, CtxA(2), CtxB(3), Disp1)
|
|
||||||
ctx += Disp2
|
|
||||||
assertContents(ctx, CtxA(2), CtxB(3), Disp2)
|
|
||||||
ctx += (CtxB(4) + CtxC(5))
|
|
||||||
assertContents(ctx, CtxA(2), CtxB(4), CtxC(5), Disp2)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testEquals() {
|
|
||||||
val ctx1 = CtxA(1) + CtxB(2) + CtxC(3)
|
|
||||||
val ctx2 = CtxB(2) + CtxC(3) + CtxA(1) // same
|
|
||||||
val ctx3 = CtxC(3) + CtxA(1) + CtxB(2) // same
|
|
||||||
val ctx4 = CtxA(1) + CtxB(2) + CtxC(4) // different
|
|
||||||
assertEquals(ctx1, ctx2)
|
|
||||||
assertEquals(ctx1, ctx3)
|
|
||||||
assertEquals(ctx2, ctx3)
|
|
||||||
assertNotEquals(ctx1, ctx4)
|
|
||||||
assertNotEquals(ctx2, ctx4)
|
|
||||||
assertNotEquals(ctx3, ctx4)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun assertContents(ctx: CoroutineContext, vararg elements: CoroutineContext.Element) {
|
|
||||||
val set = ctx.fold(setOf<CoroutineContext>()) { a, b -> a + b }
|
|
||||||
assertEquals(listOf(*elements), set.toList())
|
|
||||||
for (elem in elements)
|
|
||||||
assertTrue(ctx[elem.key] == elem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package test.coroutines
|
|
||||||
|
|
||||||
import test.assertStaticAndRuntimeTypeIs
|
|
||||||
import kotlin.test.*
|
|
||||||
import kotlin.coroutines.experimental.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test to ensure that coroutine machinery does not call equals/hashCode/toString anywhere.
|
|
||||||
*/
|
|
||||||
class CoroutinesReferenceValuesTest {
|
|
||||||
class BadClass {
|
|
||||||
override fun equals(other: Any?): Boolean = error("equals")
|
|
||||||
override fun hashCode(): Int = error("hashCode")
|
|
||||||
override fun toString(): String = error("toString")
|
|
||||||
}
|
|
||||||
|
|
||||||
var counter = 0
|
|
||||||
|
|
||||||
// tail-suspend function via suspendCoroutine (test SafeContinuation)
|
|
||||||
suspend fun getBadClassViaSuspend(): BadClass = suspendCoroutine { cont ->
|
|
||||||
counter++
|
|
||||||
cont.resume(BadClass())
|
|
||||||
}
|
|
||||||
|
|
||||||
// state machine
|
|
||||||
suspend fun checkBadClassTwice() {
|
|
||||||
assertStaticAndRuntimeTypeIs<BadClass>(getBadClassViaSuspend())
|
|
||||||
assertStaticAndRuntimeTypeIs<BadClass>(getBadClassViaSuspend())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> suspend(block: suspend () -> T) = block
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testBadClass() {
|
|
||||||
val bad = suspend {
|
|
||||||
checkBadClassTwice()
|
|
||||||
getBadClassViaSuspend()
|
|
||||||
}
|
|
||||||
var result: BadClass? = null
|
|
||||||
bad.startCoroutine(object : Continuation<BadClass> {
|
|
||||||
override val context: CoroutineContext = EmptyCoroutineContext
|
|
||||||
|
|
||||||
override fun resume(value: BadClass) {
|
|
||||||
assertTrue(result == null)
|
|
||||||
result = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resumeWithException(exception: Throwable) {
|
|
||||||
throw exception
|
|
||||||
}
|
|
||||||
})
|
|
||||||
assertTrue(result is BadClass)
|
|
||||||
assertEquals(3, counter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,295 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("ObsoleteExperimentalCoroutines", "DEPRECATION")
|
|
||||||
|
|
||||||
package test.coroutines
|
|
||||||
|
|
||||||
import kotlin.test.*
|
|
||||||
import kotlin.coroutines.experimental.buildSequence
|
|
||||||
import kotlin.coroutines.experimental.buildIterator
|
|
||||||
|
|
||||||
class SequenceBuilderTest {
|
|
||||||
@Test
|
|
||||||
fun testSimple() {
|
|
||||||
val result = buildSequence {
|
|
||||||
for (i in 1..3) {
|
|
||||||
yield(2 * i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(listOf(2, 4, 6), result.toList())
|
|
||||||
// Repeated calls also work
|
|
||||||
assertEquals(listOf(2, 4, 6), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testCallHasNextSeveralTimes() {
|
|
||||||
val result = buildSequence {
|
|
||||||
yield(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
val iterator = result.iterator()
|
|
||||||
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
|
|
||||||
assertEquals(1, iterator.next())
|
|
||||||
|
|
||||||
assertFalse(iterator.hasNext())
|
|
||||||
assertFalse(iterator.hasNext())
|
|
||||||
assertFalse(iterator.hasNext())
|
|
||||||
|
|
||||||
assertFailsWith<NoSuchElementException> { iterator.next() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testManualIteration() {
|
|
||||||
val result = buildSequence {
|
|
||||||
yield(1)
|
|
||||||
yield(2)
|
|
||||||
yield(3)
|
|
||||||
}
|
|
||||||
|
|
||||||
val iterator = result.iterator()
|
|
||||||
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
assertEquals(1, iterator.next())
|
|
||||||
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
assertEquals(2, iterator.next())
|
|
||||||
|
|
||||||
assertEquals(3, iterator.next())
|
|
||||||
|
|
||||||
assertFalse(iterator.hasNext())
|
|
||||||
assertFalse(iterator.hasNext())
|
|
||||||
|
|
||||||
assertFailsWith<NoSuchElementException> { iterator.next() }
|
|
||||||
|
|
||||||
assertEquals(1, result.iterator().next())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testEmptySequence() {
|
|
||||||
val result = buildSequence<Int> {}
|
|
||||||
val iterator = result.iterator()
|
|
||||||
|
|
||||||
assertFalse(iterator.hasNext())
|
|
||||||
assertFalse(iterator.hasNext())
|
|
||||||
|
|
||||||
assertFailsWith<NoSuchElementException> { iterator.next() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testLaziness() {
|
|
||||||
var sharedVar = -2
|
|
||||||
val result = buildSequence {
|
|
||||||
while (true) {
|
|
||||||
when (sharedVar) {
|
|
||||||
-1 -> return@buildSequence
|
|
||||||
-2 -> error("Invalid state: -2")
|
|
||||||
else -> yield(sharedVar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val iterator = result.iterator()
|
|
||||||
|
|
||||||
sharedVar = 1
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
assertEquals(1, iterator.next())
|
|
||||||
|
|
||||||
sharedVar = 2
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
assertEquals(2, iterator.next())
|
|
||||||
|
|
||||||
sharedVar = 3
|
|
||||||
assertTrue(iterator.hasNext())
|
|
||||||
assertEquals(3, iterator.next())
|
|
||||||
|
|
||||||
sharedVar = -1
|
|
||||||
assertFalse(iterator.hasNext())
|
|
||||||
assertFailsWith<NoSuchElementException> { iterator.next() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExceptionInCoroutine() {
|
|
||||||
var sharedVar = -2
|
|
||||||
val result = buildSequence {
|
|
||||||
while (true) {
|
|
||||||
when (sharedVar) {
|
|
||||||
-1 -> return@buildSequence
|
|
||||||
-2 -> throw UnsupportedOperationException("-2 is unsupported")
|
|
||||||
else -> yield(sharedVar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val iterator = result.iterator()
|
|
||||||
|
|
||||||
sharedVar = 1
|
|
||||||
assertEquals(1, iterator.next())
|
|
||||||
|
|
||||||
sharedVar = -2
|
|
||||||
assertFailsWith<UnsupportedOperationException> { iterator.hasNext() }
|
|
||||||
assertFailsWith<IllegalStateException> { iterator.hasNext() }
|
|
||||||
assertFailsWith<IllegalStateException> { iterator.next() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testParallelIteration() {
|
|
||||||
var inc = 0
|
|
||||||
val result = buildSequence {
|
|
||||||
for (i in 1..3) {
|
|
||||||
inc++
|
|
||||||
yield(inc * i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(listOf(Pair(1, 2), Pair(6, 8), Pair(15, 18)), result.zip(result).toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllIterator() {
|
|
||||||
val result = buildSequence {
|
|
||||||
yieldAll(listOf(1, 2, 3).iterator())
|
|
||||||
}
|
|
||||||
assertEquals(listOf(1, 2, 3), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllSequence() {
|
|
||||||
val result = buildSequence {
|
|
||||||
yieldAll(sequenceOf(1, 2, 3))
|
|
||||||
}
|
|
||||||
assertEquals(listOf(1, 2, 3), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllCollection() {
|
|
||||||
val result = buildSequence {
|
|
||||||
yieldAll(listOf(1, 2, 3))
|
|
||||||
}
|
|
||||||
assertEquals(listOf(1, 2, 3), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllCollectionMixedFirst() {
|
|
||||||
val result = buildSequence {
|
|
||||||
yield(0)
|
|
||||||
yieldAll(listOf(1, 2, 3))
|
|
||||||
}
|
|
||||||
assertEquals(listOf(0, 1, 2, 3), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllCollectionMixedLast() {
|
|
||||||
val result = buildSequence {
|
|
||||||
yieldAll(listOf(1, 2, 3))
|
|
||||||
yield(4)
|
|
||||||
}
|
|
||||||
assertEquals(listOf(1, 2, 3, 4), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllCollectionMixedBoth() {
|
|
||||||
val result = buildSequence {
|
|
||||||
yield(0)
|
|
||||||
yieldAll(listOf(1, 2, 3))
|
|
||||||
yield(4)
|
|
||||||
}
|
|
||||||
assertEquals(listOf(0, 1, 2, 3, 4), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllCollectionMixedLong() {
|
|
||||||
val result = buildSequence {
|
|
||||||
yield(0)
|
|
||||||
yieldAll(listOf(1, 2, 3))
|
|
||||||
yield(4)
|
|
||||||
yield(5)
|
|
||||||
yieldAll(listOf(6))
|
|
||||||
yield(7)
|
|
||||||
yieldAll(listOf())
|
|
||||||
yield(8)
|
|
||||||
}
|
|
||||||
assertEquals(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllCollectionOneEmpty() {
|
|
||||||
val result = buildSequence<Int> {
|
|
||||||
yieldAll(listOf())
|
|
||||||
}
|
|
||||||
assertEquals(listOf(), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllCollectionManyEmpty() {
|
|
||||||
val result = buildSequence<Int> {
|
|
||||||
yieldAll(listOf())
|
|
||||||
yieldAll(listOf())
|
|
||||||
yieldAll(listOf())
|
|
||||||
}
|
|
||||||
assertEquals(listOf(), result.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testYieldAllSideEffects() {
|
|
||||||
val effects = arrayListOf<Any>()
|
|
||||||
val result = buildSequence {
|
|
||||||
effects.add("a")
|
|
||||||
yieldAll(listOf(1, 2))
|
|
||||||
effects.add("b")
|
|
||||||
yieldAll(listOf())
|
|
||||||
effects.add("c")
|
|
||||||
yieldAll(listOf(3))
|
|
||||||
effects.add("d")
|
|
||||||
yield(4)
|
|
||||||
effects.add("e")
|
|
||||||
yieldAll(listOf())
|
|
||||||
effects.add("f")
|
|
||||||
yield(5)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (res in result) {
|
|
||||||
effects.add("(") // marks step start
|
|
||||||
effects.add(res)
|
|
||||||
effects.add(")") // marks step end
|
|
||||||
}
|
|
||||||
assertEquals(
|
|
||||||
listOf(
|
|
||||||
"a",
|
|
||||||
"(", 1, ")",
|
|
||||||
"(", 2, ")",
|
|
||||||
"b", "c",
|
|
||||||
"(", 3, ")",
|
|
||||||
"d",
|
|
||||||
"(", 4, ")",
|
|
||||||
"e", "f",
|
|
||||||
"(", 5, ")"
|
|
||||||
),
|
|
||||||
effects.toList()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testInfiniteYieldAll() {
|
|
||||||
val values = buildIterator {
|
|
||||||
while (true) {
|
|
||||||
yieldAll((1..5).map { it })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var sum = 0
|
|
||||||
repeat(10) {
|
|
||||||
sum += values.next() //.also(::println)
|
|
||||||
}
|
|
||||||
assertEquals(30, sum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package test
|
|
||||||
|
|
||||||
import kotlin.test.*
|
|
||||||
|
|
||||||
inline fun <reified T> assertStaticAndRuntimeTypeIs(value: T) {
|
|
||||||
@Suppress("USELESS_CAST")
|
|
||||||
if ((value as Any?) !is T) {
|
|
||||||
fail("Expected value $value to have ${T::class} type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks coroutine context element that intercepts coroutine continuations.
|
|
||||||
* The coroutines framework uses [ContinuationInterceptor.Key] to retrieve the interceptor and
|
|
||||||
* intercepts all coroutine continuations with [interceptContinuation] invocations.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public interface ContinuationInterceptor : CoroutineContext.Element {
|
|
||||||
/**
|
|
||||||
* The key that defines *the* context interceptor.
|
|
||||||
*/
|
|
||||||
companion object Key : CoroutineContext.Key<ContinuationInterceptor>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns continuation that wraps the original [continuation], thus intercepting all resumptions.
|
|
||||||
* This function is invoked by coroutines framework when needed and the resulting continuations are
|
|
||||||
* cached internally per each instance of the original [continuation].
|
|
||||||
*
|
|
||||||
* By convention, implementations that install themselves as *the* interceptor in the context with
|
|
||||||
* the [Key] shall also scan the context for other element that implement [ContinuationInterceptor] interface
|
|
||||||
* and use their [interceptContinuation] functions, too.
|
|
||||||
*/
|
|
||||||
public fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T>
|
|
||||||
}
|
|
||||||
-79
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persistent context for the coroutine. It is an indexed set of [Element] instances.
|
|
||||||
* An indexed set is a mix between a set and a map.
|
|
||||||
* Every element in this set has a unique [Key]. Keys are compared _by reference_.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public interface CoroutineContext {
|
|
||||||
/**
|
|
||||||
* Returns the element with the given [key] from this context or `null`.
|
|
||||||
* Keys are compared _by reference_, that is to get an element from the context the reference to its actual key
|
|
||||||
* object must be presented to this function.
|
|
||||||
*/
|
|
||||||
public operator fun <E : Element> get(key: Key<E>): E?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accumulates entries of this context starting with [initial] value and applying [operation]
|
|
||||||
* from left to right to current accumulator value and each element of this context.
|
|
||||||
*/
|
|
||||||
public fun <R> fold(initial: R, operation: (R, Element) -> R): R
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a context containing elements from this context and elements from other [context].
|
|
||||||
* The elements from this context with the same key as in the other one are dropped.
|
|
||||||
*/
|
|
||||||
public operator fun plus(context: CoroutineContext): CoroutineContext =
|
|
||||||
if (context === EmptyCoroutineContext) this else // fast path -- avoid lambda creation
|
|
||||||
context.fold(this) { acc, element ->
|
|
||||||
val removed = acc.minusKey(element.key)
|
|
||||||
if (removed === EmptyCoroutineContext) element else {
|
|
||||||
// make sure interceptor is always last in the context (and thus is fast to get when present)
|
|
||||||
val interceptor = removed[ContinuationInterceptor]
|
|
||||||
if (interceptor == null) CombinedContext(removed, element) else {
|
|
||||||
val left = removed.minusKey(ContinuationInterceptor)
|
|
||||||
if (left === EmptyCoroutineContext) CombinedContext(element, interceptor) else
|
|
||||||
CombinedContext(CombinedContext(left, element), interceptor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a context containing elements from this context, but without an element with
|
|
||||||
* the specified [key]. Keys are compared _by reference_, that is to remove an element from the context
|
|
||||||
* the reference to its actual key object must be presented to this function.
|
|
||||||
*/
|
|
||||||
public fun minusKey(key: Key<*>): CoroutineContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An element of the [CoroutineContext]. An element of the coroutine context is a singleton context by itself.
|
|
||||||
*/
|
|
||||||
public interface Element : CoroutineContext {
|
|
||||||
/**
|
|
||||||
* A key of this coroutine context element.
|
|
||||||
*/
|
|
||||||
public val key: Key<*>
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
public override operator fun <E : Element> get(key: Key<E>): E? =
|
|
||||||
if (this.key === key) this as E else null
|
|
||||||
|
|
||||||
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R =
|
|
||||||
operation(initial, this)
|
|
||||||
|
|
||||||
public override fun minusKey(key: Key<*>): CoroutineContext =
|
|
||||||
if (this.key === key) EmptyCoroutineContext else this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key for the elements of [CoroutineContext]. [E] is a type of element with this key.
|
|
||||||
* Keys in the context are compared _by reference_.
|
|
||||||
*/
|
|
||||||
public interface Key<E : Element>
|
|
||||||
}
|
|
||||||
-88
@@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental
|
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.CoroutineContext.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for [CoroutineContext.Element] implementations.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public abstract class AbstractCoroutineContextElement(public override val key: Key<*>) : Element
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An empty coroutine context.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public object EmptyCoroutineContext : CoroutineContext {
|
|
||||||
public override fun <E : Element> get(key: Key<E>): E? = null
|
|
||||||
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R = initial
|
|
||||||
public override fun plus(context: CoroutineContext): CoroutineContext = context
|
|
||||||
public override fun minusKey(key: Key<*>): CoroutineContext = this
|
|
||||||
public override fun hashCode(): Int = 0
|
|
||||||
public override fun toString(): String = "EmptyCoroutineContext"
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------- internal impl ---------------------
|
|
||||||
|
|
||||||
// this class is not exposed, but is hidden inside implementations
|
|
||||||
// this is a left-biased list, so that `plus` works naturally
|
|
||||||
internal class CombinedContext(val left: CoroutineContext, val element: Element) : CoroutineContext {
|
|
||||||
override fun <E : Element> get(key: Key<E>): E? {
|
|
||||||
var cur = this
|
|
||||||
while (true) {
|
|
||||||
cur.element[key]?.let { return it }
|
|
||||||
val next = cur.left
|
|
||||||
if (next is CombinedContext) {
|
|
||||||
cur = next
|
|
||||||
} else {
|
|
||||||
return next[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R =
|
|
||||||
operation(left.fold(initial, operation), element)
|
|
||||||
|
|
||||||
public override fun minusKey(key: Key<*>): CoroutineContext {
|
|
||||||
element[key]?.let { return left }
|
|
||||||
val newLeft = left.minusKey(key)
|
|
||||||
return when {
|
|
||||||
newLeft === left -> this
|
|
||||||
newLeft === EmptyCoroutineContext -> element
|
|
||||||
else -> CombinedContext(newLeft, element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun size(): Int =
|
|
||||||
if (left is CombinedContext) left.size() + 1 else 2
|
|
||||||
|
|
||||||
private fun contains(element: Element): Boolean =
|
|
||||||
get(element.key) == element
|
|
||||||
|
|
||||||
private fun containsAll(context: CombinedContext): Boolean {
|
|
||||||
var cur = context
|
|
||||||
while (true) {
|
|
||||||
if (!contains(cur.element)) return false
|
|
||||||
val next = cur.left
|
|
||||||
if (next is CombinedContext) {
|
|
||||||
cur = next
|
|
||||||
} else {
|
|
||||||
return contains(next as Element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean =
|
|
||||||
this === other || other is CombinedContext && other.size() == size() && other.containsAll(this)
|
|
||||||
|
|
||||||
override fun hashCode(): Int = left.hashCode() + element.hashCode()
|
|
||||||
|
|
||||||
override fun toString(): String =
|
|
||||||
"[" + fold("") { acc, element ->
|
|
||||||
if (acc.isEmpty()) element.toString() else acc + ", " + element
|
|
||||||
} + "]"
|
|
||||||
}
|
|
||||||
-38
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface representing a continuation after a suspension point that returns value of type `T`.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public interface Continuation<in T> {
|
|
||||||
/**
|
|
||||||
* Context of the coroutine that corresponds to this continuation.
|
|
||||||
*/
|
|
||||||
public val context: CoroutineContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resumes the execution of the corresponding coroutine passing [value] as the return value of the last suspension point.
|
|
||||||
*/
|
|
||||||
public fun resume(value: T)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resumes the execution of the corresponding coroutine so that the [exception] is re-thrown right after the
|
|
||||||
* last suspension point.
|
|
||||||
*/
|
|
||||||
public fun resumeWithException(exception: Throwable)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Classes and interfaces marked with this annotation are restricted when used as receivers for extension
|
|
||||||
* `suspend` functions. These `suspend` extensions can only invoke other member or extension `suspend` functions on this particular
|
|
||||||
* receiver only and are restricted from calling arbitrary suspension functions.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
|
||||||
@Retention(AnnotationRetention.BINARY)
|
|
||||||
public annotation class RestrictsSuspension
|
|
||||||
-21
@@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal expect class SafeContinuation<in T> : Continuation<T> {
|
|
||||||
internal constructor(delegate: Continuation<T>, initialResult: Any?)
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal constructor(delegate: Continuation<T>)
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal fun getResult(): Any?
|
|
||||||
|
|
||||||
override val context: CoroutineContext
|
|
||||||
override fun resume(value: T): Unit
|
|
||||||
override fun resumeWithException(exception: Throwable): Unit
|
|
||||||
}
|
|
||||||
-44
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental.intrinsics
|
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.Continuation
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts unintercepted coroutine without receiver and with result type [T] and executes it until its first suspension.
|
|
||||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
|
||||||
* In the latter case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
* This function is designed to be used from inside of [suspendCoroutineOrReturn] to resume the execution of a suspended
|
|
||||||
* coroutine using a reference to the suspending function.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public expect inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Any?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension.
|
|
||||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
|
||||||
* In the latter case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
* This function is designed to be used from inside of [suspendCoroutineOrReturn] to resume the execution of a suspended
|
|
||||||
* coroutine using a reference to the suspending function.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public expect inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
|
|
||||||
receiver: R,
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Any?
|
|
||||||
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public expect fun <T> (suspend () -> T).createCoroutineUnchecked(
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Continuation<Unit>
|
|
||||||
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public expect fun <R, T> (suspend R.() -> T).createCoroutineUnchecked(
|
|
||||||
receiver: R,
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Continuation<Unit>
|
|
||||||
-117
@@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:kotlin.jvm.JvmName("CoroutinesKt")
|
|
||||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental
|
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
|
|
||||||
import kotlin.coroutines.experimental.intrinsics.createCoroutineUnchecked
|
|
||||||
import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
|
|
||||||
import kotlin.internal.InlineOnly
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts coroutine with receiver type [R] and result type [T].
|
|
||||||
* This function creates and start a new, fresh instance of suspendable computation every time it is invoked.
|
|
||||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
public fun <R, T> (suspend R.() -> T).startCoroutine(
|
|
||||||
receiver: R,
|
|
||||||
completion: Continuation<T>
|
|
||||||
) {
|
|
||||||
createCoroutineUnchecked(receiver, completion).resume(Unit)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts coroutine without receiver and with result type [T].
|
|
||||||
* This function creates and start a new, fresh instance of suspendable computation every time it is invoked.
|
|
||||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
public fun <T> (suspend () -> T).startCoroutine(
|
|
||||||
completion: Continuation<T>
|
|
||||||
) {
|
|
||||||
createCoroutineUnchecked(completion).resume(Unit)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a coroutine with receiver type [R] and result type [T].
|
|
||||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
|
||||||
*
|
|
||||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
|
||||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
* Repeated invocation of any resume function on the resulting continuation produces [IllegalStateException].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
public fun <R, T> (suspend R.() -> T).createCoroutine(
|
|
||||||
receiver: R,
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Continuation<Unit> = SafeContinuation(createCoroutineUnchecked(receiver, completion), COROUTINE_SUSPENDED)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a coroutine without receiver and with result type [T].
|
|
||||||
* This function creates a new, fresh instance of suspendable computation every time it is invoked.
|
|
||||||
*
|
|
||||||
* To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance.
|
|
||||||
* The [completion] continuation is invoked when coroutine completes with result or exception.
|
|
||||||
* Repeated invocation of any resume function on the resulting continuation produces [IllegalStateException].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
public fun <T> (suspend () -> T).createCoroutine(
|
|
||||||
completion: Continuation<T>
|
|
||||||
): Continuation<Unit> = SafeContinuation(createCoroutineUnchecked(completion), COROUTINE_SUSPENDED)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains the current continuation instance inside suspend functions and suspends
|
|
||||||
* currently running coroutine.
|
|
||||||
*
|
|
||||||
* In this function both [Continuation.resume] and [Continuation.resumeWithException] can be used either synchronously in
|
|
||||||
* the same stack-frame where suspension function is run or asynchronously later in the same thread or
|
|
||||||
* from a different thread of execution. Repeated invocation of any resume function produces [IllegalStateException].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public suspend inline fun <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T =
|
|
||||||
suspendCoroutineOrReturn { c: Continuation<T> ->
|
|
||||||
val safe = SafeContinuation(c)
|
|
||||||
block(safe)
|
|
||||||
safe.getResult()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Continuation context of current coroutine.
|
|
||||||
*
|
|
||||||
* This allows the user code to not pass an extra [CoroutineContext] parameter in basic coroutine builders
|
|
||||||
* like [launch](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html)
|
|
||||||
* and [async](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html),
|
|
||||||
* but still provide easy access to coroutine context.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.2")
|
|
||||||
@Suppress("WRONG_MODIFIER_TARGET")
|
|
||||||
@InlineOnly
|
|
||||||
public suspend inline val coroutineContext: CoroutineContext
|
|
||||||
get() {
|
|
||||||
throw NotImplementedError("Implemented as intrinsic")
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERNAL DECLARATIONS
|
|
||||||
|
|
||||||
@kotlin.internal.InlineOnly
|
|
||||||
internal inline fun processBareContinuationResume(completion: Continuation<*>, block: () -> Any?) {
|
|
||||||
try {
|
|
||||||
val result = block()
|
|
||||||
if (result !== COROUTINE_SUSPENDED) {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
(completion as Continuation<Any?>).resume(result)
|
|
||||||
}
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
completion.resumeWithException(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-177
@@ -1,177 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:kotlin.jvm.JvmMultifileClass
|
|
||||||
@file:kotlin.jvm.JvmName("SequenceBuilderKt")
|
|
||||||
@file:OptIn(ExperimentalTypeInference::class)
|
|
||||||
|
|
||||||
package kotlin.coroutines.experimental
|
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.intrinsics.*
|
|
||||||
import kotlin.experimental.ExperimentalTypeInference
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a [Sequence] lazily yielding values one by one.
|
|
||||||
*
|
|
||||||
* Since Kotlin 1.3 use [kotlin.sequences.sequence] instead.
|
|
||||||
*
|
|
||||||
* @see kotlin.sequences.generateSequence
|
|
||||||
* @see kotlin.sequences.sequence
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public fun <T> buildSequence(@BuilderInference builderAction: suspend SequenceBuilder<T>.() -> Unit): Sequence<T> = Sequence { buildIterator(builderAction) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds an [Iterator] lazily yielding values one by one.
|
|
||||||
*
|
|
||||||
* Since Kotlin 1.3 use [kotlin.sequences.iterator] instead.
|
|
||||||
*
|
|
||||||
* @see kotlin.sequences.iterator
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public fun <T> buildIterator(@BuilderInference builderAction: suspend SequenceBuilder<T>.() -> Unit): Iterator<T> {
|
|
||||||
val iterator = SequenceBuilderIterator<T>()
|
|
||||||
iterator.nextStep = builderAction.createCoroutineUnchecked(receiver = iterator, completion = iterator)
|
|
||||||
return iterator
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder for a [Sequence] or an [Iterator], provides [yield] and [yieldAll] suspension functions.
|
|
||||||
*
|
|
||||||
* Since Kotlin 1.3 use [kotlin.sequences.SequenceScope] instead.
|
|
||||||
*
|
|
||||||
* @see buildSequence
|
|
||||||
* @see buildIterator
|
|
||||||
* @see kotlin.sequences.SequenceScope
|
|
||||||
*/
|
|
||||||
@RestrictsSuspension
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public abstract class SequenceBuilder<in T> internal constructor() {
|
|
||||||
/**
|
|
||||||
* Yields a value to the [Iterator] being built.
|
|
||||||
*/
|
|
||||||
public abstract suspend fun yield(value: T)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Yields all values from the `iterator` to the [Iterator] being built.
|
|
||||||
*
|
|
||||||
* The sequence of values returned by the given iterator can be potentially infinite.
|
|
||||||
*/
|
|
||||||
public abstract suspend fun yieldAll(iterator: Iterator<T>)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Yields a collections of values to the [Iterator] being built.
|
|
||||||
*/
|
|
||||||
public suspend fun yieldAll(elements: Iterable<T>) {
|
|
||||||
if (elements is Collection && elements.isEmpty()) return
|
|
||||||
return yieldAll(elements.iterator())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Yields potentially infinite sequence of values to the [Iterator] being built.
|
|
||||||
*
|
|
||||||
* The sequence can be potentially infinite.
|
|
||||||
*/
|
|
||||||
public suspend fun yieldAll(sequence: Sequence<T>) = yieldAll(sequence.iterator())
|
|
||||||
}
|
|
||||||
|
|
||||||
private typealias State = Int
|
|
||||||
|
|
||||||
private const val State_NotReady: State = 0
|
|
||||||
private const val State_ManyNotReady: State = 1
|
|
||||||
private const val State_ManyReady: State = 2
|
|
||||||
private const val State_Ready: State = 3
|
|
||||||
private const val State_Done: State = 4
|
|
||||||
private const val State_Failed: State = 5
|
|
||||||
|
|
||||||
private class SequenceBuilderIterator<T> : SequenceBuilder<T>(), Iterator<T>, Continuation<Unit> {
|
|
||||||
private var state = State_NotReady
|
|
||||||
private var nextValue: T? = null
|
|
||||||
private var nextIterator: Iterator<T>? = null
|
|
||||||
var nextStep: Continuation<Unit>? = null
|
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
while (true) {
|
|
||||||
when (state) {
|
|
||||||
State_NotReady -> {}
|
|
||||||
State_ManyNotReady ->
|
|
||||||
if (nextIterator!!.hasNext()) {
|
|
||||||
state = State_ManyReady
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
nextIterator = null
|
|
||||||
}
|
|
||||||
State_Done -> return false
|
|
||||||
State_Ready, State_ManyReady -> return true
|
|
||||||
else -> throw exceptionalState()
|
|
||||||
}
|
|
||||||
|
|
||||||
state = State_Failed
|
|
||||||
val step = nextStep!!
|
|
||||||
nextStep = null
|
|
||||||
step.resume(Unit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun next(): T {
|
|
||||||
when (state) {
|
|
||||||
State_NotReady, State_ManyNotReady -> return nextNotReady()
|
|
||||||
State_ManyReady -> {
|
|
||||||
state = State_ManyNotReady
|
|
||||||
return nextIterator!!.next()
|
|
||||||
}
|
|
||||||
State_Ready -> {
|
|
||||||
state = State_NotReady
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val result = nextValue as T
|
|
||||||
nextValue = null
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
else -> throw exceptionalState()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun nextNotReady(): T {
|
|
||||||
if (!hasNext()) throw NoSuchElementException() else return next()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun exceptionalState(): Throwable = when (state) {
|
|
||||||
State_Done -> NoSuchElementException()
|
|
||||||
State_Failed -> IllegalStateException("Iterator has failed.")
|
|
||||||
else -> IllegalStateException("Unexpected state of the iterator: $state")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
suspend override fun yield(value: T) {
|
|
||||||
nextValue = value
|
|
||||||
state = State_Ready
|
|
||||||
return suspendCoroutineOrReturn { c ->
|
|
||||||
nextStep = c
|
|
||||||
COROUTINE_SUSPENDED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend override fun yieldAll(iterator: Iterator<T>) {
|
|
||||||
if (!iterator.hasNext()) return
|
|
||||||
nextIterator = iterator
|
|
||||||
state = State_ManyReady
|
|
||||||
return suspendCoroutineOrReturn { c ->
|
|
||||||
nextStep = c
|
|
||||||
COROUTINE_SUSPENDED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Completion continuation implementation
|
|
||||||
override fun resume(value: Unit) {
|
|
||||||
state = State_Done
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resumeWithException(exception: Throwable) {
|
|
||||||
throw exception // just rethrow
|
|
||||||
}
|
|
||||||
|
|
||||||
override val context: CoroutineContext
|
|
||||||
get() = EmptyCoroutineContext
|
|
||||||
}
|
|
||||||
-61
@@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:kotlin.jvm.JvmName("IntrinsicsKt")
|
|
||||||
@file:kotlin.jvm.JvmMultifileClass
|
|
||||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
|
||||||
package kotlin.coroutines.experimental.intrinsics
|
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains the current continuation instance inside suspend functions and either suspends
|
|
||||||
* currently running coroutine or returns result immediately without suspension.
|
|
||||||
*
|
|
||||||
* If the [block] returns the special [COROUTINE_SUSPENDED] value, it means that suspend function did suspend the execution and will
|
|
||||||
* not return any result immediately. In this case, the [Continuation] provided to the [block] shall be invoked at some moment in the
|
|
||||||
* future when the result becomes available to resume the computation.
|
|
||||||
*
|
|
||||||
* Otherwise, the return value of the [block] must have a type assignable to [T] and represents the result of this suspend function.
|
|
||||||
* It means that the execution was not suspended and the [Continuation] provided to the [block] shall not be invoked.
|
|
||||||
* As the result type of the [block] is declared as `Any?` and cannot be correctly type-checked,
|
|
||||||
* its proper return type remains on the conscience of the suspend function's author.
|
|
||||||
*
|
|
||||||
* Note that it is not recommended to call either [Continuation.resume] nor [Continuation.resumeWithException] functions synchronously
|
|
||||||
* in the same stackframe where suspension function is run. Use [suspendCoroutine] as a safer way to obtain current
|
|
||||||
* continuation instance.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
@kotlin.internal.InlineOnly
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
public suspend inline fun <T> suspendCoroutineOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
|
|
||||||
suspendCoroutineUninterceptedOrReturn { cont -> block(cont.intercepted()) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains the current continuation instance inside suspend functions and either suspends
|
|
||||||
* currently running coroutine or returns result immediately without suspension.
|
|
||||||
*
|
|
||||||
* Unlike [suspendCoroutineOrReturn] it does not intercept continuation.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.2")
|
|
||||||
@kotlin.internal.InlineOnly
|
|
||||||
@Suppress("UNUSED_PARAMETER", "RedundantSuspendModifier")
|
|
||||||
public suspend inline fun <T> suspendCoroutineUninterceptedOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
|
|
||||||
throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intercept continuation with [ContinuationInterceptor].
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.2")
|
|
||||||
@kotlin.internal.InlineOnly
|
|
||||||
public inline fun <T> Continuation<T>.intercepted(): Continuation<T> =
|
|
||||||
throw NotImplementedError("Implementation of intercepted is intrinsic")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This value is used as a return value of [suspendCoroutineOrReturn] `block` argument to state that
|
|
||||||
* the execution was suspended and will not return any result immediately.
|
|
||||||
*/
|
|
||||||
@SinceKotlin("1.1")
|
|
||||||
public expect val COROUTINE_SUSPENDED: Any // get() = CoroutineSuspendedMarker
|
|
||||||
@@ -44,7 +44,6 @@ configurations {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile project(':kotlin-stdlib')
|
compile project(':kotlin-stdlib')
|
||||||
testCompile project(':kotlin-test:kotlin-test-junit')
|
testCompile project(':kotlin-test:kotlin-test-junit')
|
||||||
testCompile project(':kotlin-coroutines-experimental-compat')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ dependencies {
|
|||||||
compile project(':kotlin-stdlib')
|
compile project(':kotlin-stdlib')
|
||||||
compile project(':kotlin-stdlib-jdk7')
|
compile project(':kotlin-stdlib-jdk7')
|
||||||
testCompile project(':kotlin-test:kotlin-test-junit')
|
testCompile project(':kotlin-test:kotlin-test-junit')
|
||||||
testCompile project(':kotlin-coroutines-experimental-compat')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ dependencies {
|
|||||||
compile group: 'org.jetbrains', name: 'annotations', version:'13.0'
|
compile group: 'org.jetbrains', name: 'annotations', version:'13.0'
|
||||||
|
|
||||||
testCompile project(':kotlin-test:kotlin-test-junit')
|
testCompile project(':kotlin-test:kotlin-test-junit')
|
||||||
testCompile project(':kotlin-coroutines-experimental-compat')
|
|
||||||
|
|
||||||
builtins project(':core:builtins')
|
builtins project(':core:builtins')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("ObsoleteExperimentalCoroutines")
|
|
||||||
|
|
||||||
package test.coroutines.experimental.migration
|
|
||||||
|
|
||||||
import kotlin.coroutines.experimental.buildSequence as experimentalBuildSequence
|
|
||||||
import kotlin.coroutines.experimental.SequenceBuilder as ExperimentalSequenceBuilder
|
|
||||||
import kotlin.coroutines.experimental.Continuation as ExperimentalContinuation
|
|
||||||
import kotlin.coroutines.experimental.CoroutineContext as ExperimentalCoroutineContext
|
|
||||||
import kotlin.coroutines.experimental.AbstractCoroutineContextElement as ExperimentalAbstractCoroutineContextElement
|
|
||||||
import kotlin.coroutines.experimental.EmptyCoroutineContext as ExperimentalEmptyCoroutineContext
|
|
||||||
import kotlin.coroutines.experimental.ContinuationInterceptor as ExperimentalContinuationInterceptor
|
|
||||||
import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED as EXPERIMENTAL_COROUTINE_SUSPENDED
|
|
||||||
import kotlin.coroutines.experimental.migration.*
|
|
||||||
import kotlin.coroutines.*
|
|
||||||
import kotlin.test.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests on coroutines migrations utilities.
|
|
||||||
*/
|
|
||||||
class CoroutinesMigrationTest {
|
|
||||||
@Test
|
|
||||||
fun testContextMigration() {
|
|
||||||
assertTrue(EmptyCoroutineContext === ExperimentalEmptyCoroutineContext.toCoroutineContext())
|
|
||||||
assertTrue(ExperimentalEmptyCoroutineContext === EmptyCoroutineContext.toExperimentalCoroutineContext())
|
|
||||||
MyElement().let { e ->
|
|
||||||
assertTrue(e === e.toExperimentalCoroutineContext().toCoroutineContext())
|
|
||||||
val ee = MyExperimentalElement()
|
|
||||||
val ctx = (e.toExperimentalCoroutineContext() + ee).toCoroutineContext()
|
|
||||||
assertTrue(e === ctx[MyElement.Key])
|
|
||||||
assertTrue(ee === ctx.toExperimentalCoroutineContext()[MyExperimentalElement.Key])
|
|
||||||
}
|
|
||||||
MyExperimentalElement().let { ee ->
|
|
||||||
assertTrue(ee === ee.toCoroutineContext().toExperimentalCoroutineContext())
|
|
||||||
val e = MyElement()
|
|
||||||
val ctx = (ee.toCoroutineContext() + e).toExperimentalCoroutineContext()
|
|
||||||
assertTrue(ee === ctx[MyExperimentalElement.Key])
|
|
||||||
assertTrue(e === ctx.toCoroutineContext()[MyElement.Key])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyElement : AbstractCoroutineContextElement(Key) {
|
|
||||||
companion object Key : CoroutineContext.Key<MyElement>
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyExperimentalElement : ExperimentalAbstractCoroutineContextElement(Key) {
|
|
||||||
companion object Key : ExperimentalCoroutineContext.Key<MyExperimentalElement>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -14,7 +14,6 @@ dependencies {
|
|||||||
testArtifacts project(':kotlin-stdlib-jdk7')
|
testArtifacts project(':kotlin-stdlib-jdk7')
|
||||||
testArtifacts project(':kotlin-stdlib-jdk8')
|
testArtifacts project(':kotlin-stdlib-jdk8')
|
||||||
testArtifacts project(':kotlin-reflect')
|
testArtifacts project(':kotlin-reflect')
|
||||||
testArtifacts project(':kotlin-coroutines-experimental-compat')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pill {
|
pill {
|
||||||
|
|||||||
-5
@@ -33,11 +33,6 @@ class RuntimePublicAPITest {
|
|||||||
snapshotAPIAndCompare("../../reflect/api/build/libs", "kotlin-reflect-api(?!-[-a-z]+)", nonPublicPackages = listOf("kotlin.reflect.jvm.internal"))
|
snapshotAPIAndCompare("../../reflect/api/build/libs", "kotlin-reflect-api(?!-[-a-z]+)", nonPublicPackages = listOf("kotlin.reflect.jvm.internal"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun kotlinCoroutinesExperimentalCompat() {
|
|
||||||
snapshotAPIAndCompare("../../stdlib/coroutines-experimental/build/libs", "kotlin-coroutines-experimental-compat")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun snapshotAPIAndCompare(
|
private fun snapshotAPIAndCompare(
|
||||||
basePath: String,
|
basePath: String,
|
||||||
jarPattern: String,
|
jarPattern: String,
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ val distLibraryProjects = listOfNotNull(
|
|||||||
":kotlin-annotations-android",
|
":kotlin-annotations-android",
|
||||||
":kotlin-annotations-jvm",
|
":kotlin-annotations-jvm",
|
||||||
":kotlin-ant",
|
":kotlin-ant",
|
||||||
":kotlin-coroutines-experimental-compat",
|
|
||||||
":kotlin-daemon",
|
":kotlin-daemon",
|
||||||
":kotlin-daemon-client",
|
":kotlin-daemon-client",
|
||||||
// TODO: uncomment when new daemon will be put back into dist
|
// TODO: uncomment when new daemon will be put back into dist
|
||||||
@@ -121,7 +120,6 @@ val distCompilerPluginProjects = listOf(
|
|||||||
|
|
||||||
val distSourcesProjects = listOfNotNull(
|
val distSourcesProjects = listOfNotNull(
|
||||||
":kotlin-annotations-jvm",
|
":kotlin-annotations-jvm",
|
||||||
":kotlin-coroutines-experimental-compat",
|
|
||||||
":kotlin-script-runtime",
|
":kotlin-script-runtime",
|
||||||
":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
|
":kotlin-test:kotlin-test-js".takeIf { !kotlinBuildProperties.isInJpsBuildIdeaSync },
|
||||||
":kotlin-test:kotlin-test-junit",
|
":kotlin-test:kotlin-test-junit",
|
||||||
@@ -394,4 +392,4 @@ inline fun <reified T : AbstractCopyTask> Project.distTask(
|
|||||||
rename(quote("-$version"), "")
|
rename(quote("-$version"), "")
|
||||||
rename(quote("-$bootstrapKotlinVersion"), "")
|
rename(quote("-$bootstrapKotlinVersion"), "")
|
||||||
block()
|
block()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ val projectsToShadow by extra(listOf(
|
|||||||
// Projects published to maven copied to the plugin as separate jars
|
// Projects published to maven copied to the plugin as separate jars
|
||||||
val libraryProjects = listOf(
|
val libraryProjects = listOf(
|
||||||
":kotlin-reflect",
|
":kotlin-reflect",
|
||||||
":kotlin-coroutines-experimental-compat",
|
|
||||||
":kotlin-compiler-client-embeddable",
|
":kotlin-compiler-client-embeddable",
|
||||||
":kotlin-daemon-client",
|
":kotlin-daemon-client",
|
||||||
":kotlin-daemon-client-new",
|
":kotlin-daemon-client-new",
|
||||||
|
|||||||
@@ -208,7 +208,6 @@ include ":benchmarks",
|
|||||||
":plugins:uast-kotlin-idea",
|
":plugins:uast-kotlin-idea",
|
||||||
":plugins:annotation-based-compiler-plugins-ide-support",
|
":plugins:annotation-based-compiler-plugins-ide-support",
|
||||||
":kotlin-script-runtime",
|
":kotlin-script-runtime",
|
||||||
":kotlin-coroutines-experimental-compat",
|
|
||||||
":plugins:fir:fir-plugin-prototype",
|
":plugins:fir:fir-plugin-prototype",
|
||||||
":plugins:fir:fir-plugin-prototype:plugin-annotations",
|
":plugins:fir:fir-plugin-prototype:plugin-annotations",
|
||||||
":kotlin-test",
|
":kotlin-test",
|
||||||
@@ -442,7 +441,6 @@ if (buildProperties.inJpsBuildIdeaSync) {
|
|||||||
rootProject.name = "kotlin"
|
rootProject.name = "kotlin"
|
||||||
|
|
||||||
project(':kotlin-script-runtime').projectDir = "$rootDir/libraries/tools/script-runtime" as File
|
project(':kotlin-script-runtime').projectDir = "$rootDir/libraries/tools/script-runtime" as File
|
||||||
project(":kotlin-coroutines-experimental-compat").projectDir = "$rootDir/libraries/stdlib/coroutines-experimental" as File
|
|
||||||
project(':kotlin-test').projectDir = "$rootDir/libraries/kotlin.test" as File
|
project(':kotlin-test').projectDir = "$rootDir/libraries/kotlin.test" as File
|
||||||
project(':kotlin-test:kotlin-test-common').projectDir = "$rootDir/libraries/kotlin.test/common" as File
|
project(':kotlin-test:kotlin-test-common').projectDir = "$rootDir/libraries/kotlin.test/common" as File
|
||||||
project(':kotlin-test:kotlin-test-annotations-common').projectDir = "$rootDir/libraries/kotlin.test/annotations-common" as File
|
project(':kotlin-test:kotlin-test-annotations-common').projectDir = "$rootDir/libraries/kotlin.test/annotations-common" as File
|
||||||
|
|||||||
Reference in New Issue
Block a user