kotlin.coroutines.CoroutineContextImpl.kt Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package kotlin.coroutines
import kotlin.coroutines.CoroutineContext.*
import kotlin.io.Serializable
/**
* Base class for [CoroutineContext.Element] implementations.
*/
@SinceKotlin("1.3")
public abstract class AbstractCoroutineContextElement(public override val key: Key<*>) : Element
/**
* An empty coroutine context.
*/
@SinceKotlin("1.3")
public object EmptyCoroutineContext : CoroutineContext, Serializable {
private const val serialVersionUID: Long = 0
private fun readResolve(): Any = EmptyCoroutineContext
public override fun get(key: Key): E? = null
public override fun fold(initial: R, operation: (R, Element) -> R): R = initial
public override fun plus(context: CoroutineContext): CoroutineContext = context
public override fun minusKey(key: Key<*>): CoroutineContext = this
public override fun hashCode(): Int = 0
public override fun toString(): String = "EmptyCoroutineContext"
}
//--------------------- internal impl ---------------------
// this class is not exposed, but is hidden inside implementations
// this is a left-biased list, so that `plus` works naturally
@SinceKotlin("1.3")
internal class CombinedContext(
private val left: CoroutineContext,
private val element: Element
) : CoroutineContext, Serializable {
override fun get(key: Key): E? {
var cur = this
while (true) {
cur.element[key]?.let { return it }
val next = cur.left
if (next is CombinedContext) {
cur = next
} else {
return next[key]
}
}
}
public override fun fold(initial: R, operation: (R, Element) -> R): R =
operation(left.fold(initial, operation), element)
public override fun minusKey(key: Key<*>): CoroutineContext {
element[key]?.let { return left }
val newLeft = left.minusKey(key)
return when {
newLeft === left -> this
newLeft === EmptyCoroutineContext -> element
else -> CombinedContext(newLeft, element)
}
}
private fun size(): Int {
var cur = this
var size = 2
while (true) {
cur = cur.left as? CombinedContext ?: return size
size++
}
}
private fun contains(element: Element): Boolean =
get(element.key) == element
private fun containsAll(context: CombinedContext): Boolean {
var cur = context
while (true) {
if (!contains(cur.element)) return false
val next = cur.left
if (next is CombinedContext) {
cur = next
} else {
return contains(next as Element)
}
}
}
override fun equals(other: Any?): Boolean =
this === other || other is CombinedContext && other.size() == size() && other.containsAll(this)
override fun hashCode(): Int = left.hashCode() + element.hashCode()
override fun toString(): String =
"[" + fold("") { acc, element ->
if (acc.isEmpty()) element.toString() else "$acc, $element"
} + "]"
private fun writeReplace(): Any {
val n = size()
val elements = arrayOfNulls(n)
var index = 0
fold(Unit) { _, element -> elements[index++] = element }
check(index == n)
@Suppress("UNCHECKED_CAST")
return Serialized(elements as Array)
}
private class Serialized(val elements: Array) : Serializable {
companion object {
private const val serialVersionUID: Long = 0L
}
private fun readResolve(): Any = elements.fold(EmptyCoroutineContext, CoroutineContext::plus)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy