1
1
/*
2
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
2
+ * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3
3
*/
4
4
5
5
package kotlinx.coroutines.internal
@@ -11,13 +11,22 @@ import kotlin.coroutines.*
11
11
internal val NO_THREAD_ELEMENTS = Symbol (" NO_THREAD_ELEMENTS" )
12
12
13
13
// Used when there are >= 2 active elements in the context
14
- private class ThreadState (val context : CoroutineContext , n : Int ) {
15
- private var a = arrayOfNulls<Any >(n)
14
+ @Suppress(" UNCHECKED_CAST" )
15
+ private class ThreadState (@JvmField val context : CoroutineContext , n : Int ) {
16
+ private val values = arrayOfNulls<Any >(n)
17
+ private val elements = arrayOfNulls<ThreadContextElement <Any ?>>(n)
16
18
private var i = 0
17
19
18
- fun append (value : Any? ) { a[i++ ] = value }
19
- fun take () = a[i++ ]
20
- fun start () { i = 0 }
20
+ fun append (element : ThreadContextElement <* >, value : Any? ) {
21
+ values[i] = value
22
+ elements[i++ ] = element as ThreadContextElement <Any ?>
23
+ }
24
+
25
+ fun restore (context : CoroutineContext ) {
26
+ for (i in elements.indices.reversed()) {
27
+ elements[i]?.restoreThreadContext(context, values[i])
28
+ }
29
+ }
21
30
}
22
31
23
32
// Counts ThreadContextElements in the context
@@ -42,17 +51,7 @@ private val findOne =
42
51
private val updateState =
43
52
fun (state : ThreadState , element : CoroutineContext .Element ): ThreadState {
44
53
if (element is ThreadContextElement <* >) {
45
- state.append(element.updateThreadContext(state.context))
46
- }
47
- return state
48
- }
49
-
50
- // Restores state for all ThreadContextElements in the context from the given ThreadState
51
- private val restoreState =
52
- fun (state : ThreadState , element : CoroutineContext .Element ): ThreadState {
53
- @Suppress(" UNCHECKED_CAST" )
54
- if (element is ThreadContextElement <* >) {
55
- (element as ThreadContextElement <Any ?>).restoreThreadContext(state.context, state.take())
54
+ state.append(element, element.updateThreadContext(state.context))
56
55
}
57
56
return state
58
57
}
@@ -86,8 +85,7 @@ internal fun restoreThreadContext(context: CoroutineContext, oldState: Any?) {
86
85
oldState == = NO_THREAD_ELEMENTS -> return // very fast path when there are no ThreadContextElements
87
86
oldState is ThreadState -> {
88
87
// slow path with multiple stored ThreadContextElements
89
- oldState.start()
90
- context.fold(oldState, restoreState)
88
+ oldState.restore(context)
91
89
}
92
90
else -> {
93
91
// fast path for one ThreadContextElement, but need to find it
0 commit comments