对于这样的 suspend lambda :
val block = suspend (p1 : P1, ..., pn : Pn) -> R = {
...
suspendFun(...)
...
resultR
}
其编译期生成的代码类似这样(这里只考虑 lambda 块里只调用了一次 suspend 方法的情况;如果调用了 n 次 suspend 方法,switch 块会被 n - 1 层 label 标签块嵌套包围):
public class SuspendLambdaBlock<P1, ..., Pn, R> extends kotlin.coroutines.jvm.internal.SuspendLambda
implements FunctionN<P1, ..., Pn, Continuation<? super R>, Object> {
// 状态机状态标记
int label;
// 用于保存局部临时变量
Object L$0;
...
Object L$x;
public SuspendLambdaBlock(@Nullable Continuation<Object> completion) {
super(N, completion);
}
@Nullable
@Override
protected Object invokeSuspend(@NotNull Object lastResult) {
Object state = IntrinsicsKt.getCOROUTINE_SUSPENDED();
Object newResult;
switch (label) {
case 0:
... // 执行 suspendFun() 方法之前的代码
label = 1; // 设置下一次恢复执行的状态
newResult = suspendFun(..., this);
if (newResult == state /*COROUTINE_SUSPENDED*/) {
return state; // suspendFun() 返回 COROUTINE_SUSPENDED,说明需要挂起 SuspendLambdaBlock 的执行
}
break; // suspendFun() 立即返回结果值,说明不需要挂起 SuspendLambdaBlock 的执行,break 后继续执行 suspendFun() 方法之后的代码,返回最终结果。
case 1:
... // 恢复保存的临时变量 L$0, ..., L$x
newResult = lastResult
break;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
... // 执行 suspendFun() 方法之后的代码
Object finalResult = ... // 计算最终结果值
return finalResult;
}
@NotNull
@Override
public final SuspendLambdaBlock<P1, ..., Pn, R> create(
@Nullable Object p1, ..., @Nullable Object pn, @NotNull Continuation completion) {
Intrinsics.checkNotNullParameter(completion, "completion");
return SuspendLambdaBlock(completion);
}
@Override
public final Object invoke(P1 p1, ..., Pn pn, Continuation<? super R> continuation) {
return create(p1, ..., pn, continuation).invokeSuspend(Unit.INSTANCE);
}
}
FunctionN<P1, ..., Pn, R> block = new SuspendLambdaBlock(null);
例如以下代码:
suspend fun suspendFun(): R = {
...
}
val test : suspend CoroutineScope.() -> R = {
suspendFun()
}
注:
suspend CoroutineScope.() -> R
与
suspend (CoroutineScope) -> R
是同一类型
编译期间生成的代码类似这样:
fun <R> suspendFun(completion: Continuation<R>): Any? {
...
}
class SuspendLambdaBlock<R>(completion: Continuation<*>?) :
SuspendLambda(2, completion),
Function2<CoroutineScope, Continuation<in R>, Any?> {
var label = 0
override fun invokeSuspend(result: Result<Any?>): Any? {
val state = COROUTINE_SUSPENDED
val newResult: Any?
when (label) {
0 -> {
result.getOrThrow()
label = 1
newResult = suspendFun(this)
if (newResult === state) {
return state
}
}
1 -> {
newResult = result.getOrThrow()
}
else -> throw IllegalStateException("call to 'resume' before 'invoke' with coroutine")
}
return newResult
}
override fun create(value: Any?, completion: Continuation<R>): SuspendLambdaBlock<R> {
return SuspendLambdaBlockKt(completion)
}
override operator fun invoke(coroutineScope: CoroutineScope, continuation: Continuation<in R>): Any? {
return create(coroutineScope, continuation).invokeSuspend(Result.success(Unit))
}
}
Function2<CoroutineScope, Continuation<in R> test = SuspendLambdaBlock<R>(null);
SuspendLambdaBlock 第一次创建时,completion 为 null,此 SuspendLambdaBlock 代表一个 Function,可执行 invoke(…, continuation : Continuation) 方法,
此方法会将 continuation 传入并 create 一个新的 SuspendLambdaBlock 实例,此 SuspendLambdaBlock 代表一个 ContinuationImpl,
然后执行 invokeSuspend() 状态机代码。
// Suspension lambdas inherit from this class
internal abstract class SuspendLambda(
public override val arity: Int,
completion: Continuation<Any?>?
) : ContinuationImpl(completion), FunctionBase<Any?>, SuspendFunction {
constructor(arity: Int) : this(arity, null)
public override fun toString(): String =
if (completion == null)
Reflection.renderLambdaToString(this) // this is lambda
else
super.toString() // this is continuation
}
SuspendLambda 的 toString() 方法的注释:当 completion 为空时,它代表一个 lambda;当 completion 不为空时,它代表一个 continuation。
比如 IntrinsicsJvm.kt 的 (suspend R.() -> T).startCoroutineUninterceptedOrReturn 方法:
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)
this (类型为 suspend R.() -> T) 代表一个 Function2<R, Continuation<T>, Any?>,可以执行 invoke(r : R, continuation : Continuation<T>) 方法。
invoke() 方法创建一个新的 SuspendLambda(=suspend R.() -> T) 实例(它代表一个 ContinuationImpl),然后执行它的 invokeSuspend() 方法。