请教个问题 createCoroutineUnintercepted

来源:12-2 案例:仿官方框架实现 launch 2

xxxxjase

2020-10-06

//kotlinx.coroutines.Builders.common.kt
public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy) // 这里创建了协程
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

上面的已经创建了协程了,但是在 coroutine.start 里面,我一路跟到 CoroutineStart 中:

   /**
    * Starts the corresponding block as a coroutine with this coroutine's start strategy.
    *
    * * [DEFAULT] uses [startCoroutineCancellable].
    * * [ATOMIC] uses [startCoroutine].
    * * [UNDISPATCHED] uses [startCoroutineUndispatched].
    * * [LAZY] does nothing.
    *
    * @suppress **This an internal API and should not be used from general code.**
    */
   @InternalCoroutinesApi
   public operator fun <T> invoke(block: suspend () -> T, completion: Continuation<T>) =
       when (this) {
           CoroutineStart.DEFAULT -> block.startCoroutineCancellable(completion)
           CoroutineStart.ATOMIC -> block.startCoroutine(completion) // 进入这里
           CoroutineStart.UNDISPATCHED -> block.startCoroutineUndispatched(completion)
           CoroutineStart.LAZY -> Unit // will start lazily
       }

然后进入 block.startCoroutine:

/**
 * Starts a coroutine without a receiver and with result type [T].
 * This function creates and starts a new, fresh instance of suspendable computation every time it is invoked.
 * The [completion] continuation is invoked when the coroutine completes with a result or an exception.
 */
@SinceKotlin("1.3")
@Suppress("UNCHECKED_CAST")
public fun <T> (suspend () -> T).startCoroutine(completion: Continuation<T>) {
    createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}

这里的 createCoroutineUnintercepted 又是在创建协程,completion 实际上就是上面 launch 中创建的协程了。

1、这个 createCoroutineUnintercepted 为啥又创建一边??

2、createCoroutineUnintercepted 的源码在哪里?

写回答

4回答

xxxxjase

提问者

2020-10-07



下面是一个 launch 中创建的协程:

val coroutine = if (start.isLazy) // 这里创建了协程
       LazyStandaloneCoroutine(newContext, block) else
       StandaloneCoroutine(newContext, active = true) 里面创建的协程也是一个 Continuation 对象

suspend lambda 通过编译器处理后,会生成一个 SuspendLambda 类

继承关系如下:SuspendLambda -> ContinuationImpl -> BaseContinuationImpl : Continuation<Any?>

可以看到,还是一个 Continuation 对象;

然后会将上面的 Continuation 对象作为构造器的参数,然后创建 suspend lambda 对应的。

我的理解是下面的这个 Continuation 是 launch 中的那个 Continuation 的包装了一层;


0
1
bennyhuo
launch里new出来的是completion。你仔细看看。
2020-10-07
共1条回复

xxxxjase

提问者

2020-10-06

CoroutineScope.launch 方法里面已经创建了协程:Coroutine

val coroutine = if (start.isLazy) // 这里创建了协程
       LazyStandaloneCoroutine(newContext, block) else
       StandaloneCoroutine(newContext, active = true)

那为啥还要 createCoroutineUnintercepted?? 这两个是什么关系呢??不得骑姐。。






0
4
bennyhuo
回复
xxxxjase
深入理解Kotlin协程
2020-10-06
共4条回复

bennyhuo

2020-10-06

更正:

回复里面同学在 Jvm 里面找到了这个函数的实现。我确认了一下哈,后来的 Kotlin 标准库的源码有些变化,createCoroutineUnintercepted 函数现在提供了实现,不过常规的情况下还是会走到下面的 create 函数调用,这个函数仍然是需要编译器通过传入的 Lambda 表达式来生成的哈。

Kotlin 协程这几年的源码变动确实比较大,类似的还有最早的时候 Continuation 的 resume和 resumeWithException 还是它的函数,后来就成了扩展函数等等。大家在学习时,以源码为准~

---

createCoroutineUnintercepted 这个函数的源码是没有的,编译器编译时会生成一些字节码,也就是编译器会基于参数lambda表达式生成一个SuspendLambda的类,这个点咱们视频里面有提到哈。

0
7
慕前端9039556
回复
bennyhuo
我断点一下,是这样的。
2020-10-13
共7条回复

bennyhuo

2020-10-06

这是官方的源码哈。
createCoroutineUnintercepted 是创建协程最终要调用到的代码,所有创建协程的api其实都是对它的封装。

0
0

学会Kotlin 突破开发语言瓶颈

如果有一门语言可以取代Java,那么它一定是Kotlin。

1695 学习 · 447 问题

查看课程