看得出,suspend函数反编译之后,会自动将一个Continuation
作为参数传递进函数,且返回类型为object
。😮
简单看一下,将Continuation
作为参数传递给了IntrinsicsKt.intercepted($completion)
。IntrinsicsKt
在java
平台的具体实现在IntrinsicsJvm
文件中。而intercepted
的源码如下所示:
public actual fun Continuation.intercepted(): Continuation =
(this as? ContinuationImpl)?.intercepted() ?: this
这里不再深追,如果您熟悉协程框架的话,这里其实返回了Continuation
的拦截器,依旧是Continuation
类型,如果不存在拦截器,其实还是返回的自身。我们上面的写法,没有拦截器,返回的就是自身。最终将返回的Continuation
传递给了SafeContinuation
。
省略掉线程池的代码,看到最后调用了SafeContinuation
的getOrThrow
函数,我们来看一下这个代码(具体实现在SafeContinuationJvm
文件):😮
internal actual class SafeContinuation
internal actual constructor(
private val delegate: Continuation,
initialResult: Any?
) : Continuation, CoroutineStackFrame {
@PublishedApi
internal actual constructor(delegate: Continuation) : this(delegate, UNDECIDED)
…
@Volatile
private var result: Any? = initialResult
internal actual fun getOrThrow(): 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
}
…
}
先简单看一下SafeContinuation
构造器,我们会调用它的副构造器,将**continuation
赋值给delegate
。同时赋值initialResult
为UNDECIDED
**。所以此时result == UNDECIDED
。
所以调用getOrThrow
之后,就会走if (RESULT.compareAndSet(this, UNDECIDED, COROUTINE_SUSPENDED)) return COROUTINE_SUSPENDED
。将result
设置为COROUTINE_SUSPENDED
,同时返回COROUTINE_SUSPENDED
。
所以最终suspendFunction1
函数会返回COROUTINE_SUSPENDED
标志,代表挂起。
接下来我们分析一下传递给线程执行的代码如何走到恢复呢?我们看一下run()
里面的代码,其实就是在恢复的时候,调用了SafeContinuation
的resumeWith
函数,我们看一下resumeWith
的代码:
public actual override fun resumeWith(result: Result) {
while (true) { // lock-free loop
val cur = this.result // atomic read
when {
cur === UNDECIDED -> if (RESULT.compareAndSet(this, UNDECIDED, result.value)) return
cur === COROUTINE_SUSPENDED -> if (RESULT.compareAndSet(this, COROUTINE_SUSPENDED, RESUMED)) {
delegate.resumeWith(result)
return
}
else -> thro