More work on draft coroutines 1.3 ABI & API:

* SuspendFunction[01] interfaces removed, moved to RestrictedContinuationImpl
* validateContext introduced to check restricted coroutines
* Distinguish SuspendLambda as being lambda/coroutine and provide a separate
  toString implementation (draft) in its coroutine incarnation.
This commit is contained in:
Roman Elizarov
2018-06-20 20:39:47 +03:00
committed by Denis Zharkov
parent 29dcc4f18c
commit 8e2fae3322
2 changed files with 48 additions and 23 deletions
@@ -12,8 +12,6 @@ package kotlin.coroutines.intrinsics
import kotlin.coroutines.*
import kotlin.coroutines.jvm.internal.ContinuationImpl
import kotlin.coroutines.jvm.internal.RestrictedContinuationImpl
import kotlin.coroutines.jvm.internal.SuspendFunction0
import kotlin.coroutines.jvm.internal.SuspendFunction1
import kotlin.internal.InlineOnly
/**
@@ -111,7 +109,7 @@ public actual fun <R, T> (suspend R.() -> T).createCoroutineUnchecked(
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
completion: Continuation<T>
): Continuation<Unit> =
if (this is SuspendFunction0)
if (this is RestrictedContinuationImpl)
create(completion)
else
createCoroutineFromSuspendFunction(completion) {
@@ -139,7 +137,7 @@ public actual fun <R, T> (suspend R.() -> T).createCoroutineUnintercepted(
receiver: R,
completion: Continuation<T>
): Continuation<Unit> =
if (this is SuspendFunction1)
if (this is RestrictedContinuationImpl)
create(receiver, completion)
else {
createCoroutineFromSuspendFunction(completion) {
@@ -17,20 +17,40 @@ internal abstract class RestrictedContinuationImpl protected constructor(
@JvmField
protected val completion: Continuation<Any?>?
) : Continuation<Any?>, Serializable {
init {
@Suppress("LeakingThis")
validateContext()
}
protected open fun validateContext() {
completion?.let {
require(it.context === EmptyCoroutineContext) { "Coroutines with restricted suspension must have EmptyCoroutineContext" }
}
}
public override val context: CoroutineContext
get() = EmptyCoroutineContext
public override fun resumeWith(result: SuccessOrFailure<Any?>) {
val completion = completion!! // fail fast when trying to resume continuation without completion
try {
val outcome = invokeSuspend(result)
if (outcome === CoroutineSingletons.COROUTINE_SUSPENDED) return
completion!!.resume(outcome)
completion.resume(outcome)
} catch (exception: Throwable) {
completion!!.resumeWithException(exception)
completion.resumeWithException(exception)
}
}
protected abstract fun invokeSuspend(result: SuccessOrFailure<Any?>): Any?
public open fun create(completion: Continuation<*>): Continuation<Unit> {
throw UnsupportedOperationException("create(Continuation) has not been overridden")
}
public open fun create(value: Any?, completion: Continuation<*>): Continuation<Unit> {
throw UnsupportedOperationException("create(Any?;Continuation) has not been overridden")
}
}
@SinceKotlin("1.3")
@@ -41,6 +61,10 @@ internal abstract class ContinuationImpl protected constructor(
) : RestrictedContinuationImpl(completion) {
protected constructor(completion: Continuation<Any?>?) : this(completion, completion?.context)
override fun validateContext() {
// nothing to do here -- supports any context
}
override val context: CoroutineContext
get() = _context!!
@@ -53,14 +77,15 @@ internal abstract class ContinuationImpl protected constructor(
.also { intercepted = this }
public override fun resumeWith(result: SuccessOrFailure<Any?>) {
val completion = completion!! // fail fast when trying to resume continuation without completion
try {
val outcome = invokeSuspend(result)
if (outcome === CoroutineSingletons.COROUTINE_SUSPENDED) return
disposeIntercepted()
completion!!.resume(outcome)
completion.resume(outcome)
} catch (exception: Throwable) {
disposeIntercepted()
completion!!.resumeWithException(exception)
completion.resumeWithException(exception)
}
}
@@ -71,6 +96,11 @@ internal abstract class ContinuationImpl protected constructor(
}
this.intercepted = CompletedContinuation // just in case
}
override fun toString(): String {
// todo: how continuation shall be rendered?
return "Continuation @ ${this::class.java.name}"
}
}
// todo: Do we really need it?
@@ -80,7 +110,7 @@ internal object CompletedContinuation : Continuation<Any?> {
override fun resumeWith(result: SuccessOrFailure<Any?>) {
error("This continuation is already complete")
}
}
}
internal abstract class RestrictedSuspendLambda protected constructor(
@@ -91,7 +121,11 @@ internal abstract class RestrictedSuspendLambda protected constructor(
public override fun getArity(): Int = arity
public override fun toString(): String = Reflection.renderLambdaToString(this)
public override fun toString(): String =
if (completion == null)
Reflection.renderLambdaToString(this) // this is lambda
else
super.toString() // this is continuation
}
internal abstract class SuspendLambda protected constructor(
@@ -102,16 +136,9 @@ internal abstract class SuspendLambda protected constructor(
public override fun getArity(): Int = arity
public override fun toString(): String = Reflection.renderLambdaToString(this)
}
@SinceKotlin("1.3")
internal interface SuspendFunction0 : Function1<Continuation<Any?>, Any?> {
fun create(completion: Continuation<*>): Continuation<Unit>
}
@SinceKotlin("1.3")
internal interface SuspendFunction1 : Function2<Any?, Continuation<Any?>, Any?> {
fun create(receiver: Any?, completion: Continuation<*>): Continuation<Unit>
}
public override fun toString(): String =
if (completion == null)
Reflection.renderLambdaToString(this) // this is lambda
else
super.toString() // this is continuation
}