add CurrentThreadCoroutineScope

This commit is contained in:
tursom 2020-07-18 16:29:02 +08:00
parent 78c06598e1
commit f4ec9ca3c8
2 changed files with 44 additions and 42 deletions

View File

@ -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<CoroutineScope>()
private val eventLoopThreadLocal: SimpThreadLocal<CoroutineDispatcher> = 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)

View File

@ -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<Int>()
@ -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)