CoroutineContext Key and Element are now inside CoroutineContext interface itself (just like Map.Entry)
ContinuationInterceptor companion object is named Key CoroutineContext.Element property for key is named just key AbstractCoroutineContextElement implements all of CoroutineContext.Element, including key
This commit is contained in:
@@ -16,23 +16,25 @@
|
||||
|
||||
package kotlin.coroutines
|
||||
|
||||
import kotlin.coroutines.CoroutineContext.*
|
||||
|
||||
/**
|
||||
* Base class for [CoroutineContextElement] implementations.
|
||||
* Base class for [CoroutineContext.Element] implementations.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
public abstract class AbstractCoroutineContextElement : CoroutineContextElement {
|
||||
public abstract class AbstractCoroutineContextElement(public override val key: Key<*>) : Element {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public override operator fun <E : CoroutineContextElement> get(key: CoroutineContextKey<E>): E? =
|
||||
if (this.contextKey == key) this as E else null
|
||||
public override operator fun <E : Element> get(key: Key<E>): E? =
|
||||
if (this.key == key) this as E else null
|
||||
|
||||
public override fun <R> fold(initial: R, operation: (R, CoroutineContextElement) -> R): R =
|
||||
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R =
|
||||
operation(initial, this)
|
||||
|
||||
public override operator fun plus(context: CoroutineContext): CoroutineContext =
|
||||
plusImpl(context)
|
||||
|
||||
public override fun minusKey(key: CoroutineContextKey<*>): CoroutineContext =
|
||||
if (this.contextKey == key) EmptyCoroutineContext else this
|
||||
public override fun minusKey(key: Key<*>): CoroutineContext =
|
||||
if (this.key == key) EmptyCoroutineContext else this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,10 +42,10 @@ public abstract class AbstractCoroutineContextElement : CoroutineContextElement
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
public object EmptyCoroutineContext : CoroutineContext {
|
||||
public override fun <E : CoroutineContextElement> get(key: CoroutineContextKey<E>): E? = null
|
||||
public override fun <R> fold(initial: R, operation: (R, CoroutineContextElement) -> R): R = initial
|
||||
public override fun <E : Element> get(key: Key<E>): E? = null
|
||||
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R = initial
|
||||
public override fun plus(context: CoroutineContext): CoroutineContext = context
|
||||
public override fun minusKey(key: CoroutineContextKey<*>): CoroutineContext = this
|
||||
public override fun minusKey(key: Key<*>): CoroutineContext = this
|
||||
public override fun hashCode(): Int = 0
|
||||
public override fun toString(): String = "EmptyCoroutineContext"
|
||||
}
|
||||
@@ -52,8 +54,8 @@ public object EmptyCoroutineContext : CoroutineContext {
|
||||
|
||||
// this class is not exposed, but is hidden inside implementations
|
||||
// this is a left-biased list, so that `plus` works naturally
|
||||
private class CombinedContext(val left: CoroutineContext, val element: CoroutineContextElement) : CoroutineContext {
|
||||
override fun <E : CoroutineContextElement> get(key: CoroutineContextKey<E>): E? {
|
||||
private class CombinedContext(val left: CoroutineContext, val element: Element) : CoroutineContext {
|
||||
override fun <E : Element> get(key: Key<E>): E? {
|
||||
var cur = this
|
||||
while (true) {
|
||||
cur.element[key]?.let { return it }
|
||||
@@ -66,13 +68,13 @@ private class CombinedContext(val left: CoroutineContext, val element: Coroutine
|
||||
}
|
||||
}
|
||||
|
||||
public override fun <R> fold(initial: R, operation: (R, CoroutineContextElement) -> R): R =
|
||||
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R =
|
||||
operation(left.fold(initial, operation), element)
|
||||
|
||||
public override operator fun plus(context: CoroutineContext): CoroutineContext =
|
||||
plusImpl(context)
|
||||
|
||||
public override fun minusKey(key: CoroutineContextKey<*>): CoroutineContext {
|
||||
public override fun minusKey(key: Key<*>): CoroutineContext {
|
||||
element[key]?.let { return left }
|
||||
val newLeft = left.minusKey(key)
|
||||
return when (newLeft) {
|
||||
@@ -85,8 +87,8 @@ private class CombinedContext(val left: CoroutineContext, val element: Coroutine
|
||||
private fun size(): Int =
|
||||
if (left is CombinedContext) left.size() + 1 else 2
|
||||
|
||||
private fun contains(element: CoroutineContextElement): Boolean =
|
||||
get(element.contextKey) == element
|
||||
private fun contains(element: Element): Boolean =
|
||||
get(element.key) == element
|
||||
|
||||
private fun containsAll(context: CombinedContext): Boolean {
|
||||
var cur = context
|
||||
@@ -96,7 +98,7 @@ private class CombinedContext(val left: CoroutineContext, val element: Coroutine
|
||||
if (next is CombinedContext) {
|
||||
cur = next
|
||||
} else {
|
||||
return contains(next as CoroutineContextElement)
|
||||
return contains(next as Element)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +117,7 @@ private class CombinedContext(val left: CoroutineContext, val element: Coroutine
|
||||
private fun CoroutineContext.plusImpl(context: CoroutineContext): CoroutineContext =
|
||||
if (context == EmptyCoroutineContext) this else // fast path -- avoid lambda creation
|
||||
context.fold(this) { acc, element ->
|
||||
val removed = acc.minusKey(element.contextKey)
|
||||
val removed = acc.minusKey(element.key)
|
||||
if (removed == EmptyCoroutineContext) element else {
|
||||
// make sure interceptor is always last in the context (and thus is fast to get when present)
|
||||
val interceptor = removed[ContinuationInterceptor]
|
||||
|
||||
@@ -21,30 +21,25 @@ import org.junit.Test
|
||||
import kotlin.coroutines.*
|
||||
|
||||
class CoroutineContextTest {
|
||||
data class CtxA(val i: Int) : AbstractCoroutineContextElement() {
|
||||
companion object : CoroutineContextKey<CtxA>
|
||||
override val contextKey get() = CtxA
|
||||
data class CtxA(val i: Int) : AbstractCoroutineContextElement(CtxA) {
|
||||
companion object Key : CoroutineContext.Key<CtxA>
|
||||
}
|
||||
|
||||
data class CtxB(val i: Int) : AbstractCoroutineContextElement() {
|
||||
companion object : CoroutineContextKey<CtxB>
|
||||
override val contextKey get() = CtxB
|
||||
data class CtxB(val i: Int) : AbstractCoroutineContextElement(CtxB) {
|
||||
companion object Key : CoroutineContext.Key<CtxB>
|
||||
}
|
||||
|
||||
data class CtxC(val i: Int) : AbstractCoroutineContextElement() {
|
||||
companion object : CoroutineContextKey<CtxC>
|
||||
override val contextKey get() = CtxC
|
||||
data class CtxC(val i: Int) : AbstractCoroutineContextElement(CtxC) {
|
||||
companion object Key : CoroutineContext.Key<CtxC>
|
||||
}
|
||||
|
||||
object Disp1 : AbstractCoroutineContextElement(), ContinuationInterceptor {
|
||||
object Disp1 : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
|
||||
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = continuation
|
||||
override val contextKey: CoroutineContextKey<*> = ContinuationInterceptor
|
||||
override fun toString(): String = "Disp1"
|
||||
}
|
||||
|
||||
object Disp2 : AbstractCoroutineContextElement(), ContinuationInterceptor {
|
||||
object Disp2 : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
|
||||
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = continuation
|
||||
override val contextKey: CoroutineContextKey<*> = ContinuationInterceptor
|
||||
override fun toString(): String = "Disp2"
|
||||
}
|
||||
|
||||
@@ -171,10 +166,10 @@ class CoroutineContextTest {
|
||||
assertNotEquals(ctx3, ctx4)
|
||||
}
|
||||
|
||||
private fun assertContents(ctx: CoroutineContext, vararg elements: CoroutineContextElement) {
|
||||
private fun assertContents(ctx: CoroutineContext, vararg elements: CoroutineContext.Element) {
|
||||
val set = ctx.fold(setOf<CoroutineContext>()) { a, b -> a + b }
|
||||
assertEquals(listOf(*elements), set.toList())
|
||||
for (elem in elements)
|
||||
assertTrue(ctx[elem.contextKey] == elem)
|
||||
assertTrue(ctx[elem.key] == elem)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user