From 3b8baada36c86e52f7ee718ce5d8a2dccee33605 Mon Sep 17 00:00:00 2001 From: tursom Date: Sat, 18 Jul 2020 17:36:16 +0800 Subject: [PATCH] add CoroutineLocalContinuation --- .../coroutine/CoroutineLocalContinuation.kt | 11 +++ .../kotlin/cn/tursom/utils/coroutine/utils.kt | 24 ++++++ .../utils/coroutine/CoroutineLocalTest.kt | 75 ++++++++++++------- 3 files changed, 83 insertions(+), 27 deletions(-) create mode 100644 utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocalContinuation.kt diff --git a/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocalContinuation.kt b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocalContinuation.kt new file mode 100644 index 0000000..b21b202 --- /dev/null +++ b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocalContinuation.kt @@ -0,0 +1,11 @@ +package cn.tursom.utils.coroutine + +import cn.tursom.core.cast +import kotlin.coroutines.Continuation +import kotlin.coroutines.CoroutineContext + +class CoroutineLocalContinuation( + private val completion: Continuation<*> +) : Continuation by completion.cast() { + override val context: CoroutineContext = completion.context + CoroutineLocalContext() +} \ No newline at end of file diff --git a/utils/src/main/kotlin/cn/tursom/utils/coroutine/utils.kt b/utils/src/main/kotlin/cn/tursom/utils/coroutine/utils.kt index 9be05c6..c8e7144 100644 --- a/utils/src/main/kotlin/cn/tursom/utils/coroutine/utils.kt +++ b/utils/src/main/kotlin/cn/tursom/utils/coroutine/utils.kt @@ -1,8 +1,11 @@ package cn.tursom.utils.coroutine +import cn.tursom.core.cast import kotlinx.coroutines.* +import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext +import kotlin.coroutines.coroutineContext fun CoroutineScope.launchWithCoroutineLocalContext( @@ -117,4 +120,25 @@ fun runBlockingWithEnhanceContext( return runBlocking(context + CoroutineLocalContext(map)) { block() } +} + +suspend inline fun runWithCoroutineLocalContext(block: () -> T): T { + return (block.cast<(Continuation<*>) -> T>()).invoke(CoroutineLocalContinuation(getContinuation())) +} + +suspend inline fun runWithCoroutineLocal(block: () -> T): T { + if (coroutineContext[CoroutineLocalContext] == null) { + return runWithCoroutineLocalContext(block) + } + return block() +} + +@Suppress("NOTHING_TO_INLINE") +inline fun getContinuation(continuation: Continuation<*>): Continuation<*> { + return continuation +} + +suspend inline fun getContinuation(): Continuation<*> { + val getContinuation: (continuation: Continuation<*>) -> Continuation<*> = ::getContinuation + return (getContinuation.cast Continuation<*>>()).invoke() } \ No newline at end of file diff --git a/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt b/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt index 71b9289..55ff8ea 100644 --- a/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt +++ b/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt @@ -1,12 +1,12 @@ package cn.tursom.utils.coroutine -import kotlinx.coroutines.* +import cn.tursom.core.cast +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlin.coroutines.Continuation import kotlin.coroutines.coroutineContext val testCoroutineLocal = CoroutineLocal() -val testCoroutineLocalList = Array(100000) { - CoroutineLocal() -}.asList() suspend fun test() { println(coroutineContext) @@ -15,30 +15,51 @@ suspend fun test() { println(Thread.currentThread().name) } -suspend fun main() { - CurrentThreadCoroutineScope.launch { - println("Unconfined : I'm working in thread ${Thread.currentThread().name}") - delay(50) - println("Unconfined : After delay in thread ${Thread.currentThread().name}") - delay(50) - println("Unconfined : After delay in thread ${Thread.currentThread().name}") +@Suppress("NOTHING_TO_INLINE") +inline fun getContinuation(continuation: Continuation<*>): Continuation<*> { + return continuation +} + +suspend inline fun getContinuation(): Continuation<*> { + val getContinuation: (continuation: Continuation<*>) -> Continuation<*> = ::getContinuation + return (getContinuation.cast Continuation<*>>()).invoke() +} + +suspend fun testCustomContext(): Int? = runWithCoroutineLocal { + println(coroutineContext) + return testCoroutineLocal.get() +} + +suspend fun main(): Unit = runWithCoroutineLocal { + repeat(100) { + testCoroutineLocal.set(it) + println(testCustomContext()) } - GlobalScope.launch(Dispatchers.Unconfined) { // 非受限的——将和主线程一起工作 - println("Unconfined : I'm working in thread ${Thread.currentThread().name}") - delay(50) - println("Unconfined : After delay in thread ${Thread.currentThread().name}") - delay(50) - println("Unconfined : After delay in thread ${Thread.currentThread().name}") - } - GlobalScope.launch { // 父协程的上下文,主 runBlocking 协程 - println("main runBlocking: I'm working in thread ${Thread.currentThread().name}") - delay(100) - println("main runBlocking: After delay in thread ${Thread.currentThread().name}") - delay(100) - println("main runBlocking: After delay in thread ${Thread.currentThread().name}") - } - println("end") - delay(1000) + ////println(::main.javaMethod?.parameters?.get(0)) + //println(coroutineContext) + //CurrentThreadCoroutineScope.launch { + // println("Unconfined : I'm working in thread ${Thread.currentThread().name}") + // delay(50) + // println("Unconfined : After delay in thread ${Thread.currentThread().name}") + // delay(50) + // println("Unconfined : After delay in thread ${Thread.currentThread().name}") + //} + //GlobalScope.launch(Dispatchers.Unconfined) { // 非受限的——将和主线程一起工作 + // println("Unconfined : I'm working in thread ${Thread.currentThread().name}") + // delay(50) + // println("Unconfined : After delay in thread ${Thread.currentThread().name}") + // delay(50) + // println("Unconfined : After delay in thread ${Thread.currentThread().name}") + //} + //GlobalScope.launch { // 父协程的上下文,主 runBlocking 协程 + // println("main runBlocking: I'm working in thread ${Thread.currentThread().name}") + // delay(100) + // println("main runBlocking: After delay in thread ${Thread.currentThread().name}") + // delay(100) + // println("main runBlocking: After delay in thread ${Thread.currentThread().name}") + //} + //println("end") + //delay(1000) //runBlockingWithEnhanceContext { // println(coroutineContext) // println(coroutineContext[Job] is CoroutineScope)