【Kotlin suspend coroutines 原理,代码转为状态机,粗略笔记】

结论

先说结论 感想,状态机转变 在最后面。

  • kotlin的suspend coroutines,为简化 异步代码 的书写,compiler处理异步回调。
  • 程序员注明异步的method ,以 direct call形式编码
  • compiler生成 回调,并以 状态机 调用

如视频所说,没有magic。类比于用 中文写程序,中文是宏命令啥的。(个人臆测)

我了解的点

  1. compiler帮你用 回调书写异步代码
  2. compiler将你的code,翻译成状态机,来运行、暂停你的代码 。
  3. 相当于用关键字 suspend、await 告诉compiler,我代码怎么拆分。然后compiler跟你拆成 一段一段的代码,来执行。

不足:

  1. 没 涉及 coroutines是如何调度的,具体啥线程。VM 的领域知识了吧。

推测

  • 细化了异步调用粒度,到 method粒度(其实就是coroutines)
    • 实际上Thread run方法,也是method粒度啊
    • 算是扩充了 异步调用的方式吧
  • Compiler 根据susepnd关键字,给你翻译成 一块一块的代码。
    • 所谓程序 加个中间层,啥问题都解决了
  • 所谓的non-suspend,确实是non-suspend。因为这套框架 一直在调度 语句块 (携程)。

感想

这尼玛确实不用深入理解,因为你Thread杂跑异步的,你不也没去理解嘛。。。。。。
这就是新手为啥好掌握吧,没有理解包袱。

资料

文章翻译的Google视频,本人也是听了个大概,故本文仅 抛砖引玉,难以深度解惑,诸君如有需要 还需自行看视频。 当然,各位如有指导、资料,更是期望不吝赐教,多谢。

YouTube视频地址,需用*

笔记

你写的源码,为direct call,没有callback。但Compiler 会给你生成Callback,就这么简单。。。。。。。。

Compiler 转变的大致步骤:

//direct call
suspend fun postItem(item: Item) {
	//suspend action
	val token = requestToken()
	
	//Continuation
	val post = createPost(token, item)
	procsessPost(post)
}

//indirect call CPS
fun postItem(item: Item) {
	requestToken { token ->
		createPost(token, item) { post ->
			processPost(post)
		}
	}
}
//direct call
suspend fun postItem(item: Item) {
	//Label 0 
	val token = requestToken()
	//Label 1 
  val post = createPost(token, item)
	//Label 2 
	procsessPost(post)
}

//direct call
suspend fun postItem(item: Item) {
	switch (label) {
		case 0:
			val token = requestToken()
		case 1:
			val post = createPost(token, item)
		case 2:
			porcessPost(post)
	}
}

// Save state
suspend fun postItem(item: Item, cont: Continuation) {
	val sm = object: CoroutineImpl {...}
	switch (sm.label) {
		case 0:
			//val token = requestToken(sm)
			sm.item = item
			sm.label = 1
			requestToken(sm)
		case 1:
			val post = createPost(token, item, sm)
		case 2:
			porcessPost(post)
	}
}

Compiler生成了一个Continuation,并添加到方法的形参中。而这个interface就是callback的抽象,并由Compiler根据 suspend等 关键字,抽取实际代码

interface Continuation<T> {
	val context: CorotineContext
  fun resume(value: T)
  fun resumeWithException(exception: Throwable)
}

// generate Callback
suspend fun postItem(item: Item, cont: Continuation) {
	val sm = object: CoroutineImpl {
		fun resume() {
			postItem(null, this)
		}
	}
	switch (sm.label) {
		case 0:
			//val token = requestToken(sm)
			sm.item = item
			sm.label = 1
			requestToken(sm)
		case 1
			val item = sm.item
			val token = sm.result as Token
			sm.label = 2
			val post = createPost(token, item, sm)
	}
}

State Machine vs Callbacks

//State Machine
suspend fun postItem(item: Item) {
	val token = requestToken()
	val post = createPost(token, item)
	procsessPost(post)
}

//Callbacks
fun postItem(item: Item) {
	requestToken { token ->
		createPost(token, item) { post ->
			processPost(post)
		}
	}
}
  1. StateMachine分配类少
    StateMachine:重用closure / state object (即对应Item)
    Callback: 每次调用suspend function,都需要create new object (即对应的callback实参))

  2. 便于 处理N个异步请求

//State Machine
suspend fun postItem(items: Item) {
	 for (item in items) {
		val token = requestToken()
		val post = createPost(token, item)
		procsessPost(post) 
	 }

}

//Callbacks
fun postItem(item: Item) {
	// 回调地狱
	requestToken { token ->
		createPost(token, item) { post ->
			processPost(post)
				requestToken { token ->
					createPost(token, item) { post ->
						processPost(post)
						//....
					}
				}
		}
	}
}
上一篇:vs2019 16.8更新之后的 C++20 协程co_yield用法


下一篇:RT-Thread ------ waitqueue