update CoroutineLocalContext

This commit is contained in:
tursom 2020-07-19 21:43:29 +08:00
parent b26f89ff5e
commit d2e5b72391
3 changed files with 73 additions and 32 deletions

View File

@ -1,15 +1,45 @@
package cn.tursom.utils.coroutine
import cn.tursom.core.cast
import kotlinx.coroutines.ThreadContextElement
import kotlin.coroutines.CoroutineContext
open class CoroutineLocalContext(
private val map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4)
) : CoroutineContext.Element, MutableMap<CoroutineLocal<*>, Any?> by map {
override val key: CoroutineContext.Key<*> get() = Companion
private val mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) }
) : CoroutineContext.Element, ThreadContextElement<MutableMap<CoroutineLocal<*>, Any?>>, MutableMap<CoroutineLocal<*>, Any?> {
override val key: CoroutineContext.Key<*> get() = Key
private var map: MutableMap<CoroutineLocal<*>, Any?> = mapBuilder()
override fun toString(): String {
return "CoroutineLocalContext$map"
}
companion object : CoroutineContext.Key<CoroutineLocalContext>
companion object Key : CoroutineContext.Key<CoroutineLocalContext>
override fun restoreThreadContext(context: CoroutineContext, oldState: MutableMap<CoroutineLocal<*>, Any?>) {
map = oldState
}
override fun updateThreadContext(context: CoroutineContext): MutableMap<CoroutineLocal<*>, Any?> {
val oldState = map
map = mapBuilder()
return oldState
}
@JvmName("getTyped")
operator fun <T> get(key: CoroutineLocal<T>): T? = map[key].cast()
operator fun <T> set(key: CoroutineLocal<T>, value: T?): T? = map.put(key, value).cast()
override val size: Int get() = map.size
override fun containsKey(key: CoroutineLocal<*>): Boolean = map.containsKey(key)
override fun containsValue(value: Any?): Boolean = map.containsValue(value)
override fun get(key: CoroutineLocal<*>): Any? = map[key]
override fun isEmpty(): Boolean = map.isEmpty()
override val entries: MutableSet<MutableMap.MutableEntry<CoroutineLocal<*>, Any?>> get() = map.entries
override val keys: MutableSet<CoroutineLocal<*>> get() = map.keys
override val values: MutableCollection<Any?> get() = map.values
override fun clear() = map.clear()
override fun put(key: CoroutineLocal<*>, value: Any?): Any? = map.put(key, value)
override fun putAll(from: Map<out CoroutineLocal<*>, Any?>) = map.putAll(from)
override fun remove(key: CoroutineLocal<*>): Any? = map.remove(key)
}

View File

