diff --git a/utils/src/main/kotlin/cn/tursom/utils/coroutine/CurrentThreadCoroutineScope.kt b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CurrentThreadCoroutineScope.kt index 29cd079..826c864 100644 --- a/utils/src/main/kotlin/cn/tursom/utils/coroutine/CurrentThreadCoroutineScope.kt +++ b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CurrentThreadCoroutineScope.kt @@ -1,31 +1,43 @@ package cn.tursom.utils.coroutine +import cn.tursom.core.SimpThreadLocal import cn.tursom.core.cast -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.* import kotlin.coroutines.CoroutineContext import kotlin.coroutines.coroutineContext object CurrentThreadCoroutineScope { - private val currentThreadCoroutineScopeThreadLocal = ThreadLocal() + private val eventLoopThreadLocal: SimpThreadLocal = SimpThreadLocal { + newBlockingEventLoop() + } private suspend fun getCoroutineScope(): CoroutineScope { - return currentThreadCoroutineScopeThreadLocal.get() ?: kotlin.run { - val eventLoop = newBlockingEventLoop() - val coroutineScope = newBlockingCoroutine(coroutineContext, Thread.currentThread(), eventLoop) - currentThreadCoroutineScopeThreadLocal.set(coroutineScope) - coroutineScope - } + val eventLoop = eventLoopThreadLocal.get() + val coroutineScopeContext = CoroutineScopeContext() + val newBlockingCoroutine = newBlockingCoroutine( + coroutineContext + coroutineScopeContext + Dispatchers.Unconfined, + Thread.currentThread(), + eventLoop + ) + coroutineScopeContext.coroutineScope = newBlockingCoroutine + return newBlockingCoroutine } suspend fun launch( start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit - ) { - getCoroutineScope().start(start, block = block) + ): Job { + val coroutineScope = getCoroutineScope() + //coroutineScope.launch(start = start, block = block) + coroutineScope.start(start, block = block) + return coroutineScope as Job } + private val EventLoop = Class.forName("kotlinx.coroutines.EventLoop") + private val EventLoopShouldBeProcessedFromContext = EventLoop.methods + .first { it.name == "shouldBeProcessedFromContext" } + .apply { isAccessible = true } + private val BlockingEventLoop = Class.forName("kotlinx.coroutines.BlockingEventLoop") private val BlockingEventLoopConstructor = BlockingEventLoop .getConstructor(Thread::class.java) 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 da94e78..71b9289 100644 --- a/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt +++ b/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt @@ -1,8 +1,6 @@ package cn.tursom.utils.coroutine -import cn.tursom.core.cast import kotlinx.coroutines.* -import kotlin.coroutines.CoroutineContext import kotlin.coroutines.coroutineContext val testCoroutineLocal = CoroutineLocal() @@ -17,37 +15,29 @@ suspend fun test() { println(Thread.currentThread().name) } -val EventLoop = Class.forName("kotlinx.coroutines.EventLoop") -val AbstractCoroutine = Class.forName("kotlinx.coroutines.AbstractCoroutine") - -val BlockingEventLoop = Class.forName("kotlinx.coroutines.BlockingEventLoop") -val BlockingEventLoopConstructor = BlockingEventLoop.getConstructor(Thread::class.java).apply { isAccessible = true } -fun newBlockingEventLoop(thread: Thread = Thread.currentThread()): CoroutineDispatcher { - return BlockingEventLoopConstructor.newInstance(thread) as CoroutineDispatcher -} - -val BlockingCoroutine = Class.forName("kotlinx.coroutines.BlockingCoroutine") -val BlockingCoroutineConstructor = BlockingCoroutine.constructors[0].apply { isAccessible = true } -val BlockingCoroutineStart = BlockingCoroutine.methods.first { it.name == "start" && it.parameters.size == 3 }.apply { isAccessible = true } -val BlockingCoroutineJoinBlocking = BlockingCoroutine.methods.first { it.name == "joinBlocking" }.apply { isAccessible = true } - -fun newBlockingCoroutine(coroutineContext: CoroutineContext, thread: Thread = Thread.currentThread(), eventLoop: CoroutineDispatcher): CoroutineScope { - return BlockingCoroutineConstructor.newInstance(coroutineContext, thread, eventLoop).cast() -} - -fun CoroutineScope.start(start: CoroutineStart = CoroutineStart.DEFAULT, receiver: CoroutineScope = this, block: suspend CoroutineScope.() -> Any?) { - return BlockingCoroutineStart.invoke(this, start, receiver, block).cast() -} - -fun CoroutineScope.joinBlocking() { - BlockingCoroutineJoinBlocking.invoke(this) -} - suspend fun main() { - test() CurrentThreadCoroutineScope.launch { - test() + 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)