overridefun<E : Element>get(key: Key<E>): 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] } } }
publicoverridefunminusKey(key: Key<*>): CoroutineContext { element[key]?.let { return left } val newLeft = left.minusKey(key) returnwhen { newLeft === left -> this newLeft === EmptyCoroutineContext -> element else -> CombinedContext(newLeft, element) } }
privatefunsize(): Int { var cur = this var size = 2 while (true) { cur = cur.left as? CombinedContext ?: return size size++ } }
privatefuncontains(element: Element): Boolean = get(element.key) == element
privatefuncontainsAll(context: CombinedContext): Boolean { var cur = context while (true) { if (!contains(cur.element)) returnfalse val next = cur.left if (next is CombinedContext) { cur = next } else { return contains(next as Element) } } }
overridefunequals(other: Any?): Boolean = this === other || other is CombinedContext && other.size() == size() && other.containsAll(this)
overridefunhashCode(): Int = left.hashCode() + element.hashCode()
overridefuntoString(): String = "[" + fold("") { acc, element -> if (acc.isEmpty()) element.toString() else"$acc, $element" } + "]"
privatefunwriteReplace(): Any { val n = size() val elements = arrayOfNulls<CoroutineContext>(n) var index = 0 fold(Unit) { _, element -> elements[index++] = element } check(index == n) @Suppress("UNCHECKED_CAST") return Serialized(elements as Array<CoroutineContext>) }
var leftoverContext = appendContext val folded = originalContext.fold<CoroutineContext>(EmptyCoroutineContext) { result, element -> if (element !is CopyableThreadContextElement<*>) return@fold result + element // 该元素会被覆盖吗? val newElement = leftoverContext[element.key] // 不,复制即可 if (newElement == null) { // 对于类似于 "withContext "的构建器,我们不会复制,因为元素不是共享的 return@fold result + if (isNewCoroutine) element.copyForChild() else element } // 是,那么首先从追加上下文中移除元素 leftoverContext = leftoverContext.minusKey(element.key) // 返回总和 @Suppress("UNCHECKED_CAST") return@fold result + (element as CopyableThreadContextElement<Any?>).mergeForChild(newElement) }
if (hasElementsRight) { leftoverContext = leftoverContext.fold<CoroutineContext>(EmptyCoroutineContext) { result, element -> // 我们正在添加新的上下文元素 -- 我们必须复制它,否则它可能会被其他人共享 if (element is CopyableThreadContextElement<*>) { return@fold result + element.copyForChild() } return@fold result + element } } return folded + leftoverContext }