@ -15,36 +15,36 @@ import kotlin.coroutines.coroutineContext
fun CoroutineScope.launchWithCoroutineLocalContext(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> Unit
): Job {
return launch(context + CoroutineLocalContext(map), start, block)
return launch(context + CoroutineLocalContext(mapBuilder), start, block)
}
@Suppress("DeferredIsResult")
fun <T> CoroutineScope.asyncWithCoroutineLocalContext(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> T
): Deferred<T> {
return async(context + CoroutineLocalContext(map), start, block)
return async(context + CoroutineLocalContext(mapBuilder), start, block)
}
suspend fun <T> withCoroutineLocalContext(
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> T
): T {
return withContext(CoroutineLocalContext(map), block)
return withContext(CoroutineLocalContext(mapBuilder), block)
}
@Throws(InterruptedException::class)
fun <T> runBlockingWithCoroutineLocalContext(
context: CoroutineContext = EmptyCoroutineContext,
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> T
): T {
return runBlocking(context + CoroutineLocalContext(map), block)
return runBlocking(context + CoroutineLocalContext(mapBuilder), block)
}
fun CoroutineScope.launchWithCoroutineScopeContext(
@ -67,29 +67,29 @@ fun <T> CoroutineScope.asyncWithCoroutineScopeContext(
fun CoroutineScope.launchWithCoroutineLocalAndCoroutineScopeContext(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> Unit
): Job {
return launch(context + CoroutineLocalContext(map) + CoroutineScopeContext(this), start, block)
return launch(context + CoroutineLocalContext(mapBuilder) + CoroutineScopeContext(this), start, block)
}
@Suppress("DeferredIsResult")
fun <T> CoroutineScope.asyncWithCoroutineLocalAndCoroutineScopeContext(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> T
): Deferred<T> {
return async(context + CoroutineLocalContext(map) + CoroutineScopeContext(this), start, block)
return async(context + CoroutineLocalContext(mapBuilder) + CoroutineScopeContext(this), start, block)
}
@Throws(InterruptedException::class)
fun <T> runBlockingWithCoroutineLocalAndCoroutineScopeContext(
context: CoroutineContext = EmptyCoroutineContext,
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> T
): T {
return runBlocking(context + CoroutineLocalContext(map) + CoroutineScopeContext()) {
return runBlocking(context + CoroutineLocalContext(mapBuilder) + CoroutineScopeContext()) {
CoroutineScopeContext set this
block()
}
@ -99,29 +99,29 @@ fun <T> runBlockingWithCoroutineLocalAndCoroutineScopeContext(
fun CoroutineScope.launchWithEnhanceContext(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> Unit
): Job {
return launch(context + CoroutineLocalContext(map), start, block)
return launch(context + CoroutineLocalContext(mapBuilder), start, block)
}
@Suppress("DeferredIsResult")
fun <T> CoroutineScope.asyncWithEnhanceContext(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> T
): Deferred<T> {
return async(context + CoroutineLocalContext(map), start, block)
return async(context + CoroutineLocalContext(mapBuilder), start, block)
}
@Throws(InterruptedException::class)
fun <T> runBlockingWithEnhanceContext(
context: CoroutineContext = EmptyCoroutineContext,
map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4),
mapBuilder: () -> MutableMap<CoroutineLocal<*>, Any?> = { HashMap(4) },
block: suspend CoroutineScope.() -> T
): T {
return runBlocking(context + CoroutineLocalContext(map)) {
return runBlocking(context + CoroutineLocalContext(mapBuilder)) {
block()
}
}
@ -224,6 +224,6 @@ fun combinedContext(coroutineContext: CoroutineContext): Boolean {
// return launch(Dispatchers.Main, block = action)
//}
suspend fun <T> runOnUiThread(action: suspend CoroutineScope.() -> T): T {
return withContext(Dispatchers.Main, action)
suspend fun <T> runOnUiThread(coroutineContext: CoroutineContext = EmptyCoroutineContext, action: suspend CoroutineScope.() -> T): T {
return withContext(coroutineContext + Dispatchers.Main, action)
}

View File

@ -1,6 +1,7 @@
package cn.tursom.utils.coroutine
import kotlinx.coroutines.*
import kotlin.coroutines.ContinuationInterceptor
import kotlin.coroutines.coroutineContext
val testCoroutineLocal = CoroutineLocal<Int>()
@ -33,13 +34,23 @@ class Test : CoroutineScope by MainScope() {
}
}
suspend fun main() {
//MainDispatcher.init()
runOnUiThread {
Test().test()
println(testCoroutineLocal.get())
object R : () -> R {
override fun invoke(): R = this
}
val threadLocal = ThreadLocal<String>()
fun main() = runBlocking {
println(coroutineContext[ContinuationInterceptor])
MainDispatcher.init()
runOnUiThread(threadLocal.asContextElement()) {
threadLocal.set("hello")
//Test().test()
//println(testCoroutineLocal.get())
println(threadLocal.get())
println(coroutineContext)
GlobalScope.launch(Dispatchers.Main) {
launch(Dispatchers.Main) {
println(threadLocal.get())
println(coroutineContext)
}
//runOnUiThread {