kotlin 协程-01 delay 函数(没写完)

kotlin 协程-01 delay 函数(没写完)

lucas Lv4

读代码困难

协程代码里有大量的Lambda,我每次看kotlinLambda,都有点头疼,但是不能退缩!!!

看源码

我们先看这delay函数的定义

1
2
3
4
5
6
7
8
9
10
11
// Delay.kt

public suspend fun delay(timeMillis: Long) {
if (timeMillis <= 0) return // don't delay
return suspendCancellableCoroutine sc@ { cont: CancellableContinuation<Unit> ->
// if timeMillis == Long.MAX_VALUE then just wait forever like awaitCancellation, don't schedule.
if (timeMillis < Long.MAX_VALUE) {
cont.context.delay.scheduleResumeAfterDelay(timeMillis, cont)
}
}
}

这里返回了一个Lambda,这个Lambda接受一个CancellableContinuation<Unit>,并调用了scheduleResumeAfterDelay方法

接下我们看看这个Lambda怎么定义的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// CancellableCoroutine.kt

public suspend inline fun <T> suspendCancellableCoroutine(
crossinline block: (CancellableContinuation<T>) -> Unit
): T =
suspendCoroutineUninterceptedOrReturn { uCont ->
val cancellable = CancellableContinuationImpl(uCont.intercepted(), resumeMode = MODE_CANCELLABLE)
/*
* For non-atomic cancellation we setup parent-child relationship immediately
* in case when`block`blocks the current thread (e.g. Rx2 with trampoline scheduler), but
* properly supports cancellation.
*/
cancellable.initCancellability()
block(cancellable)
cancellable.getResult()
}

这个suspendCancellableCoroutine接受了另一个Lambda block,这个block就是上面Delay.kt里面大括号里面的所有代码。

suspendCancellableCoroutine通过suspendCoroutineUninterceptedOrReturn方法来执行逻辑

而且这是一个inline方法,这到不太影响我们来梳理代码逻辑,注意返回值即可

我们继续看suspendCoroutineUninterceptedOrReturn

1
2
3
4
5
6
7
8
// Intrinsic.kt

public suspend inline fun <T> suspendCoroutineUninterceptedOrReturn(
crossinline block: (Continuation<T>) -> Any?
): T {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
throw NotImplementedError("Implementation of suspendCoroutineUninterceptedOrReturn is intrinsic")
}

这里我们直接进入了Intrinsic.kt里,说明这里已经到了底层了,就没必要看了,我们继续回到CancellableCoroutine.kt

我们看到他新建了一个cancellable,然后调用initCancellability,然后执行了block,也就是执行了cancellable.context.delay.scheduleResumeAfterDelay(timeMillis, cancellable)

前面都是初始化工作,关键就是这个,到此我们观察代码,最终定位到了这里,也就是一开始我们看到的那一点点代码

并且这些定位工作是值得的,他让我们可以放心地去专注于我们的主要逻辑了

我们点进scheduleResumeAfterDelay

1
2
3
4
5
6
7
8
9
10
11
12
@InternalCoroutinesApi
public interface Delay {

...

public fun scheduleResumeAfterDelay(
timeMillis: Long,
continuation: CancellableContinuation<Unit>
)

...
}

发现这是一个Interface里的方法

那么我们就看看这个这个Interface是在哪实现的

我们进入这个delay

1
2
internal val CoroutineContext.delay: Delay get() = 
get(ContinuationInterceptor) as? Delay ?: DefaultDelay

这里是在尝试将get(ContinuationInterceptor)的返回值转成Delay,失败就返回DefaultDelay

看看这个DefaultDelay

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// DefaultExecutor.kt

@PublishedApi
internal actual val DefaultDelay: Delay = initializeDefaultDelay()

private fun initializeDefaultDelay(): Delay {
// Opt-out flag
if (!defaultMainDelayOptIn) return DefaultExecutor
val main = Dispatchers.Main
/*
* When we already are working with UI and Main threads, it makes
* no sense to create a separate thread with timer that cannot be controller
* by the UI runtime.
*/
return if (main.isMissing() || main !is Delay) DefaultExecutor else main
}

@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
internal actual object DefaultExecutor : EventLoopImplBase(), Runnable {
...
}

可以看到,这里返回一个一个Dispacher.Main或者一个DefaultExecutor

而这个DefaultExecutor继承实现自EventLoopImplBaseRunnable

EventLoopImpBase实现了Delay

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// EventLoopCommon.kt

internal abstract class EventLoopImplBase: EventLoopImplPlatform(), Delay {
...
override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
val timeNanos = delayToNanos(timeMillis)
if (timeNanos < MAX_DELAY_NS) {
val now = nanoTime()
DelayedResumeTask(now + timeNanos, continuation).also { task ->
/*
* Order is important here: first we schedule the heap and only then
* publish it to continuation. Otherwise,`DelayedResumeTask`would
* have to know how to be disposed of even when it wasn't scheduled yet.
*/
schedule(now, task)
continuation.disposeOnCancellation(task)
}
}
}
...
}

.

  • Title: kotlin 协程-01 delay 函数(没写完)
  • Author: lucas
  • Created at : 2023-10-25 15:01:33
  • Updated at : 2024-11-13 10:38:46
  • Link: https://darkflamemasterdev.github.io/2023/10/25/kotlin-协程-01-delay-函数/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
kotlin 协程-01 delay 函数(没写完)