add MainCoroutineDispatcherFactory

This commit is contained in:
tursom 2020-07-19 13:11:44 +08:00
parent a1046bca98
commit b26f89ff5e
6 changed files with 63 additions and 17 deletions

View File

@ -1,6 +1,7 @@
package cn.tursom.utils.coroutine
import cn.tursom.core.cast
import cn.tursom.core.toHexString
import kotlinx.coroutines.Job
import java.util.concurrent.ConcurrentHashMap
import kotlin.coroutines.CoroutineContext
@ -43,6 +44,8 @@ open class CoroutineLocal<T> {
return true
}
override fun toString(): String = "CoroutineLocal@${hashCode().toHexString(false)}"
companion object {
private val attachMap = ConcurrentHashMap<CoroutineContext, MutableMap<CoroutineLocal<*>, Any?>>()
override fun toString(): String = attachMap.toString()

View File

@ -0,0 +1,13 @@
package cn.tursom.utils.coroutine
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.MainCoroutineDispatcher
import kotlinx.coroutines.internal.MainDispatcherFactory
@Suppress("unused")
@InternalCoroutinesApi
class MainCoroutineDispatcherFactory : MainDispatcherFactory {
override val loadPriority: Int = 1
override fun createDispatcher(allFactories: List<MainDispatcherFactory>): MainCoroutineDispatcher = MainDispatcher
}

View File

@ -1,27 +1,42 @@
package cn.tursom.utils.coroutine
import cn.tursom.core.cast
import kotlinx.coroutines.ExecutorCoroutineDispatcher
import kotlinx.coroutines.MainCoroutineDispatcher
import kotlinx.coroutines.asCoroutineDispatcher
import java.io.Closeable
import java.lang.reflect.Field
import java.lang.reflect.Modifier
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.concurrent.thread
import kotlin.coroutines.CoroutineContext
object MainDispatcher : MainCoroutineDispatcher(), Closeable {
private val dispatcher = Executors.newSingleThreadExecutor {
thread(start = false, block = it::run, name = "mainDispatcher", isDaemon = false)
private val loaded = AtomicBoolean(false)
private val dispatcher: ExecutorCoroutineDispatcher = Executors.newSingleThreadExecutor {
thread(start = false, block = it::run, name = "MainDispatcher", isDaemon = false)
}.asCoroutineDispatcher()
fun init() {
val mainDispatcherLoader = Class.forName("kotlinx.coroutines.internal.MainDispatcherLoader")
val dispatcher = mainDispatcherLoader.getDeclaredField("dispatcher")
private var oldDispatcher: MainCoroutineDispatcher? = null
private val mainDispatcherLoader: Class<*> = Class.forName("kotlinx.coroutines.internal.MainDispatcherLoader")
private val dispatcherField: Field = mainDispatcherLoader.getDeclaredField("dispatcher").also { dispatcher ->
dispatcher.isAccessible = true
val mf: Field = Field::class.java.getDeclaredField("modifiers")
mf.isAccessible = true
mf.setInt(dispatcher, dispatcher.modifiers and Modifier.FINAL.inv())
dispatcher.set(null, this)
}
fun init() {
if (loaded.compareAndSet(false, true)) {
oldDispatcher = dispatcherField.get(null).cast()
dispatcherField.set(null, this)
}
}
fun resume() {
if (loaded.compareAndSet(true, false) && oldDispatcher != null) {
dispatcherField.set(null, oldDispatcher)
}
}
override val immediate: MainCoroutineDispatcher get() = this

View File

@ -218,4 +218,12 @@ fun combinedContext(coroutineContext: CoroutineContext): Boolean {
left.set(coroutineContext, leftObj + CoroutineLocalContext())
}
return true
}
//fun CoroutineScope.runOnUiThread(action: suspend CoroutineScope.() -> Unit): Job {
// return launch(Dispatchers.Main, block = action)
//}
suspend fun <T> runOnUiThread(action: suspend CoroutineScope.() -> T): T {
return withContext(Dispatchers.Main, action)
}

View File

@ -0,0 +1 @@
cn.tursom.utils.coroutine.MainDispatcherFactory

View File

@ -23,23 +23,29 @@ interface CoroutineLocalTest {
}
class Test : CoroutineScope by MainScope() {
suspend fun test(): Job {
println(this)
suspend fun test() {
testCoroutineLocal.set(1)
println(coroutineContext)
return coroutineScope {
println(this)
coroutineScope {
println(coroutineContext)
println(Thread.currentThread().name)
delay(1)
return@coroutineScope launch {
println(Thread.currentThread().name)
}
}
}
}
suspend fun main() {
MainDispatcher.init()
Test().test().join()
//MainDispatcher.init()
runOnUiThread {
Test().test()
println(testCoroutineLocal.get())
println(coroutineContext)
GlobalScope.launch(Dispatchers.Main) {
println(coroutineContext)
}
//runOnUiThread {
// println(coroutineContext)
// println(testCoroutineLocal.get())
//}
}
MainDispatcher.close()
}