当前位置:网站首页>Kotlin coroutine createCoroutine and startCoroutine principle
Kotlin coroutine createCoroutine and startCoroutine principle
2022-08-07 17:25:00 【Xiaofenghanyue】
How coroutines are created and started?This article takes you to find out.
一、createCoroutine 和 startCoroutine
在Continuation.kt文件中,有2个基础API,Here it is mentioned separately,It is convenient for us to understand laterlaunch.
public fun <T> (suspend () -> T).createCoroutine(
completion: Continuation<T>
): Continuation<Unit> =
SafeContinuation(createCoroutineUnintercepted(completion).intercepted(), COROUTINE_SUSPENDED)
public fun <T> (suspend () -> T).startCoroutine(
completion: Continuation<T>
) {
createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}
createCoroutine和startCoroutineIt is the basis for creating and starting coroutinesAPI,launch、asyncThe base is used to some extent at the bottom levelAPI,launch和asyncIt's just packaging.所以,Let's get hold of them first.
这2The functions don't look much different,一个调用了resumeStart a coroutine,一个没有调用,It needs to be called externallyresume(createCoroutine会把Continuation返回出去).
既然launch和asyncThey can be used to create and start coroutines,So can we use them directly to create and start coroutines?那当然可以.这里我举个startCoroutine的例子,Look carefully at its function declaration,It's actually an extension function,扩展的是(suspend () -> T)这种类型.
(suspend () -> T):suspend函数+返回类型是T
它可以有2种写法:
//方式1-----------
val block = suspend {
...
"云天明"
}
block.startCoroutine(continuation)
//方式2--------------
suspend fun getUserName(): String {
...
return "云天明"
}
(::getUserName).startCoroutine(continuation)
One is anonymoussuspend函数,One is the normal named onesuspend函数.现在,We simply write itdemo来调一下startCoroutine.
//StartCoroutine.kt
fun main() {
val continuation = object : Continuation<String> {
override val context: CoroutineContext
get() = EmptyCoroutineContext
override fun resumeWith(result: Result<String>) {
println("结果: ${
result.getOrNull()}")
}
}
block.startCoroutine(continuation)
Thread.sleep(3000L)
}
val block = suspend {
println("start")
delay(2000L)
println("end")
"DX3906"
}
It's very simple to tune up,startCoroutine是(suspend () -> T)的扩展函数,And need to pass oneContinuation参数.Let's decompile it first,长什么样子.
public final class StartCoroutineKt {
//blockThat piece is converted into a classStartCoroutineKt$block$1,An instance object is created here,It can be used directly later
private static final Function1<Continuation<? super String>, Object> block = new StartCoroutineKt$block$1((Continuation<? super StartCoroutineKt$block$1>) null);
public static final void main() {
//调用扩展函数,将block和continuation参数传入.
ContinuationKt.startCoroutine(block, new StartCoroutineKt$main$continuation$1());
Thread.sleep(3000);
}
public static final Function1<Continuation<? super String>, Object> getBlock() {
return block;
}
}
//对应block那块
final class StartCoroutineKt$block$1 extends SuspendLambda implements Function1<Continuation<? super String>, Object> {
int label;
StartCoroutineKt$block$1(Continuation<? super StartCoroutineKt$block$1> continuation) {
super(1, continuation);
}
//创建StartCoroutineKt$block$1实例
public final Continuation<Unit> create(Continuation<?> continuation) {
return new StartCoroutineKt$block$1(continuation);
}
public final Object invoke(Continuation<? super String> continuation) {
//创建StartCoroutineKt$block$1实例并执行invokeSuspend
return ((StartCoroutineKt$block$1) create(continuation)).invokeSuspend(Unit.INSTANCE);
}
public final Object invokeSuspend(Object $result) {
Object coroutine_suspended = IntrinsicsKt.getCOROUTINE_SUSPENDED();
//状态机
switch (this.label) {
case 0:
//label一开始是0
ResultKt.throwOnFailure($result);
System.out.println("start");
this.label = 1;
//Here the normal case will returnCOROUTINE_SUSPENDED,label已经改成1了,下次走case 1的逻辑
if (DelayKt.delay(2000, this) != coroutine_suspended) {
break;
} else {
return coroutine_suspended;
}
case 1:
//label为1,没有return,Continue to the last closing statement
ResultKt.throwOnFailure($result);
break;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
//结束
System.out.println("end");
return "云天明";
}
}
//对应Continuation那块
public final class StartCoroutineKt$main$continuation$1 implements Continuation<String> {
StartCoroutineKt$main$continuation$1() {
}
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
public void resumeWith(Object result) {
//输出结果
StringBuilder sb = new StringBuilder();
sb.append("结果: ");
sb.append((String) (Result.m29isFailureimpl(result) ? null : result));
System.out.println(sb.toString());
}
}
还是比较清晰的,
- 首先
object : Continuation<String>Yes definitely generates an anonymous inner class,在该类中,简单在resumeWithIt outputs the result - block那块代码,An anonymous inner class is also generated.需要注意的是,它继承自SuspendLambda,这个没见过,Analysis later,里面有几个方法:create、invoke、invokeSuspend.其中createis to create an instance of this class,invoke是调用create方法并执行invokeSuspend,invokeSuspendInside is the logic related to the state machine.
- main里面执行了
ContinuationKt.startCoroutine(block, continuation),The extension method is called(This is how extension methods work)
We understand the general structure of the decompiled code,Now need to analyzestartCoroutineHow exactly did it go,See how it uses the decompiled code.
createCoroutineUnintercepted
public fun <T> (suspend () -> T).startCoroutine(
completion: Continuation<T>
) {
createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}
//这个函数是expect的,没有函数体
public expect fun <T> (suspend () -> T).createCoroutineUnintercepted(
completion: Continuation<T>
): Continuation<Unit>
startCoroutine首先是调用了createCoroutineUnintercepted函数,而createCoroutineUnintercepted是expect的,它是一种声明.因为Kotlin是跨平台的,So part of the logic is platform dependent,这个createCoroutineUnintercepted就是这种.It has no function body,我们只关心JVM平台,所以需要到JVMFind the implementation of this function on the platform.在Kotlin源码地图文章中,We mentioned the coroutine source code,分为2个仓库,一个是Kotlin仓库,一个是KotlinCoroutine repository.这个createCoroutineUnintercepted是在Kotlin仓库中,具体位置是:kotlin/libraries/stdlib/jvm/src/kotlin/coroutines/intrinsics/IntrinsicsJvm.kt
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
completion: Continuation<T>
): Continuation<Unit> {
val probeCompletion = probeCoroutineCreated(completion)
return if (this is BaseContinuationImpl)
//走这里
create(probeCompletion)
else
createCoroutineFromSuspendFunction(probeCompletion) {
(this as Function1<Continuation<T>, Any?>).invoke(it)
}
}
咦,createCoroutineUnintercepted居然也是(suspend () -> T)的扩展函数,所以if那里的this指的就是block,也就是StartCoroutineKt$block$1.它继承自SuspendLambda.
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
}
internal abstract class ContinuationImpl(
completion: Continuation<Any?>?,
private val _context: CoroutineContext?
) : BaseContinuationImpl(completion) {
......
}
//BaseContinuationImpl实现了Continuation接口
internal abstract class BaseContinuationImpl(
public val completion: Continuation<Any?>?
) : Continuation<Any?>, CoroutineStackFrame, Serializable {
...
}
SuspendLambda是ContinuationImpl的子类,而ContinuationImpl是BaseContinuationImpl的子类.所以上面的if (this is BaseContinuationImpl)判断是ok的,会走到create(probeCompletion).也就是StartCoroutineKt$block$1的create方法,will be created insideStartCoroutineKt$block$1实例.
public final Continuation<Unit> create(Continuation<?> continuation) {
return new StartCoroutineKt$block$1(continuation);
}
Going here is equivalent tostartCoroutine中的createCoroutineUnintercepted(completion)这一步就走完了,它最终返回的是StartCoroutineKt$block$1的实例,也就是一个Continuation.It marks the coroutine has been created.再来看下intercepted是什么逻辑
intercepted
public fun <T> (suspend () -> T).startCoroutine(
completion: Continuation<T>
) {
createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}
//好家伙,intercepted也是expect的
public expect fun <T> Continuation<T>.intercepted(): Continuation<T>
发现这里的interceptedExtension functions tooexpect的,又得去kotlin仓库里面找jvm相关的实现.我找了下,The path is here:kotlin/libraries/stdlib/jvm/src/kotlin/coroutines/intrinsics/IntrinsicsJvm.kt
public actual fun <T> Continuation<T>.intercepted(): Continuation<T> =
(this as? ContinuationImpl)?.intercepted() ?: this
intercepted是一个扩展函数,这里的this也就是前面createCoroutineUnintercepted(completion)创建出来的StartCoroutineKt$block$1实例,它本身是SuspendLambda的子类,而SuspendLambda就是ContinuationImpl的子类.所以这里的as?will convert successfully,Converted out is notnull.也就是说走到了ContinuationImpl的intercepted()
internal abstract class ContinuationImpl(
completion: Continuation<Any?>?,
private val _context: CoroutineContext?
) : BaseContinuationImpl(completion) {
constructor(completion: Continuation<Any?>?) : this(completion, completion?.context)
//这个context其实就是传入的Continuation中的context
public override val context: CoroutineContext
get() = _context!!
@Transient
private var intercepted: Continuation<Any?>? = null
public fun intercepted(): Continuation<Any?> =
intercepted
?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
.also {
intercepted = it }
}
@Transient
private var intercepted: Continuation<Any?>? = null
public fun intercepted(): Continuation<Any?> =
intercepted
?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
.also {
intercepted = it }
When doing this for the first timeintercepted是null,那么会从context中取ContinuationInterceptor,而context就是Continuation传入的context,我们传入的是EmptyCoroutineContext,取出来是null(ContinuationInterceptor会对Continuation进行拦截,Then assign the execution logic to the corresponding thread,The logic of this block will be discussed in detail later,就不详细展开了.),所以这里intercepted()The final execution result is returnedthis,this也就是StartCoroutineKt$block$1(block函数生成的类).
intercepted()Come back when you're donestartCoroutine:
public fun <T> (suspend () -> T).startCoroutine(
completion: Continuation<T>
) {
createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}
resume
就差最后一个resume(Unit)了,前面createCoroutineUnintercepted(completion).intercepted()创建出来的是StartCoroutineKt$block$1实例,So we need to look inside this classresume函数.
Let's talk about class inheritance:
StartCoroutineKt$block$1 extends SuspendLambda implements Function1
internal abstract class SuspendLambda(
public override val arity: Int,
completion: Continuation<Any?>?
) : ContinuationImpl(completion), FunctionBase<Any?>, SuspendFunction
internal abstract class ContinuationImpl(
completion: Continuation<Any?>?,
private val _context: CoroutineContext?
) : BaseContinuationImpl(completion)
internal abstract class BaseContinuationImpl(
public val completion: Continuation<Any?>?
) : Continuation<Any?>, CoroutineStackFrame, Serializable
public interface Continuation<in T> {
public val context: CoroutineContext
public fun resumeWith(result: Result<T>)
}
StartCoroutineKt$block$1中没有该resume函数,其父类SuspendLambdaThere is also no such function,再到SuspendLambda的父类ContinuationImpl中,发现也没有.再到ContinuationImpl的父类BaseContinuationImpl中,There is also no such function,只有一个resumeWith,奇了怪了.后来,我发现这个resume函数是一个扩展函数:
public inline fun <T> Continuation<T>.resume(value: T): Unit =
resumeWith(Result.success(value))
而resumeThis extension function is ultimately calledresumeWith,resumeWidth的实现在BaseContinuationImpl中.
public final override fun resumeWith(result: Result<Any?>) {
var current = this
var param = result
while (true) {
probeCoroutineResumed(current)
with(current) {
val completion = completion!! // fail fast when trying to resume continuation without completion
val outcome: Result<Any?> =
try {
val outcome = invokeSuspend(param)
if (outcome === COROUTINE_SUSPENDED) return
Result.success(outcome)
} catch (exception: Throwable) {
Result.failure(exception)
}
releaseIntercepted() // this state machine instance is terminating
if (completion is BaseContinuationImpl) {
current = completion
param = outcome
} else {
//label等于1时走这里
completion.resumeWith(outcome)
return
}
}
}
}
This one is openwhile(true)循环,不断地执行invokeSuspend(),如果遇到invokeSuspend返回结果是COROUTINE_SUSPENDED则退出while(true)循环.
public final Object invokeSuspend(Object $result) {
Object coroutine_suspended = IntrinsicsKt.getCOROUTINE_SUSPENDED();
//状态机
switch (this.label) {
case 0:
//label一开始是0
ResultKt.throwOnFailure($result);
System.out.println("start");
this.label = 1;
//Here the normal case will returnCOROUTINE_SUSPENDED,label已经改成1了,下次走case 1的逻辑
if (DelayKt.delay(2000, this) != coroutine_suspended) {
break;
} else {
return coroutine_suspended;
}
case 1:
//label为1,没有return,Continue to the last closing statement
ResultKt.throwOnFailure($result);
break;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
//结束
System.out.println("end");
return "云天明";
}
invokeSuspend实际上就是我们的demo中的StartCoroutineKt$block$1里的invokeSuspend函数.在demo中,这个invokeSuspendThe first time the state machine is there,label是0,So it will come right awayDelayKt.delay(2000, this),它是一个挂起函数,The result will be obtained at this time:COROUTINE_SUSPENDED.resumeWith遇到COROUTINE_SUSPENDED就不会继续往下走了,等到delay执行完成之后,会回调这个resumeWith函数,再继续走invokeSuspend,此时label已经是1了,Go to the state machine logic,返回结果“云天明”.
This result will be resumeWidth的outcomereceive,resumeWidth中的这个completion其实就是我们demo中的StartCoroutineKt$main$continuation$1(实现Continuation<String>的那个类,是通过构造函数传进来的),最终会走到completion.resumeWith(outcome),That is, it came to the place where the output results:println("结果: ${result.getOrNull()}").整个流程就走完了.
二、小结
createCoroutine用来创建协程,startCoroutineUsed to create and start coroutines.The principles inside them are similar,Just a no callresume启动协程,另一个调用了resume启动协程.编译的时候,会生成一个SuspendLambda的实现类,该类invokeSuspendThe logic used to execute the state machine,调用resumeThe state machine is then triggered,The state machine is finished,The coroutine is over.
三、小练习
You can read it after reading this article,Try to analyze itlaunch的原理,看看launch与startCoroutine是什么关系.
边栏推荐
- Can a laptop connect to a mobile phone hotspot? Steps to connect a laptop to a mobile phone personal hotspot
- 【带限制的完全背包】Educational Codeforces Round 133 (Rated for Div. 2) D. Chip Move
- 笔记本能连接手机热点吗 笔记本电脑连接手机个人热点的步骤
- How to clean up computer C drive Win7 clean up computer C drive junk files method introduction
- 网页不让复制的文字如何复制 不允许复制的网页怎么复制
- 使用C语言实现静态顺序表
- 网页浏览记录如何查看 怎样查历史网页浏览记录
- 分布式一致性协议 之 NWR协议与Gossip 协议
- FutureTask源码深度剖析
- CNAS认可准则之纠正、纠正措施和预防措施的区别
猜你喜欢

How to handle the wireless network card of the laptop How to handle the wireless network card of the laptop

网线连不上网怎么回事 为什么网线插电脑上不了网

How to format Windows 7 laptop How to format Windows 7 laptop

Some common questions in technical job interviews

笔记本电脑上有蓝牙吗 笔记本电脑如何开蓝牙

win7nvidia控制面板在哪 win7系统怎么打开nvidia控制面板

重装系统什么软件好用 电脑系统重装哪个最好用

How to view web browsing history How to check history web browsing history

win7系统垃圾怎么清理_win7系统垃圾清理的方法

特征工程介绍
随机推荐
Some common questions in technical job interviews
做项目,你需要。。。【持续更新】
如何解决Win7无法正常启动
笔记本电脑无线网卡怎么办理 如何办理笔记本电脑的无线上网卡
C language - character reverse order ( gets( ) function)
In-depth analysis of options spot contract exchange system development description analysis
怎样设置电脑无线网络 如何设置无线网络连接
DOM总结
MySQL面试必备(二)索引篇
【带限制的完全背包】Educational Codeforces Round 133 (Rated for Div. 2) D. Chip Move
怎么做ppt详细步骤电脑 怎么做ppt模板制作
How to view web browsing history How to check history web browsing history
ELK日志平台搭建(一)
电脑屏幕老是一下黑屏一下亮怎么回事 电脑显示器老是黑一下又亮如何解决
重装系统什么软件好用 电脑系统重装哪个最好用
电脑看视频卡怎么解决 电脑看视频一卡一卡的解决教程
FutureTask源码深度剖析
win7添加字体怎么添加_win7添加字体步骤图解
Chrome scroll bar style modification how to operate Chrome browser scroll bar style customization method
Error:Connection refused: connect