@@ -6,7 +6,7 @@ import kotlin.coroutines.*
6
6
import kotlin.test.*
7
7
import kotlinx.coroutines.flow.*
8
8
9
- class ThreadContextElementTest : TestBase () {
9
+ class ThreadContextElementJvmTest : TestBase () {
10
10
11
11
@Test
12
12
fun testExample () = runTest {
@@ -15,23 +15,23 @@ class ThreadContextElementTest : TestBase() {
15
15
val mainThread = Thread .currentThread()
16
16
val data = MyData ()
17
17
val element = MyElement (data)
18
- assertNull(myThreadLocal .get())
18
+ assertNull(threadContextElementThreadLocal .get())
19
19
val job = GlobalScope .launch(element + exceptionHandler) {
20
20
assertTrue(mainThread != Thread .currentThread())
21
21
assertSame(element, coroutineContext[MyElement ])
22
- assertSame(data, myThreadLocal .get())
22
+ assertSame(data, threadContextElementThreadLocal .get())
23
23
withContext(mainDispatcher) {
24
24
assertSame(mainThread, Thread .currentThread())
25
25
assertSame(element, coroutineContext[MyElement ])
26
- assertSame(data, myThreadLocal .get())
26
+ assertSame(data, threadContextElementThreadLocal .get())
27
27
}
28
28
assertTrue(mainThread != Thread .currentThread())
29
29
assertSame(element, coroutineContext[MyElement ])
30
- assertSame(data, myThreadLocal .get())
30
+ assertSame(data, threadContextElementThreadLocal .get())
31
31
}
32
- assertNull(myThreadLocal .get())
32
+ assertNull(threadContextElementThreadLocal .get())
33
33
job.join()
34
- assertNull(myThreadLocal .get())
34
+ assertNull(threadContextElementThreadLocal .get())
35
35
}
36
36
37
37
@Test
@@ -43,13 +43,13 @@ class ThreadContextElementTest : TestBase() {
43
43
context = Dispatchers .Default + exceptionHandler + element,
44
44
start = CoroutineStart .UNDISPATCHED
45
45
) {
46
- assertSame(data, myThreadLocal .get())
46
+ assertSame(data, threadContextElementThreadLocal .get())
47
47
yield ()
48
- assertSame(data, myThreadLocal .get())
48
+ assertSame(data, threadContextElementThreadLocal .get())
49
49
}
50
- assertNull(myThreadLocal .get())
50
+ assertNull(threadContextElementThreadLocal .get())
51
51
job.join()
52
- assertNull(myThreadLocal .get())
52
+ assertNull(threadContextElementThreadLocal .get())
53
53
}
54
54
55
55
@Test
@@ -58,22 +58,22 @@ class ThreadContextElementTest : TestBase() {
58
58
newSingleThreadContext(" withContext" ).use {
59
59
val data = MyData ()
60
60
GlobalScope .async(Dispatchers .Default + MyElement (data)) {
61
- assertSame(data, myThreadLocal .get())
61
+ assertSame(data, threadContextElementThreadLocal .get())
62
62
expect(2 )
63
63
64
64
val newData = MyData ()
65
65
GlobalScope .async(it + MyElement (newData)) {
66
- assertSame(newData, myThreadLocal .get())
66
+ assertSame(newData, threadContextElementThreadLocal .get())
67
67
expect(3 )
68
68
}.await()
69
69
70
70
withContext(it + MyElement (newData)) {
71
- assertSame(newData, myThreadLocal .get())
71
+ assertSame(newData, threadContextElementThreadLocal .get())
72
72
expect(4 )
73
73
}
74
74
75
75
GlobalScope .async(it) {
76
- assertNull(myThreadLocal .get())
76
+ assertNull(threadContextElementThreadLocal .get())
77
77
expect(5 )
78
78
}.await()
79
79
@@ -126,31 +126,31 @@ class ThreadContextElementTest : TestBase() {
126
126
newFixedThreadPoolContext(nThreads = 4 , name = " withContext" ).use {
127
127
withContext(it + CopyForChildCoroutineElement (MyData ())) {
128
128
val forBlockData = MyData ()
129
- myThreadLocal .setForBlock(forBlockData) {
130
- assertSame(myThreadLocal .get(), forBlockData)
129
+ threadContextElementThreadLocal .setForBlock(forBlockData) {
130
+ assertSame(threadContextElementThreadLocal .get(), forBlockData)
131
131
launch {
132
- assertSame(myThreadLocal .get(), forBlockData)
132
+ assertSame(threadContextElementThreadLocal .get(), forBlockData)
133
133
}
134
134
launch {
135
- assertSame(myThreadLocal .get(), forBlockData)
135
+ assertSame(threadContextElementThreadLocal .get(), forBlockData)
136
136
// Modify value in child coroutine. Writes to the ThreadLocal and
137
137
// the (copied) ThreadLocalElement's memory are not visible to peer or
138
138
// ancestor coroutines, so this write is both threadsafe and coroutinesafe.
139
139
val innerCoroutineData = MyData ()
140
- myThreadLocal .setForBlock(innerCoroutineData) {
141
- assertSame(myThreadLocal .get(), innerCoroutineData)
140
+ threadContextElementThreadLocal .setForBlock(innerCoroutineData) {
141
+ assertSame(threadContextElementThreadLocal .get(), innerCoroutineData)
142
142
}
143
- assertSame(myThreadLocal .get(), forBlockData) // Asserts value was restored.
143
+ assertSame(threadContextElementThreadLocal .get(), forBlockData) // Asserts value was restored.
144
144
}
145
145
launch {
146
146
val innerCoroutineData = MyData ()
147
- myThreadLocal .setForBlock(innerCoroutineData) {
148
- assertSame(myThreadLocal .get(), innerCoroutineData)
147
+ threadContextElementThreadLocal .setForBlock(innerCoroutineData) {
148
+ assertSame(threadContextElementThreadLocal .get(), innerCoroutineData)
149
149
}
150
- assertSame(myThreadLocal .get(), forBlockData)
150
+ assertSame(threadContextElementThreadLocal .get(), forBlockData)
151
151
}
152
152
}
153
- assertNull(myThreadLocal .get()) // Asserts value was restored to its origin
153
+ assertNull(threadContextElementThreadLocal .get()) // Asserts value was restored to its origin
154
154
}
155
155
}
156
156
}
@@ -193,58 +193,31 @@ class ThreadContextElementTest : TestBase() {
193
193
@Test
194
194
fun testThreadLocalFlowOn () = runTest {
195
195
val myData = MyData ()
196
- myThreadLocal .set(myData)
196
+ threadContextElementThreadLocal .set(myData)
197
197
expect(1 )
198
198
flow {
199
- assertEquals(myData, myThreadLocal .get())
199
+ assertEquals(myData, threadContextElementThreadLocal .get())
200
200
emit(1 )
201
201
}
202
- .flowOn(myThreadLocal .asContextElement() + Dispatchers .Default )
202
+ .flowOn(threadContextElementThreadLocal .asContextElement() + Dispatchers .Default )
203
203
.single()
204
- myThreadLocal .set(null )
204
+ threadContextElementThreadLocal .set(null )
205
205
finish(2 )
206
206
}
207
207
}
208
208
209
- class MyData
210
-
211
- // declare thread local variable holding MyData
212
- private val myThreadLocal = ThreadLocal <MyData ?>()
213
-
214
- // declare context element holding MyData
215
- class MyElement (val data : MyData ) : ThreadContextElement<MyData?> {
216
- // declare companion object for a key of this element in coroutine context
217
- companion object Key : CoroutineContext.Key<MyElement>
218
-
219
- // provide the key of the corresponding context element
220
- override val key: CoroutineContext .Key <MyElement >
221
- get() = Key
222
-
223
- // this is invoked before coroutine is resumed on current thread
224
- override fun updateThreadContext (context : CoroutineContext ): MyData ? {
225
- val oldState = myThreadLocal.get()
226
- myThreadLocal.set(data)
227
- return oldState
228
- }
229
-
230
- // this is invoked after coroutine has suspended on current thread
231
- override fun restoreThreadContext (context : CoroutineContext , oldState : MyData ? ) {
232
- myThreadLocal.set(oldState)
233
- }
234
- }
235
-
236
209
/* *
237
210
* A [ThreadContextElement] that implements copy semantics in [copyForChild].
238
211
*/
239
- class CopyForChildCoroutineElement (val data : MyData ? ) : CopyableThreadContextElement<MyData?> {
212
+ internal class CopyForChildCoroutineElement (val data : MyData ? ) : CopyableThreadContextElement<MyData?> {
240
213
companion object Key : CoroutineContext.Key<CopyForChildCoroutineElement>
241
214
242
215
override val key: CoroutineContext .Key <CopyForChildCoroutineElement >
243
216
get() = Key
244
217
245
218
override fun updateThreadContext (context : CoroutineContext ): MyData ? {
246
- val oldState = myThreadLocal .get()
247
- myThreadLocal .set(data)
219
+ val oldState = threadContextElementThreadLocal .get()
220
+ threadContextElementThreadLocal .set(data)
248
221
return oldState
249
222
}
250
223
@@ -253,7 +226,7 @@ class CopyForChildCoroutineElement(val data: MyData?) : CopyableThreadContextEle
253
226
}
254
227
255
228
override fun restoreThreadContext (context : CoroutineContext , oldState : MyData ? ) {
256
- myThreadLocal .set(oldState)
229
+ threadContextElementThreadLocal .set(oldState)
257
230
}
258
231
259
232
/* *
@@ -268,7 +241,7 @@ class CopyForChildCoroutineElement(val data: MyData?) : CopyableThreadContextEle
268
241
* thread and calls [restoreThreadContext].
269
242
*/
270
243
override fun copyForChild (): CopyForChildCoroutineElement {
271
- return CopyForChildCoroutineElement (myThreadLocal .get())
244
+ return CopyForChildCoroutineElement (threadContextElementThreadLocal .get())
272
245
}
273
246
}
274
247
0 commit comments